@spies-ui/react 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +3 -0
- package/.turbo/turbo-build.log +18 -0
- package/CHANGELOG.md +7 -0
- package/dist/index.d.mts +1790 -0
- package/dist/index.d.ts +1790 -0
- package/dist/index.js +777 -0
- package/dist/index.mjs +755 -0
- package/package.json +32 -0
- package/src/components/Avatar/index.tsx +19 -0
- package/src/components/Avatar/styles.ts +31 -0
- package/src/components/Box.tsx +32 -0
- package/src/components/Button.tsx +97 -0
- package/src/components/Checkbox/index.tsx +28 -0
- package/src/components/Checkbox/styles.ts +84 -0
- package/src/components/Dropdown/index.tsx +98 -0
- package/src/components/Dropdown/styles.ts +75 -0
- package/src/components/Heading.tsx +32 -0
- package/src/components/InputBox/index.tsx +24 -0
- package/src/components/InputBox/styles.ts +7 -0
- package/src/components/Text.tsx +45 -0
- package/src/components/TextArea/index.tsx +18 -0
- package/src/components/TextArea/styles.ts +42 -0
- package/src/components/TextInput/index.tsx +22 -0
- package/src/components/TextInput/styles.ts +61 -0
- package/src/index.tsx +9 -0
- package/src/styles/index.ts +36 -0
- package/tsconfig.json +4 -0
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spies-ui/react",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./dist/index.mjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsup src/index.tsx --format esm,cjs --dts --external react",
|
|
10
|
+
"dev": "tsup src/index.tsx --format esm,cjs --dts --external react --watch",
|
|
11
|
+
"lint": "eslint src/**/*.ts* --fix"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": "",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@spies-ui/eslint-config": "*",
|
|
18
|
+
"@spies-ui/tokens": "*",
|
|
19
|
+
"@spies-ui/ts-config": "*",
|
|
20
|
+
"@types/react": "^18.2.79",
|
|
21
|
+
"@types/react-dom": "^18.2.25",
|
|
22
|
+
"react": "^18.2.0",
|
|
23
|
+
"tsup": "^8.0.2",
|
|
24
|
+
"typescript": "^5.4.5"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@radix-ui/react-avatar": "^1.0.4",
|
|
28
|
+
"@radix-ui/react-checkbox": "^1.0.4",
|
|
29
|
+
"@stitches/react": "^1.2.8",
|
|
30
|
+
"phosphor-react": "^1.4.1"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ComponentProps } from 'react'
|
|
2
|
+
import { AvatarContainer, AvatarFallback, AvatarImage } from './styles'
|
|
3
|
+
import { User } from 'phosphor-react'
|
|
4
|
+
|
|
5
|
+
export interface AvatarProps extends ComponentProps<typeof AvatarImage> {}
|
|
6
|
+
|
|
7
|
+
export function Avatar(props: AvatarProps) {
|
|
8
|
+
return (
|
|
9
|
+
<AvatarContainer>
|
|
10
|
+
<AvatarImage {...props} />
|
|
11
|
+
|
|
12
|
+
<AvatarFallback delayMs={600}>
|
|
13
|
+
<User />
|
|
14
|
+
</AvatarFallback>
|
|
15
|
+
</AvatarContainer>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Avatar.displayName = 'Avatar'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as Avatar from '@radix-ui/react-avatar'
|
|
2
|
+
import { styled } from '../../styles'
|
|
3
|
+
|
|
4
|
+
export const AvatarContainer = styled(Avatar.Root, {
|
|
5
|
+
borderRadius: '$full',
|
|
6
|
+
display: 'inline-block',
|
|
7
|
+
width: '$12',
|
|
8
|
+
height: '$12',
|
|
9
|
+
overflow: 'hidden',
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
export const AvatarImage = styled(Avatar.Image, {
|
|
13
|
+
width: '100%',
|
|
14
|
+
height: '100%',
|
|
15
|
+
objectFix: 'cover',
|
|
16
|
+
borderRadius: 'inherit',
|
|
17
|
+
})
|
|
18
|
+
export const AvatarFallback = styled(Avatar.Fallback, {
|
|
19
|
+
width: '100%',
|
|
20
|
+
height: '100%',
|
|
21
|
+
display: 'flex',
|
|
22
|
+
alignItems: 'center',
|
|
23
|
+
justifyContent: 'center',
|
|
24
|
+
backgroundColor: '$gray600',
|
|
25
|
+
color: '$gray800',
|
|
26
|
+
|
|
27
|
+
svg: {
|
|
28
|
+
width: '$6',
|
|
29
|
+
height: '$6',
|
|
30
|
+
},
|
|
31
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ComponentProps, ElementType } from 'react'
|
|
2
|
+
import { styled } from '../styles'
|
|
3
|
+
|
|
4
|
+
export const Box = styled('div', {
|
|
5
|
+
padding: '$4',
|
|
6
|
+
borderRadius: '$md',
|
|
7
|
+
variants: {
|
|
8
|
+
background: {
|
|
9
|
+
default: {
|
|
10
|
+
backgroundColor: 'transparent',
|
|
11
|
+
},
|
|
12
|
+
gray600: {
|
|
13
|
+
backgroundColor: '$gray600',
|
|
14
|
+
},
|
|
15
|
+
gray700: {
|
|
16
|
+
backgroundColor: '$gray700',
|
|
17
|
+
},
|
|
18
|
+
gray800: {
|
|
19
|
+
backgroundColor: '$gray800',
|
|
20
|
+
},
|
|
21
|
+
gray900: {
|
|
22
|
+
backgroundColor: '$gray900',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export interface BoxProps extends ComponentProps<typeof Box> {
|
|
29
|
+
as?: ElementType
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Box.displayName = 'Box'
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { ComponentProps, ElementType } from 'react'
|
|
2
|
+
import { styled } from '../styles'
|
|
3
|
+
|
|
4
|
+
export const Button = styled('button', {
|
|
5
|
+
all: 'unset',
|
|
6
|
+
fontFamily: '$default',
|
|
7
|
+
fontWeight: '$medium',
|
|
8
|
+
fontSize: '$sm',
|
|
9
|
+
textAlign: 'center',
|
|
10
|
+
minWidth: 0,
|
|
11
|
+
boxSizing: 'border-box',
|
|
12
|
+
|
|
13
|
+
display: 'flex',
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
justifyContent: 'center',
|
|
16
|
+
gap: '$2',
|
|
17
|
+
|
|
18
|
+
cursor: 'pointer',
|
|
19
|
+
|
|
20
|
+
transition: '0.2s',
|
|
21
|
+
|
|
22
|
+
svg: {
|
|
23
|
+
width: '$4',
|
|
24
|
+
height: '$4',
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
'&:disabled': {
|
|
28
|
+
cursor: 'not-allowed',
|
|
29
|
+
backgroundColor: '$gray200',
|
|
30
|
+
borderColor: '$gray200',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
variants: {
|
|
34
|
+
variant: {
|
|
35
|
+
default: {
|
|
36
|
+
backgroundColor: 'transparent',
|
|
37
|
+
border: '2px solid $gray500',
|
|
38
|
+
color: '$smokedWhite',
|
|
39
|
+
|
|
40
|
+
'&:not(:disabled):hover': {
|
|
41
|
+
// backgroundColor: '$smokedWhite',
|
|
42
|
+
// borderColor: '$smokedWhite',
|
|
43
|
+
// color: '$gray900',
|
|
44
|
+
borderColor: '$gray600',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
primary: {
|
|
48
|
+
backgroundColor: '$primary',
|
|
49
|
+
border: '2px solid $primary',
|
|
50
|
+
color: '$smokedWhite',
|
|
51
|
+
|
|
52
|
+
'&:not(:disabled):hover': {
|
|
53
|
+
backgroundColor: '$primaryLight',
|
|
54
|
+
borderColor: '$primaryLight',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
size: {
|
|
60
|
+
default: {
|
|
61
|
+
padding: '$3 $6',
|
|
62
|
+
},
|
|
63
|
+
fit: {
|
|
64
|
+
width: '100%',
|
|
65
|
+
paddingTop: '$3',
|
|
66
|
+
paddingBottom: '$3',
|
|
67
|
+
},
|
|
68
|
+
small: {
|
|
69
|
+
padding: '$3 $4',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
radius: {
|
|
74
|
+
small: {
|
|
75
|
+
borderRadius: '$sm',
|
|
76
|
+
},
|
|
77
|
+
default: {
|
|
78
|
+
borderRadius: '$lg',
|
|
79
|
+
},
|
|
80
|
+
full: {
|
|
81
|
+
borderRadius: '$full',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
defaultVariants: {
|
|
87
|
+
size: 'default',
|
|
88
|
+
radius: 'default',
|
|
89
|
+
variant: 'default',
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
export interface ButtonProps extends ComponentProps<typeof Button> {
|
|
94
|
+
as?: ElementType
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
Button.displayName = 'Button'
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Check } from 'phosphor-react'
|
|
2
|
+
import { CheckboxContainer, CheckboxIndicator, CheckboxBox } from './styles'
|
|
3
|
+
import { Text } from '../Text'
|
|
4
|
+
import { InputBox } from '../InputBox'
|
|
5
|
+
import { ComponentProps } from 'react'
|
|
6
|
+
|
|
7
|
+
export interface CheckboxProps
|
|
8
|
+
extends ComponentProps<typeof CheckboxContainer> {
|
|
9
|
+
label?: string
|
|
10
|
+
error?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Checkbox({ label, error, ...props }: CheckboxProps) {
|
|
14
|
+
return (
|
|
15
|
+
<InputBox error={error}>
|
|
16
|
+
<CheckboxBox>
|
|
17
|
+
<CheckboxContainer {...props} errored={!!error}>
|
|
18
|
+
<CheckboxIndicator asChild>
|
|
19
|
+
<Check weight="bold" />
|
|
20
|
+
</CheckboxIndicator>
|
|
21
|
+
</CheckboxContainer>
|
|
22
|
+
{!!label && <Text size="sm">{label}</Text>}
|
|
23
|
+
</CheckboxBox>
|
|
24
|
+
</InputBox>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Checkbox.displayName = 'Checkbox'
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { styled, keyframes } from '../../styles'
|
|
2
|
+
import * as Checkbox from '@radix-ui/react-checkbox'
|
|
3
|
+
|
|
4
|
+
export const CheckboxBox = styled('div', {
|
|
5
|
+
display: 'flex',
|
|
6
|
+
gap: '$2',
|
|
7
|
+
|
|
8
|
+
'&:has(button:disabled)': {
|
|
9
|
+
opacity: 0.5,
|
|
10
|
+
},
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
export const CheckboxContainer = styled(Checkbox.Root, {
|
|
14
|
+
all: 'unset',
|
|
15
|
+
width: '$6',
|
|
16
|
+
height: '$6',
|
|
17
|
+
backgroundColor: '$gray900',
|
|
18
|
+
borderRadius: '$xs',
|
|
19
|
+
lineHeight: 0,
|
|
20
|
+
cursor: 'pointer',
|
|
21
|
+
overflow: 'hidden',
|
|
22
|
+
boxSizing: 'border-box',
|
|
23
|
+
display: 'flex',
|
|
24
|
+
justifyContent: 'center',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
border: '2px solid $gray900',
|
|
27
|
+
|
|
28
|
+
'&[data-state="checked"]': {
|
|
29
|
+
backgroundColor: '$primary',
|
|
30
|
+
borderColor: '$primary',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
'&:focus': {
|
|
34
|
+
border: '2px solid $primary',
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
'&:disabled': {
|
|
38
|
+
cursor: 'not-allowed',
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
variants: {
|
|
42
|
+
errored: {
|
|
43
|
+
true: {
|
|
44
|
+
borderColor: '$danger',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
defaultVariants: {
|
|
50
|
+
errored: false,
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const slideIn = keyframes({
|
|
55
|
+
from: {
|
|
56
|
+
transform: 'translateX(-100%)',
|
|
57
|
+
},
|
|
58
|
+
to: {
|
|
59
|
+
transform: 'translateX(0)',
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const slideOut = keyframes({
|
|
64
|
+
from: {
|
|
65
|
+
transform: 'translateX(0)',
|
|
66
|
+
},
|
|
67
|
+
to: {
|
|
68
|
+
transform: 'translateX(100%)',
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
export const CheckboxIndicator = styled(Checkbox.Indicator, {
|
|
73
|
+
color: '$smokedWhite',
|
|
74
|
+
width: '$4',
|
|
75
|
+
height: '$4',
|
|
76
|
+
|
|
77
|
+
'&[data-state="checked"]': {
|
|
78
|
+
animation: `${slideIn} 100ms ease-out`,
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
'&[data-state="unchecked"]': {
|
|
82
|
+
animation: `${slideOut} 100ms ease-out`,
|
|
83
|
+
},
|
|
84
|
+
})
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { useRef, useState, useEffect } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
DropdownContainer,
|
|
4
|
+
DropdownList,
|
|
5
|
+
DropdownItem,
|
|
6
|
+
DropdownTrigger,
|
|
7
|
+
} from './styles'
|
|
8
|
+
import { Button } from './../Button'
|
|
9
|
+
|
|
10
|
+
export interface Option {
|
|
11
|
+
text: string
|
|
12
|
+
variant?: 'default' | 'danger'
|
|
13
|
+
onSelect: () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DropdownProps {
|
|
17
|
+
options: Option[]
|
|
18
|
+
name?: string
|
|
19
|
+
children?: React.ReactElement
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function Dropdown({ options, children, name }: DropdownProps) {
|
|
23
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
24
|
+
const dropdownRef = useRef<HTMLUListElement>(null)
|
|
25
|
+
const buttonRef = useRef<HTMLButtonElement>(null)
|
|
26
|
+
|
|
27
|
+
const toggleDropdown = () => {
|
|
28
|
+
setIsOpen(!isOpen)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const handleSelectOption = (option: Option) => {
|
|
32
|
+
option.onSelect()
|
|
33
|
+
setIsOpen(false)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
37
|
+
if (
|
|
38
|
+
dropdownRef.current &&
|
|
39
|
+
buttonRef.current &&
|
|
40
|
+
!dropdownRef.current.contains(event.target as Node) &&
|
|
41
|
+
!buttonRef.current.contains(event.target as Node)
|
|
42
|
+
) {
|
|
43
|
+
setIsOpen(false)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
document.addEventListener('mousedown', handleClickOutside)
|
|
49
|
+
return () => {
|
|
50
|
+
document.removeEventListener('mousedown', handleClickOutside)
|
|
51
|
+
}
|
|
52
|
+
}, [])
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const handleReposition = () => {
|
|
56
|
+
if (isOpen && buttonRef.current && dropdownRef.current) {
|
|
57
|
+
const buttonRect = buttonRef.current.getBoundingClientRect()
|
|
58
|
+
const dropdownRect = dropdownRef.current.getBoundingClientRect()
|
|
59
|
+
const buttonTop = buttonRect.top
|
|
60
|
+
const buttonHeight = buttonRect.height
|
|
61
|
+
const dropdownHeight = dropdownRect.height
|
|
62
|
+
|
|
63
|
+
const spaceBelow = window.innerHeight - buttonTop - buttonHeight
|
|
64
|
+
if (spaceBelow < dropdownHeight) {
|
|
65
|
+
dropdownRef.current.style.bottom = `${buttonHeight + 6}px`
|
|
66
|
+
} else {
|
|
67
|
+
dropdownRef.current.style.top = `${buttonHeight + 6}px`
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
handleReposition()
|
|
73
|
+
}, [isOpen])
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<DropdownContainer>
|
|
77
|
+
<DropdownTrigger ref={buttonRef} onClick={toggleDropdown}>
|
|
78
|
+
{name && children === undefined && <Button>{name}</Button>}
|
|
79
|
+
{children && name === undefined && children}
|
|
80
|
+
</DropdownTrigger>
|
|
81
|
+
{isOpen && (
|
|
82
|
+
<DropdownList ref={dropdownRef}>
|
|
83
|
+
{options.map((option, index) => (
|
|
84
|
+
<DropdownItem
|
|
85
|
+
key={index}
|
|
86
|
+
onClick={() => handleSelectOption(option)}
|
|
87
|
+
variant={option.variant}
|
|
88
|
+
>
|
|
89
|
+
{option.text}
|
|
90
|
+
</DropdownItem>
|
|
91
|
+
))}
|
|
92
|
+
</DropdownList>
|
|
93
|
+
)}
|
|
94
|
+
</DropdownContainer>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Dropdown.displayName = 'Dropdown'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { styled, keyframes } from '../../styles'
|
|
2
|
+
|
|
3
|
+
export const DropdownContainer = styled('div', {
|
|
4
|
+
position: 'relative',
|
|
5
|
+
display: 'inline-block',
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
export const DropdownTrigger = styled('span', {})
|
|
9
|
+
|
|
10
|
+
const fadeIn = keyframes({
|
|
11
|
+
'0%': { opacity: '0' },
|
|
12
|
+
'100%': { opacity: '1' },
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export const DropdownList = styled('ul', {
|
|
16
|
+
position: 'absolute',
|
|
17
|
+
// top: '100%',
|
|
18
|
+
// left: 0,
|
|
19
|
+
backgroundColor: '#18181B',
|
|
20
|
+
borderRadius: '$lg',
|
|
21
|
+
padding: 0,
|
|
22
|
+
// margin: '$1 0',
|
|
23
|
+
margin: 0,
|
|
24
|
+
listStyle: 'none',
|
|
25
|
+
zIndex: 9999,
|
|
26
|
+
minWidth: '100%', // ensures the dropdown list as wide as the container
|
|
27
|
+
|
|
28
|
+
left: '50%',
|
|
29
|
+
transform: 'translateX(-50%)',
|
|
30
|
+
|
|
31
|
+
animation: `${fadeIn} 100ms ease-out`,
|
|
32
|
+
|
|
33
|
+
'& li:first-child': {
|
|
34
|
+
marginTop: '$2',
|
|
35
|
+
},
|
|
36
|
+
'& li:last-child': {
|
|
37
|
+
marginBottom: '$2',
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
export const DropdownItem = styled('li', {
|
|
42
|
+
fontFamily: '$default',
|
|
43
|
+
fontSize: '$sm',
|
|
44
|
+
color: '$smokedWhite',
|
|
45
|
+
padding: '$2 $2',
|
|
46
|
+
marginLeft: '$2',
|
|
47
|
+
marginRight: '$2',
|
|
48
|
+
width: '$40',
|
|
49
|
+
borderRadius: '$md',
|
|
50
|
+
cursor: 'pointer',
|
|
51
|
+
|
|
52
|
+
variants: {
|
|
53
|
+
variant: {
|
|
54
|
+
default: {
|
|
55
|
+
color: '$smokedWhite',
|
|
56
|
+
|
|
57
|
+
'&:hover': {
|
|
58
|
+
backgroundColor: '$gray700',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
danger: {
|
|
62
|
+
color: '$danger',
|
|
63
|
+
|
|
64
|
+
'&:hover': {
|
|
65
|
+
backgroundColor: '$danger',
|
|
66
|
+
color: '$smokedWhite',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
defaultVariants: {
|
|
73
|
+
variant: 'default',
|
|
74
|
+
},
|
|
75
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ComponentProps, ElementType } from 'react'
|
|
2
|
+
import { styled } from '../styles'
|
|
3
|
+
|
|
4
|
+
export const Heading = styled('h2', {
|
|
5
|
+
fontFamily: '$heading',
|
|
6
|
+
lineHeight: '$shorter',
|
|
7
|
+
margin: 0,
|
|
8
|
+
color: '$smokedWhite',
|
|
9
|
+
|
|
10
|
+
variants: {
|
|
11
|
+
size: {
|
|
12
|
+
sm: { fontSize: '$xl' },
|
|
13
|
+
md: { fontSize: '$2xl' },
|
|
14
|
+
lg: { fontSize: '$4xl' },
|
|
15
|
+
'2xl': { fontSize: '$5xl' },
|
|
16
|
+
'3xl': { fontSize: '$5xl' },
|
|
17
|
+
'4xl': { fontSize: '$6xl' },
|
|
18
|
+
'5xl': { fontSize: '$7xl' },
|
|
19
|
+
'6xl': { fontSize: '$8xl' },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
size: 'md',
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export interface HeadingProps extends ComponentProps<typeof Heading> {
|
|
29
|
+
as?: ElementType
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Heading.displayName = 'Heading'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Text } from '../Text'
|
|
2
|
+
import { InputContainer } from './styles'
|
|
3
|
+
|
|
4
|
+
export interface InputProps {
|
|
5
|
+
label?: string
|
|
6
|
+
children: React.ReactElement
|
|
7
|
+
error?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function InputBox({ label, error, children }: InputProps) {
|
|
11
|
+
return (
|
|
12
|
+
<InputContainer>
|
|
13
|
+
{!!label && <Text size={'sm'}>{label}</Text>}
|
|
14
|
+
{children}
|
|
15
|
+
{!!error && (
|
|
16
|
+
<Text size="xs" variant="danger">
|
|
17
|
+
{error}
|
|
18
|
+
</Text>
|
|
19
|
+
)}
|
|
20
|
+
</InputContainer>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
InputBox.displayName = 'InputBox'
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ComponentProps, ElementType } from 'react'
|
|
2
|
+
import { styled } from '../styles'
|
|
3
|
+
|
|
4
|
+
export const Text = styled('p', {
|
|
5
|
+
fontFamily: '$default',
|
|
6
|
+
lineHeight: '$base',
|
|
7
|
+
margin: 0,
|
|
8
|
+
color: '$smokedWhite',
|
|
9
|
+
|
|
10
|
+
variants: {
|
|
11
|
+
size: {
|
|
12
|
+
xxs: { fontSize: '$xxs' },
|
|
13
|
+
xs: { fontSize: '$xs' },
|
|
14
|
+
sm: { fontSize: '$sm' },
|
|
15
|
+
md: { fontSize: '$md' },
|
|
16
|
+
lg: { fontSize: '$lg' },
|
|
17
|
+
xl: { fontSize: '$xl' },
|
|
18
|
+
'2xl': { fontSize: '$2xl' },
|
|
19
|
+
'4xl': { fontSize: '$4xl' },
|
|
20
|
+
'5xl': { fontSize: '$5xl' },
|
|
21
|
+
'6xl': { fontSize: '$6xl' },
|
|
22
|
+
'7xl': { fontSize: '$7xl' },
|
|
23
|
+
'8xl': { fontSize: '$8xl' },
|
|
24
|
+
'9xl': { fontSize: '$9xl' },
|
|
25
|
+
},
|
|
26
|
+
variant: {
|
|
27
|
+
default: { color: '$smokedWhite' },
|
|
28
|
+
primary: { color: '$primary' },
|
|
29
|
+
danger: { color: '$danger' },
|
|
30
|
+
success: { color: '$success' },
|
|
31
|
+
warning: { color: '$warning' },
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
defaultVariants: {
|
|
36
|
+
size: 'md',
|
|
37
|
+
variant: 'default',
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
export interface TextProps extends ComponentProps<typeof Text> {
|
|
42
|
+
as?: ElementType
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Text.displayName = 'Text'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ComponentProps } from 'react'
|
|
2
|
+
import { InputBox } from '../InputBox'
|
|
3
|
+
import { TextAreaInput } from './styles'
|
|
4
|
+
|
|
5
|
+
export interface TextAreaProps extends ComponentProps<typeof TextAreaInput> {
|
|
6
|
+
label?: string
|
|
7
|
+
error?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function TextArea({ label, error, ...props }: TextAreaProps) {
|
|
11
|
+
return (
|
|
12
|
+
<InputBox label={label} error={error}>
|
|
13
|
+
<TextAreaInput {...props} errored={!!error} />
|
|
14
|
+
</InputBox>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
TextArea.displayName = 'TextArea'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { styled } from '../../styles'
|
|
2
|
+
|
|
3
|
+
export const TextAreaInput = styled('textarea', {
|
|
4
|
+
backgroundColor: '$gray900',
|
|
5
|
+
padding: '$3 $4',
|
|
6
|
+
borderRadius: '$sm',
|
|
7
|
+
boxSizing: 'border-box',
|
|
8
|
+
border: '2px solid $gray900',
|
|
9
|
+
|
|
10
|
+
fontFamily: '$default',
|
|
11
|
+
fontSize: '$sm',
|
|
12
|
+
color: '$white',
|
|
13
|
+
fontWeight: '$regular',
|
|
14
|
+
resize: 'vertical',
|
|
15
|
+
minHeight: 80,
|
|
16
|
+
|
|
17
|
+
'&:focus': {
|
|
18
|
+
outline: 0,
|
|
19
|
+
borderColor: '$primary',
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
'&:disabled': {
|
|
23
|
+
opacity: 0.5,
|
|
24
|
+
cursor: 'not-allowed',
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
'&:placeholder': {
|
|
28
|
+
color: '$gray400',
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
variants: {
|
|
32
|
+
errored: {
|
|
33
|
+
true: {
|
|
34
|
+
borderColor: '$danger',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
defaultVariants: {
|
|
40
|
+
errored: false,
|
|
41
|
+
},
|
|
42
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ComponentProps } from 'react'
|
|
2
|
+
import { Input, Prefix, TextInputContainer } from './styles'
|
|
3
|
+
import { InputBox } from '../InputBox'
|
|
4
|
+
|
|
5
|
+
export interface TextInputProps extends ComponentProps<typeof Input> {
|
|
6
|
+
label?: string
|
|
7
|
+
prefix?: string
|
|
8
|
+
error?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function TextInput({ label, prefix, error, ...props }: TextInputProps) {
|
|
12
|
+
return (
|
|
13
|
+
<InputBox label={label} error={error}>
|
|
14
|
+
<TextInputContainer errored={!!error}>
|
|
15
|
+
{!!prefix && <Prefix>{prefix}</Prefix>}
|
|
16
|
+
<Input {...props} />
|
|
17
|
+
</TextInputContainer>
|
|
18
|
+
</InputBox>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
TextInput.displayName = 'TextInput'
|