Skip to content

Commit

Permalink
feat(lists component): add new with-icon state (#1304)
Browse files Browse the repository at this point in the history
* feat(lists component): add new with-icon state

* style(list.mdx): grammatical accuracy
  • Loading branch information
paghar committed Mar 19, 2024
1 parent 83396e8 commit 60aa2f4
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 9 deletions.
8 changes: 7 additions & 1 deletion content/docs/typography/list.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ Use this example to create a default unordered list of items using the `List` co

<Example name="list.root" />

## Icons

This example can be used to apply custom icons instead of the default bullets for the list items.

<Example name="list.icon" />

## Nested

Use this example to nested another list of items inside the parent list element.
Use this example to nest another list of items inside the parent list element.

<Example name="list.nested" />

Expand Down
1 change: 1 addition & 0 deletions examples/list/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { nested } from './list.nested';
export { ordered } from './list.ordered';
export { icon } from './list.icon';
export { root } from './list.root';
export { unstyled } from './list.unstyled';
export { horizontal } from './list.horizontal';
63 changes: 63 additions & 0 deletions examples/list/list.icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { type CodeData } from '~/components/code-demo';
import { List, ListItem } from '~/src';
import { HiCheckCircle } from 'react-icons/hi';

const code = `
'use client';
import { List } from 'flowbite-react';
import { HiCheckCircle } from 'react-icons/hi';
function Component() {
return (
<List>
<List.Item icon={HiCheckCircle}>At least 10 characters (and up to 100 characters)</List.Item>
<List.Item icon={HiCheckCircle}>At least one lowercase character</List.Item>
<List.Item icon={HiCheckCircle}>Inclusion of at least one special character, e.g., ! @ # ?</List.Item>
</List>
);
}
`;

const codeRSC = `
import { List, ListItem } from 'flowbite-react';
import { HiCheckCircle } from 'react-icons/hi';
function Component() {
return (
<List>
<ListItem icon={HiCheckCircle}>At least 10 characters (and up to 100 characters)</ListItem>
<ListItem icon={HiCheckCircle}>At least one lowercase character</ListItem>
<ListItem icon={HiCheckCircle}>Inclusion of at least one special character, e.g., ! @ # ?</ListItem>
</List>
);
}
`;

function Component() {
return (
<List>
<ListItem icon={HiCheckCircle}>At least 10 characters (and up to 100 characters)</ListItem>
<ListItem icon={HiCheckCircle}>At least one lowercase character</ListItem>
<ListItem icon={HiCheckCircle}>Inclusion of at least one special character, e.g., ! @ # ?</ListItem>
</List>
);
}

export const icon: CodeData = {
type: 'single',
code: [
{
fileName: 'client',
language: 'tsx',
code,
},
{
fileName: 'server',
language: 'tsx',
code: codeRSC,
},
],
githubSlug: 'list/list.icon.tsx',
component: <Component />,
};
3 changes: 2 additions & 1 deletion src/components/List/List.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import type { ComponentProps, FC, PropsWithChildren } from 'react';
import { twMerge } from 'tailwind-merge';
import type { FlowbiteStateColors } from '../..';
import type { FlowbiteListItemTheme, FlowbiteStateColors } from '../..';
import { mergeDeep } from '../../helpers/merge-deep';
import { getTheme } from '../../theme-store';
import type { DeepPartial } from '../../types';
import { ListItem } from './ListItem';

export interface FlowbiteListTheme {
root: FlowbiteListRootTheme;
item: FlowbiteListItemTheme;
}

export interface FlowbiteListRootTheme {
Expand Down
24 changes: 17 additions & 7 deletions src/components/List/ListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
import type { FC, PropsWithChildren } from 'react';
import type { ComponentProps, FC } from 'react';
import { twMerge } from 'tailwind-merge';
import { mergeDeep } from '../../helpers/merge-deep';
import { getTheme } from '../../theme-store';
import type { DeepPartial } from '../../types';

export interface FlowbiteListItemTheme {
base: string;
icon: string;
withIcon: {
on: string;
off: string;
};
}

export interface ListItemProps extends PropsWithChildren {
theme?: DeepPartial<FlowbiteListItemTheme>;
export interface ListItemProps extends ComponentProps<'li'> {
className?: string;
icon?: FC<ComponentProps<'svg'>>;
theme?: DeepPartial<FlowbiteListItemTheme>;
}

export const ListItem: FC<ListItemProps> = ({ children, className, theme: customTheme = {} }) => {
const theme = mergeDeep(getTheme().listGroup.item, customTheme);
export const ListItem: FC<ListItemProps> = ({ children, className, icon: Icon, theme: customTheme = {}, ...props }) => {
const theme = mergeDeep(getTheme().list.item, customTheme);

return <li className={twMerge(theme.base, className)}>{children}</li>;
return (
<li className={twMerge(theme.withIcon[Icon ? 'on' : 'off'], className)} {...props}>
{Icon && <Icon className={twMerge(theme.icon)} />}
{children}
</li>
);
};
7 changes: 7 additions & 0 deletions src/components/List/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ export const listTheme: FlowbiteListTheme = {
unstyled: 'list-none',
nested: 'ps-5 mt-2',
},
item: {
withIcon: {
off: '',
on: 'flex items-center',
},
icon: 'w-3.5 h-3.5 me-2 flex-shrink-0',
},
};

0 comments on commit 60aa2f4

Please sign in to comment.