@liguelead/design-system 0.0.10 → 0.0.11

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.
Files changed (44) hide show
  1. package/components/Button/Button.appearance.ts +20 -16
  2. package/components/Button/Button.sizes.ts +18 -17
  3. package/components/Button/Button.styles.ts +7 -11
  4. package/components/Button/Button.tsx +5 -5
  5. package/components/Button/Button.types.ts +3 -3
  6. package/components/Checkbox/Checkbox.styles.ts +84 -35
  7. package/components/Checkbox/Checkbox.tsx +62 -5
  8. package/components/Checkbox/Checkbox.types.ts +1 -0
  9. package/components/IconButton/IconButton.sizes.ts +6 -13
  10. package/components/IconButton/IconButton.tsx +5 -5
  11. package/components/InputOpt/InputOpt.styles.ts +75 -0
  12. package/components/InputOpt/InputOpt.tsx +153 -0
  13. package/components/InputOpt/InputOpt.types.ts +14 -0
  14. package/components/InputOpt/index.ts +1 -0
  15. package/components/InputOpt/utils/focusManagement.ts +31 -0
  16. package/components/InputOpt/utils/index.ts +2 -0
  17. package/components/InputOpt/utils/inputValidation.ts +14 -0
  18. package/components/LinkButton/LinkButton.size.ts +39 -0
  19. package/components/LinkButton/LinkButton.style.ts +45 -0
  20. package/components/LinkButton/LinkButton.tsx +75 -0
  21. package/components/LinkButton/LinkButton.types.ts +11 -0
  22. package/components/LinkButton/index.ts +1 -0
  23. package/components/RadioButton/RadioButton.inputVariants.ts +133 -0
  24. package/components/RadioButton/RadioButton.styles.ts +78 -0
  25. package/components/RadioButton/RadioButton.tsx +88 -0
  26. package/components/RadioButton/RadioButton.types.ts +33 -0
  27. package/components/RadioButton/RadioButton.variants.ts +67 -0
  28. package/components/RadioButton/index.ts +1 -0
  29. package/components/SegmentedButton/SegmentedButton.tsx +0 -6
  30. package/components/Select/Select.sizes.ts +10 -11
  31. package/components/Select/Select.states.tsx +8 -37
  32. package/components/Select/Select.styles.ts +53 -39
  33. package/components/Select/Select.tsx +30 -23
  34. package/components/Select/Select.types.ts +1 -2
  35. package/components/Text/Text.styles.ts +11 -8
  36. package/components/Text/Text.tsx +2 -2
  37. package/components/Text/Text.types.ts +3 -1
  38. package/components/TextField/TextField.sizes.ts +3 -9
  39. package/components/TextField/TextField.states.tsx +11 -11
  40. package/components/TextField/TextField.styles.ts +4 -0
  41. package/components/TextField/TextField.tsx +5 -2
  42. package/components/index.ts +3 -0
  43. package/package.json +2 -2
  44. package/utils/darkenOrLighen.ts +1 -1
@@ -1,11 +1,11 @@
1
- import {ButtonAppearanceTypes} from './Button.types'
1
+ import { ButtonVariantTypes} from './Button.types'
2
2
  import {colorType} from 'types'
3
3
  import {useTheme} from 'styled-components'
4
4
  import {darkenOrLighten, getTextColor, parseColor} from '../../utils'
5
5
 
