Skip to content

Commit f702e51

Browse files
feat(list): ✨ add list & list item comp (#110)
1 parent 17d1342 commit f702e51

File tree

10 files changed

+837
-390
lines changed

10 files changed

+837
-390
lines changed

package.json

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -74,34 +74,34 @@
7474
"reakit": "^1.3.6"
7575
},
7676
"devDependencies": {
77-
"@babel/cli": "7.13.10",
78-
"@babel/core": "^7.13.10",
77+
"@babel/cli": "7.13.14",
78+
"@babel/core": "^7.13.14",
7979
"@babel/plugin-proposal-class-properties": "7.13.0",
8080
"@babel/preset-env": "7.13.12",
81-
"@babel/preset-react": "7.12.13",
81+
"@babel/preset-react": "7.13.13",
8282
"@babel/preset-typescript": "7.13.0",
83-
"@commitlint/cli": "^12.1.0",
84-
"@commitlint/config-conventional": "^12.1.0",
85-
"@storybook/addon-a11y": "^6.2.0-rc.8",
86-
"@storybook/addon-actions": "^6.2.0-rc.8",
87-
"@storybook/addon-essentials": "^6.2.0-rc.8",
88-
"@storybook/addon-links": "^6.2.0-rc.8",
83+
"@commitlint/cli": "^12.0.1",
84+
"@commitlint/config-conventional": "^12.0.1",
85+
"@storybook/addon-a11y": "^6.2.1",
86+
"@storybook/addon-actions": "^6.2.1",
87+
"@storybook/addon-essentials": "^6.2.1",
88+
"@storybook/addon-links": "^6.2.1",
8989
"@storybook/addon-postcss": "^2.0.0",
90-
"@storybook/react": "^6.2.0-rc.8",
90+
"@storybook/react": "^6.2.1",
9191
"@tailwindcss/jit": "^0.1.7",
92-
"@testing-library/dom": "^7.30.0",
93-
"@testing-library/jest-dom": "^5.11.9",
94-
"@testing-library/react": "^11.2.5",
95-
"@testing-library/react-hooks": "^5.1.0",
96-
"@testing-library/user-event": "^13.0.7",
97-
"@types/jest": "^26.0.21",
92+
"@testing-library/dom": "^7.30.2",
93+
"@testing-library/jest-dom": "^5.11.10",
94+
"@testing-library/react": "^11.2.6",
95+
"@testing-library/react-hooks": "^5.1.1",
96+
"@testing-library/user-event": "^13.1.1",
97+
"@types/jest": "^26.0.22",
9898
"@types/jest-axe": "^3.5.1",
99-
"@types/node": "^14.14.35",
99+
"@types/node": "^14.14.37",
100100
"@types/react": "^17.0.3",
101101
"@types/react-dom": "^17.0.3",
102102
"@types/testing-library__jest-dom": "^5.9.5",
103-
"@typescript-eslint/eslint-plugin": "^4.19.0",
104-
"@typescript-eslint/parser": "^4.19.0",
103+
"@typescript-eslint/eslint-plugin": "^4.20.0",
104+
"@typescript-eslint/parser": "^4.20.0",
105105
"all-contributors-cli": "^6.20.0",
106106
"autoprefixer": "10.2.5",
107107
"babel-eslint": "^10.1.0",
@@ -113,25 +113,25 @@
113113
"cross-env": "^7.0.3",
114114
"date-fns": "^2.19.0",
115115
"deepmerge": "^4.2.2",
116-
"eslint": "^7.22.0",
116+
"eslint": "^7.23.0",
117117
"eslint-config-prettier": "^8.1.0",
118118
"eslint-config-react-app": "^6.0.0",
119119
"eslint-plugin-flowtype": "^5.4.0",
120120
"eslint-plugin-import": "^2.22.1",
121121
"eslint-plugin-jest": "^24.3.2",
122122
"eslint-plugin-jsx-a11y": "^6.4.1",
123123
"eslint-plugin-prettier": "^3.3.1",
124-
"eslint-plugin-react": "^7.23.0",
124+
"eslint-plugin-react": "^7.23.1",
125125
"eslint-plugin-react-hooks": "^4.2.0",
126126
"eslint-plugin-testing-library": "^3.10.2",
127127
"gacp": "^2.10.2",
128-
"husky": "^5.2.0",
128+
"husky": "^6.0.0",
129129
"jest": "^26.6.3",
130130
"jest-axe": "^4.1.0",
131131
"lint-staged": "^10.5.4",
132132
"patch-package": "^6.4.7",
133133
"pinst": "^2.1.6",
134-
"postcss": "^8.2.8",
134+
"postcss": "^8.2.9",
135135
"postcss-cli": "^8.3.1",
136136
"prettier": "^2.2.1",
137137
"react": "^17.0.2",

src/index.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@ export * from "./calendar";
77
export * from "./checkbox";
88
export * from "./circular-progress";
99
export * from "./datepicker";
10+
export * from "./form-field";
1011
export * from "./hooks";
1112
export * from "./icon";
1213
export * from "./icons";
14+
export * from "./input";
15+
export * from "./list";
1316
export * from "./progress";
1417
export * from "./radio";
1518
export * from "./slider";
1619
export * from "./spinner";
1720
export * from "./switch";
1821
export * from "./tag";
19-
export * from "./form-field";
20-
export * from "./toast";
21-
export * from "./tooltip";
22+
export * from "./textarea";
2223
export * from "./theme";
2324
export * from "./theme/types";
25+
export * from "./toast";
26+
export * from "./tooltip";
2427
export * from "./utils";

src/list/List.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import * as React from "react";
2+
import { cx } from "@renderlesskit/react";
3+
4+
import { useTheme } from "../theme";
5+
import { Box, BoxProps } from "../box";
6+
import { createContext } from "../utils";
7+
import { forwardRefWithAs } from "../utils/types";
8+
9+
export type ListContext = {
10+
size?: keyof Renderlesskit.GetThemeValue<"list", "size">;
11+
};
12+
13+
const [ListProvider, useListContext] = createContext<ListContext>({
14+
name: "ListContext",
15+
errorMessage:
16+
"useListContext: `context` is undefined. Seems you forgot to wrap List components in `<List />`",
17+
});
18+
19+
export { ListProvider, useListContext };
20+
21+
export type ListProps = BoxProps & ListContext & {};
22+
23+
export const List = forwardRefWithAs<ListProps, HTMLUListElement, "ul">(
24+
(props, ref) => {
25+
const { size = "md", className, ...rest } = props;
26+
27+
const theme = useTheme();
28+
const listStyles = cx(theme.list.base, theme.list.size[size], className);
29+
30+
return (
31+
<ListProvider value={{ size }}>
32+
<Box as="ul" role="list" ref={ref} className={listStyles} {...rest} />
33+
</ListProvider>
34+
);
35+
},
36+
);
37+
38+
List.displayName = "List";
39+
40+
export default List;
41+
42+
export const UnorderedList = forwardRefWithAs<
43+
ListProps,
44+
HTMLUListElement,
45+
"ul"
46+
>((props, ref) => {
47+
const { className, ...rest } = props;
48+
49+
const theme = useTheme();
50+
const unorderedListStyles = cx(theme.list.ul, className);
51+
52+
return <List ref={ref} className={unorderedListStyles} {...rest} />;
53+
});
54+
55+
UnorderedList.displayName = "UnorderedList";
56+
57+
export const OrderedList = forwardRefWithAs<ListProps, HTMLOListElement, "ol">(
58+
(props, ref) => {
59+
const { className, ...rest } = props;
60+
61+
const theme = useTheme();
62+
const orderedListStyles = cx(theme.list.ol, className);
63+
64+
return <List as="ol" ref={ref} className={orderedListStyles} {...rest} />;
65+
},
66+
);
67+
68+
OrderedList.displayName = "OrderedList";

src/list/ListIcon.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import * as React from "react";
2+
import { cx } from "@renderlesskit/react";
3+
4+
import { useTheme } from "../theme";
5+
import { Box, BoxProps } from "../box";
6+
import { useListContext } from "./List";
7+
import { forwardRefWithAs } from "../utils/types";
8+
9+
export type ListIconProps = BoxProps & {};
10+
11+
export const ListIcon = forwardRefWithAs<
12+
ListIconProps,
13+
HTMLSpanElement,
14+
"span"
15+
>((props, ref) => {
16+
const { className, ...rest } = props;
17+
const { size = "md" } = useListContext();
18+
19+
const theme = useTheme();
20+
const listIconStyles = cx(
21+
theme.list.icon.base,
22+
theme.list.icon.size[size],
23+
className,
24+
);
25+
26+
return (
27+
<Box
28+
as="span"
29+
ref={ref}
30+
role="presentation"
31+
className={listIconStyles}
32+
{...rest}
33+
/>
34+
);
35+
});
36+
37+
ListIcon.displayName = "ListIcon";
38+
39+
export default ListIcon;

src/list/ListItem.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as React from "react";
2+
import { cx } from "@renderlesskit/react";
3+
4+
import { useTheme } from "../theme";
5+
import { Box, BoxProps } from "../box";
6+
import { forwardRefWithAs } from "../utils/types";
7+
8+
export type ListItemProps = BoxProps & {};
9+
10+
export const ListItem = forwardRefWithAs<ListItemProps, HTMLLIElement, "li">(
11+
(props, ref) => {
12+
const { className, ...rest } = props;
13+
14+
const theme = useTheme();
15+
const listItemStyles = cx(theme.list.item, className);
16+
17+
return <Box as="li" ref={ref} className={listItemStyles} {...rest} />;
18+
},
19+
);
20+
21+
ListItem.displayName = "ListItem";
22+
23+
export default ListItem;

src/list/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from "./List";
2+
export * from "./ListItem";
3+
export * from "./ListIcon";

src/list/stories/List.stories.tsx

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import React from "react";
2+
import { Meta } from "@storybook/react/types-6-0";
3+
4+
import {
5+
createUnionControl,
6+
storyTemplate,
7+
} from "../../../.storybook/storybookUtils";
8+
import { InfoCircleIcon } from "../../icons";
9+
import {
10+
List,
11+
ListItem,
12+
ListIcon,
13+
UnorderedList,
14+
OrderedList,
15+
ListProps,
16+
} from "../index";
17+
18+
export default {
19+
title: "Primitives/List",
20+
component: List,
21+
argTypes: { size: createUnionControl(["sm", "md", "lg"]) },
22+
} as Meta;
23+
24+
const ul = storyTemplate<ListProps>(
25+
args => {
26+
return (
27+
<UnorderedList {...args}>
28+
<ListItem>This is the 1st ListItem</ListItem>
29+
<ListItem>This is the 2nd ListItem</ListItem>
30+
<ListItem>This is the 3rd ListItem</ListItem>
31+
</UnorderedList>
32+
);
33+
},
34+
{ size: "md" },
35+
);
36+
37+
export const ULSmall = ul({ size: "sm" });
38+
export const ULMedium = ul({});
39+
export const ULLarge = ul({ size: "lg" });
40+
41+
const ol = storyTemplate<ListProps>(
42+
args => {
43+
return (
44+
<OrderedList {...args}>
45+
<ListItem>This is the 1st ListItem</ListItem>
46+
<ListItem>This is the 2nd ListItem</ListItem>
47+
<ListItem>This is the 3rd ListItem</ListItem>
48+
</OrderedList>
49+
);
50+
},
51+
{ size: "md" },
52+
);
53+
54+
export const OLSmall = ol({ size: "sm" });
55+
export const OLMedium = ol({});
56+
export const OLLarge = ol({ size: "lg" });
57+
58+
export const NestedUL = () => {
59+
return (
60+
<UnorderedList>
61+
<ListItem>
62+
This is the 1st ListItem
63+
<UnorderedList>
64+
<ListItem>This is the nested 1st ListItem</ListItem>
65+
<ListItem>This is the nested 2nd ListItem</ListItem>
66+
<ListItem>This is the nested 3rd ListItem</ListItem>
67+
</UnorderedList>
68+
</ListItem>
69+
<ListItem>This is the 2nd ListItem</ListItem>
70+
<ListItem>This is the 3rd ListItem</ListItem>
71+
</UnorderedList>
72+
);
73+
};
74+
75+
export const NestedOL = () => {
76+
return (
77+
<OrderedList>
78+
<ListItem>
79+
This is the 1st ListItem
80+
<OrderedList>
81+
<ListItem>This is the nested 1st ListItem</ListItem>
82+
<ListItem>This is the nested 2nd ListItem</ListItem>
83+
<ListItem>This is the nested 3rd ListItem</ListItem>
84+
</OrderedList>
85+
</ListItem>
86+
<ListItem>This is the 2nd ListItem</ListItem>
87+
<ListItem>This is the 3rd ListItem</ListItem>
88+
</OrderedList>
89+
);
90+
};
91+
92+
export const CustomMarker = () => {
93+
return (
94+
<List size="lg">
95+
<ListItem>
96+
<ListIcon children={<InfoCircleIcon />} />
97+
This is the 1st ListItem
98+
<List size="lg" className="ml-[1em]">
99+
<ListItem>
100+
<ListIcon children={<InfoCircleIcon />} />
101+
This is the 1st ListItem
102+
</ListItem>
103+
<ListItem>
104+
<ListIcon children={<InfoCircleIcon />} />
105+
This is the 2nd ListItem
106+
</ListItem>
107+
<ListItem>
108+
<ListIcon children={<InfoCircleIcon />} />
109+
This is the 3rd ListItem
110+
</ListItem>
111+
</List>
112+
</ListItem>
113+
<ListItem>
114+
<ListIcon children={<InfoCircleIcon />} />
115+
This is the 2nd ListItem
116+
</ListItem>
117+
<ListItem>
118+
<ListIcon children={<InfoCircleIcon />} />
119+
This is the 3rd ListItem
120+
</ListItem>
121+
</List>
122+
);
123+
};

0 commit comments

Comments
 (0)