@liguelead/design-system 0.0.10 → 0.0.12

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 (48) 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 +93 -35
  7. package/components/Checkbox/Checkbox.tsx +63 -5
  8. package/components/Checkbox/Checkbox.types.ts +5 -2
  9. package/components/IconButton/IconButton.sizes.ts +6 -13
  10. package/components/IconButton/IconButton.tsx +5 -5
  11. package/components/InputOpt/InputOpt.styles.ts +80 -0
  12. package/components/InputOpt/InputOpt.tsx +168 -0
  13. package/components/InputOpt/InputOpt.types.ts +15 -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/RequiredAsterisk/RequiredAsterisk.style.ts +6 -0
  30. package/components/RequiredAsterisk/RequiredAsterisk.tsx +7 -0
  31. package/components/RequiredAsterisk/index.ts +1 -0
  32. package/components/SegmentedButton/SegmentedButton.tsx +0 -6
  33. package/components/Select/Select.sizes.ts +10 -11
  34. package/components/Select/Select.states.tsx +16 -42
  35. package/components/Select/Select.styles.ts +57 -41
  36. package/components/Select/Select.tsx +38 -24
  37. package/components/Select/Select.types.ts +4 -3
  38. package/components/Text/Text.styles.ts +11 -8
  39. package/components/Text/Text.tsx +2 -2
  40. package/components/Text/Text.types.ts +3 -1
  41. package/components/TextField/TextField.sizes.ts +3 -9
  42. package/components/TextField/TextField.states.tsx +14 -13
  43. package/components/TextField/TextField.styles.ts +5 -3
  44. package/components/TextField/TextField.tsx +6 -2
  45. package/components/TextField/TextField.types.ts +1 -0
  46. package/components/index.ts +3 -0
  47. package/package.json +2 -2
  48. 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,22 @@
1
- import { spacing } from '@liguelead/foundation'
1
+ import {
2
+ spacing,
3
+ fontSize,
4
+ fontWeight,
5
+ radius,
6
+ shadow
7
+ } from '@liguelead/foundation'
2
8
  import { parseColor } from '../../utils'
3
- import styled from 'styled-components'
9
+ import styled, { css } from 'styled-components'
10
+ import Text from '../Text'
4
11
 
5
12
  export const CheckboxWrapper = styled.label`
6
13
  display: flex;
7
- align-items: center;
14
+ align-items: start;
8
15
  cursor: pointer;
9
16
  position: relative;
10
17
  user-select: none;
11
18
  gap: 8px;
12
- font-size: 14px;
19
+ font-size: ${fontSize.fontSize14}px;
13
20
 
14
21
  input {
15
22
  position: absolute;
@@ -17,50 +24,101 @@ export const CheckboxWrapper = styled.label`
17
24
  width: 0;
18
25
  height: 0;
19
26
  }
27
+
28
+ input:focus + span {
29
+ box-shadow: 0 0 0 3px #A3A3A350}
30
+ }
20
31
  `
21
32
 
22
33
  export const CustomCheckbox = styled.span<{
23
34
  checked: boolean
24
35
  disabled?: boolean
36
+ error?: boolean
25
37
  }>`
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'};
38
+ ${({ checked, theme, disabled, error }) => css`
39
+ width: ${spacing.spacing16}px;
40
+ height: ${spacing.spacing16}px;
41
+ border: 1px solid ${checked
42
+ ? parseColor(theme.colors.primary)
43
+ : parseColor(theme.colors.neutral400)};
44
+ border-radius: ${radius.radius4}px;
45
+ display: flex;
46
+ top: 2px;
47
+ align-items: center;
48
+ justify-content: center;
49
+ transition: all 0.2s ease-in-out;
50
+ background-color: ${checked
51
+ ? parseColor(theme.colors.primary)
52
+ : 'transparent'};
53
+ position: relative;
54
+ overflow: hidden;
55
+
56
+ ${disabled &&
57
+ css`
58
+ background-color: transparent;
59
+ border-color: ${parseColor(theme.colors.neutral400)}70;
60
+ cursor: not-allowed;
61
+ `}
36
62
 
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
- `}
63
+ ${error &&
64
+ css`
65
+ border-color: ${parseColor(theme.colors.danger200)};
66
+ box-shadow: ${shadow.errorShadow};
67
+ `}
44
68
 
