Skip to content

Add list group component #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
HiBadgeCheck,
HiBell,
HiChevronDoubleRight,
HiClipboardList,
HiCollection,
HiCreditCard,
HiDuplicate,
Expand All @@ -24,6 +25,7 @@ const BreadcrumbPage = lazy(() => import('./pages/BreadcrumbPage'));
const ButtonsPage = lazy(() => import('./pages/ButtonsPage'));
const CardPage = lazy(() => import('./pages/CardPage'));
const CarouselPage = lazy(() => import('./pages/CarouselPage'));
const ListGroupPage = lazy(() => import('./pages/ListGroupPage'));
const SpinnersPage = lazy(() => import('./pages/SpinnersPage'));
const TooltipsPage = lazy(() => import('./pages/TooltipsPage'));

Expand Down Expand Up @@ -79,6 +81,12 @@ export const Root: FC = () => {
title: 'Carousel',
href: '/carousel',
},
{
group: false,
icon: HiClipboardList,
title: 'List group',
href: '/list-group',
},
{
group: false,
icon: FaSpinner,
Expand Down Expand Up @@ -135,6 +143,7 @@ export const Root: FC = () => {
<Route path="buttons" element={<ButtonsPage />} />
<Route path="card" element={<CardPage />} />
<Route path="carousel" element={<CarouselPage />} />
<Route path="list-group" element={<ListGroupPage />} />
<Route path="spinners" element={<SpinnersPage />} />
<Route path="tooltips" element={<TooltipsPage />} />
</Routes>
Expand Down
55 changes: 55 additions & 0 deletions src/components/ListGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ComponentProps, FC, Fragment, ReactNode } from 'react';
import classNames from 'classnames';

export type ListGroupProps = {
items: ListGroupItem[];
};
export type ListGroupItem = {
title: ReactNode;
link?: string;
icon?: FC<ComponentProps<'svg'>>;
active?: boolean;
onClick?: () => void;
disabled?: boolean;
};

export const ListGroup: FC<ListGroupProps> = ({ items }) => {
return (
<div className="w-48 list-none divide-y divide-gray-200 rounded-lg border border-gray-200 bg-white text-sm font-medium text-gray-900 dark:divide-gray-600 dark:border-gray-600 dark:bg-gray-700 dark:text-white">
{items.map((item, index) => (
<Fragment key={index}>
{!item.link ? (
<button
onClick={item.onClick}
className={classNames(
'flex w-full items-center gap-2 py-2 px-4 text-left text-sm font-medium first:rounded-t-lg last:rounded-b-lg',
{
'!bg-blue-700 text-white': item.active,
'hover:bg-gray-100 hover:text-blue-700 dark:hover:bg-gray-600 dark:hover:text-white': !item.active,
},
)}
type="button"
>
{item.icon && <item.icon />}
{item.title}
</button>
) : (
<a
href={item.link}
aria-current="false"
className={classNames(
'block w-full cursor-pointer py-2 px-4 first:rounded-t-lg last:rounded-b-lg focus:outline-none dark:bg-gray-800',
{
'!bg-blue-700 text-white': item.active,
'hover:bg-gray-100 hover:text-blue-700 dark:hover:bg-gray-600 dark:hover:text-white': !item.active,
},
)}
>
{item.title}
</a>
)}
</Fragment>
))}
</div>
);
};
87 changes: 87 additions & 0 deletions src/pages/ListGroupPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { FC } from 'react';
import { ListGroup, ListGroupItem } from '../components/ListGroup';
import { CodeExample, DemoPage } from './DemoPage';
import { HiCloudDownload, HiInbox, HiOutlineAdjustments, HiUserCircle } from 'react-icons/hi';

const ListGroupPage: FC = () => {
const defaultItems: ListGroupItem[] = [
{
title: 'Profile',
},
{
title: 'Settings',
},
{
title: 'Messages',
},
{
title: 'Download',
},
];

const itemsWithLinks: ListGroupItem[] = [
{
title: 'Profile',
link: '#/list-group',
active: true,
},
{
title: 'Settings',
link: '#/list-group',
},
{
title: 'Messages',
link: '#/list-group',
},
{
title: 'Download',
link: '#/list-group',
},
];

const itemsWithIcons: ListGroupItem[] = [
{
title: 'Profile',
icon: HiUserCircle,
onClick: () => alert('profile'),
},
{
title: 'Settings',
icon: HiOutlineAdjustments,
},
{
title: 'Messages',
icon: HiInbox,
},
{
title: 'Download',
icon: HiCloudDownload,
},
];

const examples: CodeExample[] = [
{
title: 'Default list',
code: <ListGroup items={defaultItems} />,
},
{
title: 'List group with links',
code: <ListGroup items={itemsWithLinks} />,
},
{
title: 'List group with buttons',
code: <ListGroup items={itemsWithLinks} />,
},
{
title: 'List group with icons',
code: <ListGroup items={itemsWithIcons} />,
codeStringifierOptions: {
functionValue: (fn) => (fn.name === 'onClick' ? fn : fn.name),
},
},
];

return <DemoPage examples={examples} />;
};

export default ListGroupPage;