6
- export const ButtonAppearance = (
6
+ export const ButtonVariant = (
7
7
  color: colorType,
8
- appearance: ButtonAppearanceTypes
8
+ variant: ButtonVariantTypes
9
9
  ) => {
10
10
  const theme = useTheme()
11
11
  const parsedColor = parseColor(theme.colors[color])
@@ -14,7 +14,7 @@ export const ButtonAppearance = (
14
14
 
15
15
  const colorHover = darkenOrLighten(0.2, parsedColor)
16
16
 
17
- const appearances = {
17
+ const variants = {
18
18
  solid: `
19
19
  background-color: ${parsedColor};
20
20
  color: ${solidtextColor};
@@ -24,24 +24,26 @@ export const ButtonAppearance = (
24
24
  border-color: ${colorHover};
25
25
  }
26
26
  &:disabled {
27
- background-color: ${parseColor(theme.colors.neutral200)};
28
- color: ${parseColor(theme.colors.neutral500)};
29
- border-color: ${parseColor(theme.colors.neutral200)};
27
+ background-color: ${parsedColor}80;
28
+ color: ${solidtextColor}cc;
29
+ cursor: not-allowed;
30
+ border: none;
30
31
  }
31
- `,
32
+ `,
32
33
  outline: `
33
34
  background-color: transparent;
34
35
  color: ${parsedColor};
35
36
  border: 1px solid ${parsedColor};
36
37
  &:hover {
37
- background-color: ${parsedColor};
38
- border-color: ${parsedColor};
39
- color: white;
38
+ background-color: ${parseColor(theme.colors.primaryDarker)};
39
+ border-color: transparent;
40
+ color: ${parseColor(theme.colors.white)};
40
41
  }
41
42
  &:disabled {
42
43
  background-color: transparent;
43
- color: ${parseColor(theme.colors.neutral500)};
44
- border-color: ${parseColor(theme.colors.neutral500)};
44
+ color: ${parseColor(theme.colors.neutral1100)}80;
45
+ border-color: ${parseColor(theme.colors.neutral400)};
46
+ cursor: not-allowed;
45
47
  }
46
48
  `,
47
49
  ghost: `
@@ -49,14 +51,16 @@ export const ButtonAppearance = (
49
51
  color: ${parsedColor};
50
52
  border: 1px solid transparent;
51
53
  &:hover {
52
- background-color: rgba(0,0,0,0.05)
54
+ background-color: ${parseColor(theme.colors.primaryDarker)};
55
+ color: ${parseColor(theme.colors.white)};
53
56
  }
54
57
  &:disabled {
55
58
  background-color: transparent;
56
- color: ${parseColor(theme.colors.neutral500)};
59
+ color: ${parseColor(theme.colors.neutral1100)}80;
60
+ cursor: not-allowed;
57
61
  }
58
62
  `
59
63
  }
60
64
 
61
- return appearances[appearance]
65
+ return variants[variant]
62
66
  }
@@ -1,39 +1,40 @@
1
- import { fontSize, fontWeight, lineHeight, spacing } from '@liguelead/foundation'
1
+ import {
2
+ fontSize,
3
+ fontWeight,
4
+ lineHeight,
5
+ spacing,
6
+ radius
7
+ } from '@liguelead/foundation'
2
8
  import { ButtonSizeTypes } from './Button.types'
3
9
 
4
10
  export const ButtonSizes = (size: ButtonSizeTypes) => {
5
11
  const sizes = {
6
- xs: `
7
- padding: ${spacing.spacing4}px ${spacing.spacing8}px;
8
- font-size: ${fontSize.fontSize10}px;
9
- font-weight: ${fontWeight.fontWeight600};
10
- line-height: ${lineHeight.lineHeight14}px;
11
- gap: ${spacing.spacing8}px;
12
- border-radius: ${spacing.spacing4}px;
13
- `,
14
12
  sm: `
15
13
  padding: ${spacing.spacing8}px ${spacing.spacing12}px;
16
14
  font-size: ${fontSize.fontSize14}px;
17
- font-weight: ${fontWeight.fontWeight600};
15
+ font-weight: ${fontWeight.fontWeight500};
18
16
  line-height: ${lineHeight.lineHeight22}px;
19
17
  gap: ${spacing.spacing8}px;
20
- border-radius: ${spacing.spacing4}px;
18
+ min-width: ${spacing.spacing64}px;
19
+ border-radius: ${radius.radius4}px;
21
20
  `,
22
21
  md: `
23
- padding: ${spacing.spacing12}px ${spacing.spacing20}px;
22
+ padding: ${spacing.spacing8}px ${spacing.spacing16}px;
24
23
  font-size: ${fontSize.fontSize14}px;
25
- font-weight: ${fontWeight.fontWeight600};
24
+ font-weight: ${fontWeight.fontWeight500};
26
25
  line-height: ${lineHeight.lineHeight22}px;
27
26
  gap: ${spacing.spacing8}px;
28
- border-radius: ${spacing.spacing4}px;
27
+ min-width: ${spacing.spacing76}px;
28
+ border-radius: ${radius.radius4}px;
29
29
  `,
30
30
  lg: `
31
- padding: ${spacing.spacing16}px ${spacing.spacing24}px;
31
+ padding: ${spacing.spacing8}px ${spacing.spacing32}px;
32
32
  font-size: ${fontSize.fontSize16}px;
33
- font-weight: ${fontWeight.fontWeight600};
33
+ font-weight: ${fontWeight.fontWeight500};
34
34
  line-height: ${lineHeight.lineHeight24}px;
35
35
  gap: ${spacing.spacing8}px;
36
- border-radius: ${spacing.spacing4}px;
36
+ min-width: ${spacing.spacing108}px;
37
+ border-radius: ${radius.radius4}px;
37
38
  `
38
39
  }
39
40
 
@@ -1,8 +1,9 @@
1
1
  import styled from 'styled-components'
2
2
  import { ButtonProps } from './Button.types'
3
+ import { shadow } from '@liguelead/foundation'
3
4
 
4
- interface StyledButtonProps extends ButtonProps {
5
- $appearance: string
5
+ export interface StyledButtonProps extends ButtonProps {
6
+ $variant: string
6
7
  $buttonSize: string
7
8
  $fluid: boolean
8
9
  }
@@ -19,26 +20,21 @@ export const StyledButton = styled.button<StyledButtonProps>`
19
20
  cursor: pointer;
20
21
  outline: none;
21
22
  transition: background-color 0.3s, box-shadow 0.3s;
22
- ${({ $appearance }) => $appearance}
23
+ ${({ $variant }) => $variant}
23
24
 
24
25
  &:focus {
25
- outline: none;
26
- box-shadow: 0px 0px 0px var(--2, 2px) rgba(255, 255, 255, 0.1),
27
- 0px 0px 0px var(--4, 4px) rgba(255, 255, 255, 0.1);
26
+ box-shadow: ${shadow.focusShadow};
28
27
  }
29
28
  `
30
29
 
31
30
  export const RippleContainer = styled.span<{
32
- $appearance: string
31
+ $variant: string
33
32
  }>`
34
33
  position: absolute;
35
34
  border-radius: 50%;
36
35
  transform: scale(0);
37
36
  animation: ripple 0.4s linear;
38
- background-color: ${({ $appearance }) =>
39
- $appearance === 'solid'
40
- ? 'rgba(255, 255, 255, 0.5)'
41
- : 'rgba(0, 0, 0, 0.2)'};
37
+ background-color:rgba(255, 255, 255, 0.5);
42
38
  pointer-events: none;
43
39
 
44
40
  @keyframes ripple {
@@ -2,10 +2,10 @@ import { useState } from 'react'
2
2
  import { StyledButton, RippleContainer } from './Button.styles'
3
3
  import { RippleInterface, ButtonProps } from './Button.types'
4
4
  import { ButtonSizes } from './Button.sizes'
5
- import { ButtonAppearance } from './Button.appearance'
5
+ import { ButtonVariant } from './Button.appearance'
6
6
 
7
7
  const Button: React.FC<ButtonProps> = ({
8
- appearance = 'solid',
8
+ variant = 'solid',
9
9
  children,
10
10
  className,
11
11
  color = 'primary',
@@ -19,7 +19,7 @@ const Button: React.FC<ButtonProps> = ({
19
19
  const [ripples, setRipples] = useState<RippleInterface[]>([])
20
20
 
21
21
  const buttonSize = ButtonSizes(size)
22
- const buttonAppearance = ButtonAppearance(color, appearance)
22
+ const buttonVariant = ButtonVariant(color, variant)
23
23
 
24
24
  const removeRipple = (ripples: RippleInterface[], rippleId: string) => {
25
25
  return ripples.filter(r => r.id !== rippleId)
@@ -48,7 +48,7 @@ const Button: React.FC<ButtonProps> = ({
48
48
  disabled={disabled}
49
49
  className={className}
50
50
  $fluid={fluid}
51
- $appearance={buttonAppearance}
51
+ $variant={buttonVariant}
52
52
  onClick={handleClick}
53
53
  $buttonSize={buttonSize}
54
54
  type={type}
@@ -56,7 +56,7 @@ const Button: React.FC<ButtonProps> = ({
56
56
  {children}
57
57
  {ripples.map(ripple => (
58
58
  <RippleContainer
59
- $appearance={appearance}
59
+ $variant={variant}
60
60
  key={ripple.id}
61
61
  style={{
62
62
  top: ripple.y - 10,
@@ -1,10 +1,10 @@
1
1
  import { colorType } from 'types'
2
2
 
3
- export type ButtonSizeTypes = 'xs' | 'sm' | 'md' | 'lg'
4
- export type ButtonAppearanceTypes = 'solid' | 'outline' | 'ghost'
3
+ export type ButtonSizeTypes = 'sm' | 'md' | 'lg'
4
+ export type ButtonVariantTypes = 'solid' | 'outline' | 'ghost'
5
5
 
6
6
  export interface ButtonProps {
7
- appearance?: ButtonAppearanceTypes
7
+ variant?: ButtonVariantTypes
8
8
  children: React.ReactNode
9
9
  className?: string
10
10
  disabled?: boolean
@@ -1,15 +1,21 @@
1
- import { spacing } from '@liguelead/foundation'
1
+ import {
2
+ spacing,
3
+ fontSize,
4
+ fontWeight,
5
+ radius
6
+ } from '@liguelead/foundation'
2
7
  import { parseColor } from '../../utils'
3
- import styled from 'styled-components'
8
+ import styled, { css } from 'styled-components'
9
+ import Text from '../Text'
4
10
 
5
11
  export const CheckboxWrapper = styled.label`
6
12
  display: flex;
7
- align-items: center;
13
+ align-items: start;
8
14
  cursor: pointer;
9
15
  position: relative;
10
16
  user-select: none;
11
17
  gap: 8px;
12
- font-size: 14px;
18
+ font-size: ${fontSize.fontSize14}px;
13
19
 
14
20
  input {
15
21
  position: absolute;
@@ -17,50 +23,93 @@ export const CheckboxWrapper = styled.label`
17
23
  width: 0;
18
24
  height: 0;
19
25
  }
26
+
27
+ input:focus + span {
28
+ box-shadow: 0 0 0 3px #A3A3A350}
29
+ }
20
30
  `
21
31
 
22
32
  export const CustomCheckbox = styled.span<{
23
33
  checked: boolean
24
34
  disabled?: boolean
25
35
  }>`
26
- width: ${spacing.spacing20}px;
27
- height: ${spacing.spacing20}px;
28
- border: 2px solid ${({ theme }) => parseColor(theme.colors.primary)};
29
- border-radius: 2px;
30
- display: flex;
31
- align-items: center;
32
- justify-content: center;
33
- transition: all 0.2s ease-in-out;
34
- background-color: ${({ checked, theme }) =>
35
- checked ? parseColor(theme.colors.primary) : 'transparent'};
36
+ ${({ checked, theme, disabled }) => css`
37
+ width: ${spacing.spacing16}px;
38
+ height: ${spacing.spacing16}px;
39
+ border: 1px solid ${checked
40
+ ? parseColor(theme.colors.primary)
41
+ : parseColor(theme.colors.neutral400)};
42
+ border-radius: ${radius.radius4}px;
43
+ display: flex;
44
+ top: 2px;
45
+ align-items: center;
46
+ justify-content: center;
47
+ transition: all 0.2s ease-in-out;
48
+ background-color: ${checked
49
+ ? parseColor(theme.colors.primary)
50
+ : 'transparent'};
51
+ position: relative;
52
+ overflow: hidden;
53
+
54
+ ${disabled &&
55
+ css`
56
+ background-color: transparent;
57
+ border-color: ${parseColor(theme.colors.neutral400)}70;
58
+ cursor: not-allowed;
59
+ `}
36
60
 
37
- ${({ disabled, theme }) =>
38
- disabled &&
39
- `
40
- border-color: ${parseColor(theme.colors.neutral300)};
41
- background-color: ${parseColor(theme.colors.neutral100)};
42
- cursor: not-allowed;
43
- `}
61
+ &::after {
62
+ content: '';
63
+ width: 16px;
64
+ height: 16px;
65
+ display: ${checked ? 'block' : 'none'};
66
+ background-color: white;
67
+ z-index: 1;
68
+
69
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='white' d='M9 16.2l-4.2-4.2-1.4 1.4 5.6 5.6L21 7.8l-1.4-1.4z'/%3E%3C/svg%3E")
70
+ no-repeat center / contain;
71
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='white' d='M9 16.2l-4.2-4.2-1.4 1.4 5.6 5.6L21 7.8l-1.4-1.4z'/%3E%3C/svg%3E")
72
+ no-repeat center / contain;
73
+ }
74
+
75
+ `}
76
+ `
44
77
 
45
- &::after {
46
- content: '';
47
- width: 16px;
48
- height: 16px;
49
- display: ${({ checked }) => (checked ? 'block' : 'none')};
50
- background-color: white;
78
+ export const RippleContainer = styled.span`
79
+ position: absolute;
80
+ border-radius: 50%;
81
+ transform: scale(0);
82
+ animation: ripple 0.4s linear;
83
+ background-color: rgba(255, 255, 255, 0.6);
84
+ pointer-events: none;
85
+ z-index: 0;
51
86
 
52
- mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='white' d='M9 16.2l-4.2-4.2-1.4 1.4 5.6 5.6L21 7.8l-1.4-1.4z'/%3E%3C/svg%3E")
53
- no-repeat center / contain;
54
- -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='white' d='M9 16.2l-4.2-4.2-1.4 1.4 5.6 5.6L21 7.8l-1.4-1.4z'/%3E%3C/svg%3E")
55
- no-repeat center / contain;
87
+ @keyframes ripple {
88
+ to {
89
+ transform: scale(3.5);
90
+ opacity: 0;
91
+ }
56
92
  }
57
93
  `
58
94
 
59
95
  export const Label = styled.span<{ disabled?: boolean }>`
60
- font-size: 14px;
61
- font-weight: 500;
96
+ font-size: ${fontSize.fontSize14}px;
97
+ font-weight: ${fontWeight.fontWeight500};
98
+
62
99
  color: ${({ theme, disabled }) =>
63
100
  disabled
64
- ? parseColor(theme.colors.neutral500)
65
- : parseColor(theme.colors.neutral900)};
101
+ ? `${parseColor(theme.colors.neutral1100)}70`
102
+ : parseColor(theme.colors.neutral1100)};
103
+ `
104
+
105
+ export const CustomLabel = styled(Text)<{ disabled?: boolean }>`
106
+ font-size: ${fontSize.fontSize12}px;
107
+ font-weight: ${fontWeight.fontWeight400};
108
+ line-height: 8px;
109
+
110
+ color: ${({ theme, disabled }) =>
111
+ disabled
112
+ ? `${parseColor(theme.colors.textMedium)}70`
113
+ : parseColor(theme.colors.textMedium)};
114
+
66
115
  `
@@ -1,6 +1,18 @@
1
1
  import React, { useState } from 'react'
2
2
  import { CheckboxProps } from './Checkbox.types'
3
- import { CheckboxWrapper, CustomCheckbox, Label } from './Checkbox.styles'
3
+ import {
4
+ CheckboxWrapper,
5
+ CustomCheckbox,
6
+ CustomLabel,
7
+ Label,
8
+ RippleContainer
9
+ } from './Checkbox.styles'
10
+
11
+ interface RippleInterface {
12
+ id: string
13
+ x: number
14
+ y: number
15
+ }
4
16
 
5
17
  const Checkbox: React.FC<CheckboxProps> = ({
6
18
  label,
@@ -9,16 +21,34 @@ const Checkbox: React.FC<CheckboxProps> = ({
9
21
  disabled = false,
10
22
  register,
11
23
  className,
24
+ description,
12
25
  ...rest
13
26
  }) => {
14
- // Estado interno para alternar caso `checked` não seja controlado externamente
15
27
  const [internalChecked, setInternalChecked] = useState<boolean>(
16
28
  checked || false
17
29
  )
30
+ const [ripples, setRipples] = useState<RippleInterface[]>([])
31
+
32
+ const removeRipple = (ripples: RippleInterface[], rippleId: string) => {
33
+ return ripples.filter(r => r.id !== rippleId)
34
+ }
18
35
 
19
36
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
20
37
  onChange?.(e)
21
- setInternalChecked(!internalChecked) // Alterna o estado internamente
38
+ setInternalChecked(!internalChecked)
39
+ }
40
+
41
+ const handleRipple = (e: React.MouseEvent<HTMLSpanElement>) => {
42
+ if (disabled) return
43
+ const rect = e.currentTarget.getBoundingClientRect()
44
+ const x = e.clientX - rect.left
45
+ const y = e.clientY - rect.top
46
+ const newRipple: RippleInterface = {
47
+ id: `${Date.now()}-${Math.random()}`,
48
+ x,
49
+ y
50
+ }
51
+ setRipples(prev => [...prev, newRipple])
22
52
  }
23
53
 
24
54
  return (
@@ -31,8 +61,35 @@ const Checkbox: React.FC<CheckboxProps> = ({
31
61
  disabled={disabled}
32
62
  {...rest}
33
63
  />
34
- <CustomCheckbox checked={internalChecked} disabled={disabled} />
35
- {label && <Label disabled={disabled}>{label}</Label>}
64
+ <CustomCheckbox
65
+ checked={internalChecked}
66
+ disabled={disabled}
67
+ onClick={handleRipple}
68
+ >
69
+ {ripples.map(ripple => (
70
+ <RippleContainer
71
+ key={ripple.id}
72
+ style={{
73
+ top: ripple.y - 10,
74
+ left: ripple.x - 10,
75
+ width: 20,
76
+ height: 20
77
+ }}
78
+ onAnimationEnd={() =>
79
+ setRipples(prev => removeRipple(prev, ripple.id))
80
+ }
81
+ />
82
+ ))}
83
+ </CustomCheckbox>
84
+ <div>
85
+ {label && <Label disabled={disabled}>{label}</Label>}
86
+ <CustomLabel
87
+ disabled={disabled}
88
+ weight="fontWeight400"
89
+ >
90
+ {description}
91
+ </CustomLabel>
92
+ </div>
36
93
  </CheckboxWrapper>
37
94
  )
38
95
  }
@@ -3,6 +3,7 @@ import { UseFormRegisterReturn } from 'react-hook-form'
3
3
  export interface CheckboxProps {
4
4
  label?: string
5
5
  checked?: boolean
6
+ description?: string
6
7
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
7
8
  disabled?: boolean
8
9
  register?: UseFormRegisterReturn<string>
@@ -3,14 +3,6 @@ import { ButtonSizeTypes } from '../Button/Button.types'
3
3
 
4
4
  export const IconButtonSizes = (size: ButtonSizeTypes) => {
5
5
  const sizes = {
6
- xs: `
7
- padding: ${spacing.spacing8}px ${spacing.spacing8}px;
8
- border-radius: ${spacing.spacing4}px;
9
- & svg {
10
- width: ${spacing.spacing12}px !important;
11
- height: ${spacing.spacing12}px;
12
- }
13
- `,
14
6
  sm: `
15
7
  padding: ${spacing.spacing12}px ${spacing.spacing12}px;
16
8
  border-radius: ${spacing.spacing4}px;
@@ -20,19 +12,20 @@ export const IconButtonSizes = (size: ButtonSizeTypes) => {
20
12
  }
21
13
  `,
22
14
  md: `
23
- padding: ${spacing.spacing12}px ${spacing.spacing12}px;
15
+ padding: ${spacing.spacing8}px ${spacing.spacing4}px;
24
16
  border-radius: ${spacing.spacing4}px;
17
+ min-width: ${spacing.spacing36}px;
25
18
  & svg {
26
- width: ${spacing.spacing20}px;
27
- height: ${spacing.spacing20}px;
19
+ width: ${spacing.spacing16}px;
20
+ height: ${spacing.spacing16}px;
28
21
  }
29
22
  `,
30
23
  lg: `
31
24
  padding: ${spacing.spacing12}px ${spacing.spacing12}px;
32
25
  border-radius: ${spacing.spacing4}px;
33
26
  & svg {
34
- width: ${spacing.spacing32}px;
35
- height: ${spacing.spacing32}px;
27
+ width: ${spacing.spacing16}px;
28
+ height: ${spacing.spacing16}px;
36
29
  }
37
30
  `
38
31
  }
@@ -1,11 +1,11 @@
1
1
  import { useState } from 'react'
2
2
  import { ButtonProps, RippleInterface } from '../Button/Button.types'
3
- import { ButtonAppearance } from '../Button/Button.appearance'
3
+ import { ButtonVariant } from '../Button/Button.appearance'
4
4
  import { IconButtonSizes } from './IconButton.sizes'
5
5
  import { RippleContainer, StyledButton } from '../Button/Button.styles'
6
6
 
7
7
  const IconButton: React.FC<ButtonProps> = ({
8
- appearance = 'solid',
8
+ variant = 'solid',
9
9
  children,
10
10
  className,
11
11
  color = 'primary',
@@ -18,7 +18,7 @@ const IconButton: React.FC<ButtonProps> = ({
18
18
  const [ripples, setRipples] = useState<RippleInterface[]>([])
19
19
 
20
20
  const buttonSize = IconButtonSizes(size)
21
- const buttonAppearance = ButtonAppearance(color, appearance)
21
+ const buttonVariant = ButtonVariant(color, variant)
22
22
 
23
23
  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
24
24
  const rect = e.currentTarget.getBoundingClientRect()
@@ -43,14 +43,14 @@ const IconButton: React.FC<ButtonProps> = ({
43
43
  disabled={disabled}
44
44
  className={className}
45
45
  $fluid={fluid}
46
- $appearance={buttonAppearance}
46
+ $variant={buttonVariant}
47
47
  onClick={handleClick}
48
48
  $buttonSize={buttonSize}
49
49
  {...rest}>
50
50
  {children}
51
51
  {ripples.map(ripple => (
52
52
  <RippleContainer
53
- $appearance={appearance}
53
+ $variant={variant}
54
54
  key={ripple.id}
55
55
  style={{
56
56
  top: ripple.y - 10,
@@ -0,0 +1,75 @@
1
+ import styled, { css } from 'styled-components'
2
+ import { spacing, fontSize, fontWeight, shadow, lineHeight } from '@liguelead/foundation'
3
+ import { parseColor } from '../../utils'
4
+
5
+ export const OptWrapper = styled.div`
6
+ display: flex;
7
+ gap: ${spacing.spacing16}px;
8
+ `
9
+
10
+ interface OptBoxProps {
11
+ $disabled?: boolean;
12
+ $error?: boolean;
13
+ }
14
+
15
+ export const OptBox = styled.input<OptBoxProps>`
16
+ width: ${spacing.spacing36}px;
17
+ height: ${spacing.spacing36}px;
18
+ text-align: center;
19
+ font-size: ${fontSize.fontSize14}px;
20
+ font-weight: ${fontWeight.fontWeight400};
21
+ border: 1px solid ${({ theme }) => parseColor(theme.colors.neutral400)};
22
+ background: ${({ theme }) => parseColor(theme.colors.white)};
23
+ color: ${({ theme }) => parseColor(theme.colors.neutral1100)};
24
+ border-radius: 4px;
25
+ outline: none;
26
+ transition: border-color .15s ease, box-shadow .15s ease;
27
+
28
+ ${({ $error, theme }) =>
29
+ $error &&
30
+ css`
31
+ border-color: ${parseColor(theme.colors.danger100)};
32
+ `}
33
+
34
+ &:focus {
35
+ ${({ $error, theme }) =>
36
+ $error
37
+ ? css`
38
+ border-color: ${parseColor(theme.colors.danger200)};
39
+ box-shadow: 0 0 0 3px ${parseColor(theme.colors.danger100)}40;
40
+ `
41
+ : css`
42
+ border-color: ${parseColor(theme.colors.neutral700)};
43
+ box-shadow: ${shadow.focusShadow};
44
+ `}
45
+ }
46
+
47
+ ${({ $disabled, theme }) =>
48
+ $disabled &&
49
+ css`
50
+ opacity: 0.5;
51
+ cursor: not-allowed;
52
+ border-color: ${parseColor(theme.colors.neutral400)};
53
+ background: ${parseColor(theme.colors.neutral100)};
54
+ `}
55
+ `
56
+
57
+ export const OtpSeparator = styled.span`
58
+ color: ${({ theme }) => parseColor(theme.colors.neutral700)};
59
+ font-size: 20px;
60
+ user-select: none;
61
+ `
62
+
63
+ export const OtpSeparatorContainer = styled.div`
64
+ display: flex;
65
+ align-items: center;
66
+ `
67
+
68
+ export const OptHelperText = styled.span<{ $error?: boolean }>`
69
+ display: block;
70
+ margin-top: ${spacing.spacing8}px;
71
+ font-size: ${fontSize.fontSize12}px;
72
+ line-height: ${lineHeight.lineHeight16}px;
73
+ color: ${({ theme, $error }) =>
74
+ $error ? parseColor(theme.colors.danger100) : parseColor(theme.colors.neutral700)};
75
+ `