45
- &::after {
46
- content: '';
47
- width: 16px;
48
- height: 16px;
49
- display: ${({ checked }) => (checked ? 'block' : 'none')};
50
- background-color: white;
69
+ &::after {
70
+ content: '';
71
+ width: 16px;
72
+ height: 16px;
73
+ display: ${checked ? 'block' : 'none'};
74
+ background-color: white;
75
+ z-index: 1;
76
+
77
+ 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")
78
+ no-repeat center / contain;
79
+ -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")
80
+ no-repeat center / contain;
81
+ }
82
+
83
+ `}
84
+ `
51
85
 
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;
86
+ export const RippleContainer = styled.span`
87
+ position: absolute;
88
+ border-radius: 50%;
89
+ transform: scale(0);
90
+ animation: ripple 0.4s linear;
91
+ background-color: rgba(255, 255, 255, 0.6);
92
+ pointer-events: none;
93
+ z-index: 0;
94
+
95
+ @keyframes ripple {
96
+ to {
97
+ transform: scale(3.5);
98
+ opacity: 0;
99
+ }
56
100
  }
57
101
  `
58
102
 
59
103
  export const Label = styled.span<{ disabled?: boolean }>`
60
- font-size: 14px;
61
- font-weight: 500;
104
+ font-size: ${fontSize.fontSize14}px;
105
+ font-weight: ${fontWeight.fontWeight500};
106
+
62
107
  color: ${({ theme, disabled }) =>
63
108
  disabled
64
- ? parseColor(theme.colors.neutral500)
65
- : parseColor(theme.colors.neutral900)};
109
+ ? `${parseColor(theme.colors.textDark)}70`
110
+ : parseColor(theme.colors.textDark)};
111
+ `
112
+
113
+ export const CustomLabel = styled(Text)<{ disabled?: boolean; error?: boolean }>`
114
+ font-size: ${fontSize.fontSize12}px;
115
+ font-weight: ${fontWeight.fontWeight400};
116
+ line-height: 8px;
117
+
118
+ color: ${({ theme, disabled, error }) =>
119
+ disabled
120
+ ? `${parseColor(theme.colors.textMedium)}70`
121
+ : error
122
+ ? parseColor(theme.colors.danger200)
123
+ : parseColor(theme.colors.textMedium)};
66
124
  `
@@ -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,36 @@ const Checkbox: React.FC<CheckboxProps> = ({
9
21
  disabled = false,
10
22
  register,
11
23
  className,
24
+ error,
25
+ children,
26
+ description,
12
27
  ...rest
13
28
  }) => {
14
- // Estado interno para alternar caso `checked` não seja controlado externamente
15
29
  const [internalChecked, setInternalChecked] = useState<boolean>(
16
30
  checked || false
17
31
  )
32
+ const [ripples, setRipples] = useState<RippleInterface[]>([])
33
+
34
+ const removeRipple = (ripples: RippleInterface[], rippleId: string) => {
35
+ return ripples.filter(r => r.id !== rippleId)
36
+ }
18
37
 
19
38
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
20
39
  onChange?.(e)
21
- setInternalChecked(!internalChecked) // Alterna o estado internamente
40
+ setInternalChecked(!internalChecked)
41
+ }
42
+
43
+ const handleRipple = (e: React.MouseEvent<HTMLSpanElement>) => {
44
+ if (disabled) return
45
+ const rect = e.currentTarget.getBoundingClientRect()
46
+ const x = e.clientX - rect.left
47
+ const y = e.clientY - rect.top
48
+ const newRipple: RippleInterface = {
49
+ id: `${Date.now()}-${Math.random()}`,
50
+ x,
51
+ y
52
+ }
53
+ setRipples(prev => [...prev, newRipple])
22
54
  }
23
55
 
24
56
  return (
@@ -31,8 +63,34 @@ const Checkbox: React.FC<CheckboxProps> = ({
31
63
  disabled={disabled}
32
64
  {...rest}
33
65
  />
34
- <CustomCheckbox checked={internalChecked} disabled={disabled} />
35
- {label && <Label disabled={disabled}>{label}</Label>}
66
+ <CustomCheckbox
67
+ checked={internalChecked}
68
+ disabled={disabled}
69
+ error={!!error}
70
+ onClick={handleRipple}>
71
+ {ripples.map(ripple => (
72
+ <RippleContainer
73
+ key={ripple.id}
74
+ style={{
75
+ top: ripple.y - 10,
76
+ left: ripple.x - 10,
77
+ width: 20,
78
+ height: 20
79
+ }}
80
+ onAnimationEnd={() =>
81
+ setRipples(prev => removeRipple(prev, ripple.id))
82
+ }
83
+ />
84
+ ))}
85
+ </CustomCheckbox>
86
+ <div>
87
+ {label ? <Label disabled={disabled}>{label}</Label> : children}
88
+ {(description || error) && (
89
+ <CustomLabel disabled={disabled} weight="fontWeight400">
90
+ {error?.message || description}
91
+ </CustomLabel>
92
+ )}
93
+ </div>
36
94
  </CheckboxWrapper>
37
95
  )
38
96
  }
@@ -1,8 +1,11 @@
1
- import { UseFormRegisterReturn } from 'react-hook-form'
1
+ import { FieldValues, UseFormRegisterReturn } from 'react-hook-form'
2
2
 
3
- export interface CheckboxProps {
3
+ export interface CheckboxProps<TFieldValues extends FieldValues = FieldValues> {
4
4
  label?: string
5
5
  checked?: boolean
6
+ error?: TFieldValues
7
+ description?: string
8
+ children?: React.ReactNode
6
9
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
7
10
  disabled?: boolean
8
11
  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,80 @@
1
+ import styled, { css } from 'styled-components'
2
+ import { spacing, fontSize, fontWeight, shadow, lineHeight } from '@liguelead/foundation'
3
+ import { parseColor } from '../../utils'
4
+
5
+ interface OptBoxProps {
6
+ $disabled?: boolean;
7
+ $error?: boolean;
8
+ }
9
+
10
+ export const OptWrapper = styled.div`
11
+ display: flex;
12
+ gap: ${spacing.spacing8}px;
13
+ `
14
+
15
+ export const OptContainer = styled.div`
16
+ display: flex;
17
+ flex-direction: column;
18
+ gap: ${spacing.spacing4}px;
19
+ `
20
+
21
+ export const OptBox = styled.input<OptBoxProps>`
22
+ width: ${spacing.spacing36}px;
23
+ height: ${spacing.spacing36}px;
24
+ text-align: center;
25
+ font-size: ${fontSize.fontSize14}px;
26
+ font-weight: ${fontWeight.fontWeight400};
27
+ border: 1px solid ${({ theme }) => parseColor(theme.colors.neutral400)};
28
+ background: ${({ theme }) => parseColor(theme.colors.white)};
29
+ color: ${({ theme }) => parseColor(theme.colors.neutral1100)};
30
+ border-radius: 4px;
31
+ outline: none;
32
+ transition: border-color .15s ease, box-shadow .15s ease;
33
+
34
+ ${({ $error, theme }) =>
35
+ $error &&
36
+ css`
37
+ border-color: ${parseColor(theme.colors.danger100)};
38
+ `}
39
+
40
+ &:focus {
41
+ ${({ $error, theme }) =>
42
+ $error
43
+ ? css`
44
+ border-color: ${parseColor(theme.colors.danger200)};
45
+ box-shadow: ${shadow.errorShadow};
46
+ `
47
+ : css`
48
+ border-color: ${parseColor(theme.colors.neutral700)};
49
+ box-shadow: ${shadow.focusShadow};
50
+ `}
51
+ }
52
+
53
+ ${({ $disabled, theme }) =>
54
+ $disabled &&
55
+ css`
56
+ opacity: 0.5;
57
+ cursor: not-allowed;
58
+ border-color: ${parseColor(theme.colors.neutral400)};
59
+ background: ${parseColor(theme.colors.neutral100)};
60
+ `}
61
+ `
62
+
63
+ export const OtpSeparator = styled.span`
64
+ width: 14px;
65
+ border: 1px solid ${({ theme }) => parseColor(theme.colors.neutral700)};
66
+ border-radius: 8px;
67
+ `
68
+
69
+ export const OtpSeparatorContainer = styled.div`
70
+ display: flex;
71
+ align-items: center;
72
+ `
73
+
74
+ export const OptHelperText = styled.span<{ $error?: boolean }>`
75
+ display: block;
76
+ font-size: ${fontSize.fontSize12}px;
77
+ line-height: ${lineHeight.lineHeight16}px;
78
+ color: ${({ theme, $error }) =>
79
+ $error ? parseColor(theme.colors.danger100) : parseColor(theme.colors.neutral700)};
80
+ `