Skip to content

Commit c6af433

Browse files
committed
feat: TextField, Paragraph
1 parent b8f6745 commit c6af433

File tree

9 files changed

+212
-29
lines changed

9 files changed

+212
-29
lines changed

.vscode/launch.json

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Paragraph } from '@solved-ac/ui-react'
2+
import { ComponentMeta, ComponentStory } from '@storybook/react'
3+
import React from 'react'
4+
5+
export default {
6+
title: 'Components/Paragraph',
7+
component: Paragraph,
8+
argTypes: {
9+
children: {
10+
control: 'none',
11+
description: 'Children to display',
12+
},
13+
margin: {
14+
control: { type: 'select', options: ['none', 'normal', 'wide'] },
15+
description: 'The margin of the paragraph',
16+
},
17+
as: {
18+
control: { type: 'select', options: ['div', 'span', 'button', 'a'] },
19+
description: 'The element to render the paragraph as',
20+
},
21+
},
22+
} as ComponentMeta<typeof Paragraph>
23+
24+
const Template: ComponentStory<typeof Paragraph> = (args) => (
25+
<Paragraph {...args} />
26+
)
27+
28+
export const Default = Template.bind({})
29+
Default.args = {
30+
children: (
31+
<>
32+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec
33+
vulputate arcu, nec semper est. Vestibulum ante ipsum primis in faucibus
34+
orci luctus et ultrices posuere cubilia curae; Suspendisse vel purus et
35+
metus laoreet efficitur in ut elit. Duis ultrices enim dapibus purus
36+
imperdiet molestie. Nam pretium odio metus, tempus vehicula neque sodales
37+
quis. Suspendisse vehicula, libero ac viverra consectetur, ante lectus
38+
malesuada ex, ut porta nunc justo quis neque. Aenean tristique nulla quis
39+
eros faucibus, sit amet lacinia nibh interdum. Quisque aliquet leo ut erat
40+
ultrices posuere. Duis mauris nulla, posuere sed dapibus eget, ultricies
41+
id dui. Phasellus vel augue a urna fermentum vehicula. Quisque sed elit
42+
non nibh ullamcorper lacinia. Orci varius natoque penatibus et magnis dis
43+
parturient montes, nascetur ridiculus mus. Duis nibh ligula, scelerisque
44+
porta rutrum ac, tempus vitae ipsum. Morbi ut ante a felis fringilla
45+
aliquam bibendum nec felis. Donec vel nunc congue, rhoncus mauris quis,
46+
malesuada nisi.
47+
</>
48+
),
49+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { TextField } from '@solved-ac/ui-react'
2+
import { ComponentMeta, ComponentStory } from '@storybook/react'
3+
import React from 'react'
4+
5+
export default {
6+
title: 'Components/TextField',
7+
component: TextField,
8+
argTypes: {
9+
value: {
10+
control: 'text',
11+
description: 'The value of the text field',
12+
},
13+
fullWidth: {
14+
control: 'boolean',
15+
description: 'Whether the text field should be full width',
16+
},
17+
disabled: {
18+
control: 'boolean',
19+
description: 'Whether the text field should be disabled',
20+
},
21+
multiline: {
22+
control: 'boolean',
23+
description: 'Whether the text field should be multiline',
24+
},
25+
resizable: {
26+
control: {
27+
type: 'select',
28+
options: ['none', 'both', 'horizontal', 'vertical'],
29+
},
30+
description: 'Whether the text field should be resizable',
31+
},
32+
},
33+
} as ComponentMeta<typeof TextField>
34+
35+
const Template: ComponentStory<typeof TextField> = (args) => (
36+
<TextField {...args} />
37+
)
38+
39+
export const Default = Template.bind({})
40+
Default.args = {
41+
value: 'TextField',
42+
}

src/components/Paragraph.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React, { ElementType } from 'react'
2+
import styled from 'styled-components'
3+
import { PC, PP, PR } from '../types/PolymorphicElementProps'
4+
5+
const marginMap = {
6+
none: '0',
7+
normal: '1em',
8+
wide: '2em',
9+
}
10+
11+
interface ParagraphContainerProps {
12+
margin: 'none' | 'normal' | 'wide'
13+
}
14+
15+
const ParagraphContainer = styled.p<ParagraphContainerProps>`
16+
margin-block-start: ${({ margin }) => marginMap[margin]};
17+
margin-block-end: ${({ margin }) => marginMap[margin]};
18+
margin-inline-start: 0;
19+
margin-inline-end: 0;
20+
`
21+
22+
export interface ParagraphProps {
23+
margin?: 'none' | 'normal' | 'wide'
24+
}
25+
26+
export const Paragraph: PC<'p', ParagraphProps> = React.forwardRef(
27+
<T extends ElementType>(props: PP<T, ParagraphProps>, ref?: PR<T>) => {
28+
const { margin = 'normal', as = 'p', ...rest } = props
29+
30+
return <ParagraphContainer ref={ref} as={as} margin={margin} {...rest} />
31+
}
32+
)

src/components/Tab/Tab.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const TabContainer = styled.button<TabContainerProps>`
4444
border-color 0.3s ease;
4545
background: ${v.backgroundColor};
4646
color: ${v.textColor};
47+
vertical-align: bottom;
4748
&:not([disabled]):hover,
4849
&:not([disabled]):active {
4950
color: ${v.hoverTextColor};

src/components/TextField.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React, { ElementType } from 'react'
2+
import styled from 'styled-components'
3+
import { PC, PP, PR } from '../types/PolymorphicElementProps'
4+
import { cssDisablable } from '../utils/styles'
5+
6+
interface TextFieldContainerProps {
7+
fullWidth: boolean
8+
resizable: 'none' | 'both' | 'horizontal' | 'vertical'
9+
}
10+
11+
const TextFieldContainer = styled.input<TextFieldContainerProps>`
12+
${cssDisablable}
13+
font-family: inherit;
14+
height: auto;
15+
line-height: normal;
16+
font-size: 1rem;
17+
padding: 0.8em 0.5em;
18+
background: ${({ theme }) => theme.color.background.footer};
19+
color: ${({ theme }) => theme.color.text.primary.main};
20+
border: ${({ theme }) => theme.styles.border()};
21+
border-radius: 8px;
22+
width: ${({ fullWidth }) => (fullWidth ? '100%' : 'auto')};
23+
resize: ${({ resizable }) => resizable};
24+
`
25+
26+
export interface TextFieldProps {
27+
fullWidth?: boolean
28+
multiline?: boolean
29+
disabled?: boolean
30+
resizable?: 'none' | 'both' | 'horizontal' | 'vertical' | boolean
31+
}
32+
33+
const getResizable = (
34+
resizable: TextFieldProps['resizable']
35+
): 'none' | 'both' | 'horizontal' | 'vertical' => {
36+
if (typeof resizable === 'boolean') {
37+
return resizable ? 'both' : 'none'
38+
}
39+
if (!resizable) {
40+
return 'none'
41+
}
42+
return resizable
43+
}
44+
45+
export const TextField: PC<'input', TextFieldProps> = React.forwardRef(
46+
<T extends ElementType>(props: PP<T, TextFieldProps>, ref?: PR<T>) => {
47+
const {
48+
fullWidth = false,
49+
multiline = false,
50+
disabled = false,
51+
resizable = false,
52+
as,
53+
...rest
54+
} = props
55+
56+
// TODO types are wrong when `as` is inferred by variant
57+
const calculatedAs = as || (multiline ? 'textarea' : 'input')
58+
59+
return (
60+
<TextFieldContainer
61+
fullWidth={fullWidth}
62+
disabled={disabled}
63+
resizable={getResizable(resizable)}
64+
ref={ref}
65+
as={calculatedAs}
66+
{...rest}
67+
/>
68+
)
69+
}
70+
)

src/components/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ export * from './Footer'
1010
export * from './List'
1111
export * from './NavBar'
1212
export * from './PaginationItem'
13+
export * from './Paragraph'
1314
export * from './Space'
1415
export * from './Tab'
1516
export * from './Table'
17+
export * from './TextField'
1618
export * from './Typo'
1719

src/styles/GlobalStyles.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,15 @@ export const SolvedGlobalStyles = createGlobalStyle<{ theme: SolvedTheme }>`
9494
font-family: ${({ theme }) => theme.typography.code};
9595
}
9696
97+
/* @keepallvillain */
98+
:lang(ko) {
99+
h1, h2, h3 {
100+
word-break: keep-all;
101+
}
102+
}
103+
97104
${textInputs()} {
98-
font-family: inherit;
99-
height: auto;
100-
line-height: normal;
101-
font-size: 1rem;
102-
width: 100%;
103-
padding: 0.8em 0.5em;
104-
background: ${({ theme }) => theme.color.background.footer};
105-
color: ${({ theme }) => theme.color.text.primary.main};
106-
border: ${({ theme }) => theme.styles.border()};
107-
border-radius: 8px;
105+
font: inherit;
108106
}
109107
110108
${buttons()} {

src/utils/styles.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,16 @@ export const cssCentering = css`
7777
justify-content: center;
7878
`
7979

80-
export const cssClickable = css`
81-
text-decoration: none;
82-
cursor: pointer;
83-
user-select: none;
80+
export const cssDisablable = css`
8481
&:disabled {
8582
cursor: not-allowed;
8683
opacity: 0.5;
8784
}
8885
`
86+
87+
export const cssClickable = css`
88+
text-decoration: none;
89+
cursor: pointer;
90+
user-select: none;
91+
${cssDisablable}
92+
`

0 commit comments

Comments
 (0)