Skip to content

Commit 5e39fdb

Browse files
committed
feat: Itemize, Enumerate
1 parent 0fb3e85 commit 5e39fdb

File tree

9 files changed

+297
-1
lines changed

9 files changed

+297
-1
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { Enumerate, Item, Itemize } from '@solved-ac/ui-react'
2+
import { ComponentMeta, ComponentStory } from '@storybook/react'
3+
import React from 'react'
4+
5+
export default {
6+
title: 'Components/Item/Enumerate',
7+
component: Enumerate,
8+
argTypes: {
9+
children: {
10+
control: 'none',
11+
description: 'The children to display inside the list',
12+
},
13+
},
14+
} as ComponentMeta<typeof Enumerate>
15+
16+
const Template: ComponentStory<typeof Enumerate> = (args) => (
17+
<Enumerate {...args} />
18+
)
19+
20+
export const Default = Template.bind({})
21+
Default.args = {
22+
children: (
23+
<>
24+
<Item>Item 1</Item>
25+
<Item>Item 2</Item>
26+
<Item>Item 3</Item>
27+
<Item>Item 4</Item>
28+
<Item>Item 5</Item>
29+
</>
30+
),
31+
}
32+
33+
export const Nested = Template.bind({})
34+
Nested.args = {
35+
children: (
36+
<>
37+
<Item>
38+
Item 1
39+
<Enumerate>
40+
<Item>Enumerated 1</Item>
41+
<Item>Enumerated 2</Item>
42+
<Item>Enumerated 3</Item>
43+
<Item>Enumerated 4</Item>
44+
</Enumerate>
45+
</Item>
46+
<Item>
47+
Item 2
48+
<Itemize>
49+
<Item>Item 2.1</Item>
50+
<Item>Item 2.2</Item>
51+
<Item>Item 2.3</Item>
52+
<Item>Item 2.4</Item>
53+
</Itemize>
54+
</Item>
55+
<Item>Item 3</Item>
56+
<Item>Item 4</Item>
57+
<Item>Item 5</Item>
58+
</>
59+
),
60+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Enumerate, Item, Itemize } from '@solved-ac/ui-react'
2+
import { ComponentMeta, ComponentStory } from '@storybook/react'
3+
import React from 'react'
4+
5+
export default {
6+
title: 'Components/Item/Itemize',
7+
component: Itemize,
8+
argTypes: {
9+
children: {
10+
control: 'none',
11+
description: 'The children to display inside the list',
12+
},
13+
marker: {
14+
control: {
15+
type: 'select',
16+
options: ['✓', '✗', '—'],
17+
},
18+
},
19+
},
20+
} as ComponentMeta<typeof Itemize>
21+
22+
const Template: ComponentStory<typeof Itemize> = (args) => <Itemize {...args} />
23+
24+
export const Default = Template.bind({})
25+
Default.args = {
26+
children: (
27+
<>
28+
<Item>Item 1</Item>
29+
<Item>Item 2</Item>
30+
<Item>Item 3</Item>
31+
<Item>Item 4</Item>
32+
<Item>Item 5</Item>
33+
</>
34+
),
35+
}
36+
37+
export const Nested = Template.bind({})
38+
Nested.args = {
39+
children: (
40+
<>
41+
<Item>
42+
Item 1
43+
<Enumerate>
44+
<Item>Enumerated 1</Item>
45+
<Item>Enumerated 2</Item>
46+
<Item>Enumerated 3</Item>
47+
<Item>Enumerated 4</Item>
48+
</Enumerate>
49+
</Item>
50+
<Item>
51+
Item 2
52+
<Itemize>
53+
<Item>Item 2.1</Item>
54+
<Item>Item 2.2</Item>
55+
<Item>Item 2.3</Item>
56+
<Item>Item 2.4</Item>
57+
</Itemize>
58+
</Item>
59+
<Item>Item 3</Item>
60+
<Item>Item 4</Item>
61+
<Item>Item 5</Item>
62+
</>
63+
),
64+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@solved-ac/ui-react",
3-
"version": "0.0.1-alpha.38",
3+
"version": "0.0.1-alpha.39",
44
"description": "React component library used by solved.ac",
55
"author": "shiftpsh",
66
"license": "MIT",

src/components/$Item/Enumerate.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React, { ElementType, useContext } from 'react'
2+
import styled from 'styled-components'
3+
import { PC, PP, PR } from '../../types/PolymorphicElementProps'
4+
import { ItemizeContext } from './ItemizeContext'
5+
6+
const marginMap = {
7+
none: '0',
8+
normal: '1em',
9+
wide: '2em',
10+
}
11+
12+
interface EnumerateContainerProps {
13+
marker: string
14+
margin: 'none' | 'normal' | 'wide'
15+
}
16+
17+
const EnumerateContainer = styled.ol<EnumerateContainerProps>`
18+
padding-inline-start: 4ch;
19+
margin-block-start: ${({ margin }) => marginMap[margin]};
20+
margin-block-end: ${({ margin }) => marginMap[margin]};
21+
margin-inline-start: 0;
22+
margin-inline-end: 0;
23+
list-style-type: ${({ marker }) => marker};
24+
& > li::marker {
25+
color: ${({ theme }) => theme.color.text.secondary.main};
26+
}
27+
`
28+
29+
export interface EnumerateProps {
30+
marker?: string
31+
margin?: 'none' | 'normal' | 'wide'
32+
}
33+
34+
export const Enumerate: PC<'ol', EnumerateProps> = React.forwardRef(
35+
<T extends ElementType>(props: PP<T, EnumerateProps>, ref?: PR<T>) => {
36+
const itemizeContext = useContext(ItemizeContext)
37+
const {
38+
margin = itemizeContext.level === 0 ? 'normal' : 'none',
39+
marker = 'decimal',
40+
as = 'ol',
41+
...rest
42+
} = props
43+
44+
return (
45+
<ItemizeContext.Provider
46+
value={{ marker, usesCounter: true, level: itemizeContext.level + 1 }}
47+
>
48+
<EnumerateContainer
49+
margin={margin}
50+
marker={marker}
51+
ref={ref}
52+
as={as}
53+
{...rest}
54+
/>
55+
</ItemizeContext.Provider>
56+
)
57+
}
58+
)

src/components/$Item/Item.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React, { ElementType, useContext } from 'react'
2+
import styled from 'styled-components'
3+
import { PC, PP, PR } from '../../types/PolymorphicElementProps'
4+
import { ItemizeContext } from './ItemizeContext'
5+
6+
interface ItemContainerProps {
7+
marker: string
8+
usesCounter: boolean
9+
}
10+
11+
const ItemContainer = styled.li<ItemContainerProps>`
12+
list-style-type: ${({ marker, usesCounter }) =>
13+
usesCounter ? marker : `'${marker} '`};
14+
& > li::marker {
15+
color: ${({ theme }) => theme.color.text.secondary.main};
16+
}
17+
`
18+
19+
export interface ItemProps {
20+
marker?: string
21+
}
22+
23+
export const Item: PC<'li', ItemProps> = React.forwardRef(
24+
<T extends ElementType>(props: PP<T, ItemProps>, ref?: PR<T>) => {
25+
const itemizeContext = useContext(ItemizeContext)
26+
const { marker = itemizeContext.marker, as = 'li', ...rest } = props
27+
28+
return (
29+
<ItemContainer
30+
ref={ref}
31+
as={as}
32+
marker={marker}
33+
usesCounter={itemizeContext.usesCounter}
34+
{...rest}
35+
/>
36+
)
37+
}
38+
)

src/components/$Item/Itemize.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React, { ElementType, useContext } from 'react'
2+
import styled from 'styled-components'
3+
import { PC, PP, PR } from '../../types/PolymorphicElementProps'
4+
import { ItemizeContext } from './ItemizeContext'
5+
6+
const marginMap = {
7+
none: '0',
8+
normal: '1em',
9+
wide: '2em',
10+
}
11+
12+
interface ItemizeContainerProps {
13+
marker: string
14+
margin: 'none' | 'normal' | 'wide'
15+
}
16+
17+
const ItemizeContainer = styled.ul<ItemizeContainerProps>`
18+
padding-inline-start: 4ch;
19+
margin-block-start: ${({ margin }) => marginMap[margin]};
20+
margin-block-end: ${({ margin }) => marginMap[margin]};
21+
margin-inline-start: 0;
22+
margin-inline-end: 0;
23+
list-style-type: '${({ marker }) => marker} ';
24+
& > li::marker {
25+
color: ${({ theme }) => theme.color.text.secondary.main};
26+
}
27+
`
28+
29+
export interface ItemizeProps {
30+
marker?: string
31+
margin?: 'none' | 'normal' | 'wide'
32+
}
33+
34+
export const Itemize: PC<'ul', ItemizeProps> = React.forwardRef(
35+
<T extends ElementType>(props: PP<T, ItemizeProps>, ref?: PR<T>) => {
36+
const itemizeContext = useContext(ItemizeContext)
37+
const {
38+
margin = itemizeContext.level === 0 ? 'normal' : 'none',
39+
marker = itemizeContext.level === 0 ? '✓' : '–',
40+
as = 'ul',
41+
...rest
42+
} = props
43+
44+
return (
45+
<ItemizeContext.Provider
46+
value={{ marker, usesCounter: false, level: itemizeContext.level + 1 }}
47+
>
48+
<ItemizeContainer
49+
margin={margin}
50+
marker={marker}
51+
ref={ref}
52+
as={as}
53+
{...rest}
54+
/>
55+
</ItemizeContext.Provider>
56+
)
57+
}
58+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react'
2+
3+
export interface ItemizeContextProps {
4+
level: number
5+
marker: string
6+
usesCounter: boolean
7+
}
8+
9+
export const ItemizeContext = React.createContext<ItemizeContextProps>({
10+
level: 0,
11+
marker: '✓',
12+
usesCounter: false,
13+
})

src/components/$Item/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './Enumerate'
2+
export * from './Item'
3+
export * from './Itemize'
4+

src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './$Item'
12
export * from './$List'
23
export * from './$Tab'
34
export * from './$Table'

0 commit comments

Comments
 (0)