@liguelead/design-system 0.0.30 → 0.0.32
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/components/Alert/Alert.stories.tsx +94 -18
- package/components/Badge/Badge.stories.tsx +114 -0
- package/components/Badge/Badge.styles.ts +36 -0
- package/components/Badge/Badge.tsx +23 -0
- package/components/Badge/Badge.types.ts +11 -0
- package/components/Badge/index.ts +2 -0
- package/components/Button/Button.appearance.ts +1 -1
- package/components/Button/Button.stories.tsx +99 -18
- package/components/Checkbox/Checkbox.stories.tsx +107 -7
- package/components/DatePicker/DatePicker.styles.ts +1 -0
- package/components/DatePicker/DatePicker.tsx +9 -10
- package/components/IconButton/IconButton.sizes.ts +7 -7
- package/components/IconButton/IconButton.tsx +0 -1
- package/components/InputOpt/InputOpt.stories.tsx +30 -44
- package/components/Select/Select.stories.tsx +80 -19
- package/components/Select/Select.tsx +7 -9
- package/components/Table/Datatable.stories.tsx +186 -0
- package/components/Table/Table.stories.tsx +127 -46
- package/components/Table/Table.styles.ts +83 -8
- package/components/Table/Table.tsx +292 -142
- package/components/Table/Table.types.ts +104 -12
- package/components/Table/components/ColumnVisibility/ColumnVisibility.style.ts +46 -0
- package/components/Table/components/ColumnVisibility/ColumnVisibility.tsx +55 -0
- package/components/Table/components/DatatableColumnFilterMenu/DatatableColumnFilterMenu.styles.ts +120 -0
- package/components/Table/components/DatatableColumnFilterMenu/DatatableColumnFilterMenu.tsx +228 -0
- package/components/Table/components/DatatableColumnFilterMenu/index.ts +1 -0
- package/components/Table/components/DatatableTopBar/DatatableTopBar.styles.ts +25 -0
- package/components/Table/components/DatatableTopBar/DatatableTopBar.tsx +89 -0
- package/components/Table/components/DatatableTopBar/index.ts +1 -0
- package/components/Table/components/SearchInput/SearchInput.tsx +30 -0
- package/components/Table/components/TableHeader/TableHeader.tsx +98 -0
- package/components/Table/components/TablePagination/TablePagination.tsx +78 -0
- package/components/Table/components/index.ts +6 -0
- package/components/Table/hooks/useDatatableFilters.ts +88 -0
- package/components/Table/stories.fixtures.ts +100 -0
- package/components/Table/tanstack-table.d.ts +10 -0
- package/components/Table/utils/dateRangeFilterFn.ts +33 -0
- package/components/Table/utils/index.ts +2 -1
- package/components/Tabs/Tabs.stories.tsx +152 -0
- package/components/Tabs/Tabs.styles.ts +12 -0
- package/components/Tabs/Tabs.tsx +34 -0
- package/components/Tabs/Tabs.types.ts +15 -0
- package/components/Tabs/index.ts +2 -0
- package/components/TextField/TextField.stories.tsx +135 -12
- package/components/index.ts +3 -0
- package/package.json +3 -2
|
@@ -6,55 +6,131 @@ const meta: Meta<typeof Alert> = {
|
|
|
6
6
|
component: Alert,
|
|
7
7
|
parameters: {
|
|
8
8
|
layout: 'padded',
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component: `
|
|
12
|
+
Componente de alerta para comunicar mensagens de feedback ao usuário.
|
|
13
|
+
|
|
14
|
+
**Quando usar cada variante:**
|
|
15
|
+
- \`default\` — informações gerais ou neutras
|
|
16
|
+
- \`info\` — dicas, orientações ou informações complementares
|
|
17
|
+
- \`success\` — confirmação de ação concluída com sucesso
|
|
18
|
+
- \`warning\` — atenção necessária, mas não crítica
|
|
19
|
+
- \`danger\` — erros, falhas ou ações destrutivas
|
|
20
|
+
|
|
21
|
+
**Boas práticas:**
|
|
22
|
+
- Use títulos curtos e objetivos
|
|
23
|
+
- A descrição deve complementar, não repetir o título
|
|
24
|
+
- Use \`hasButton\` apenas quando houver uma ação clara para o usuário
|
|
25
|
+
`,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
},
|
|
10
29
|
tags: ['autodocs'],
|
|
11
30
|
argTypes: {
|
|
12
31
|
variant: {
|
|
13
32
|
control: 'select',
|
|
14
33
|
options: ['default', 'danger', 'warning', 'info', 'success'],
|
|
15
|
-
description: '
|
|
34
|
+
description: 'Variante visual do alerta',
|
|
35
|
+
table: { defaultValue: { summary: 'default' } },
|
|
16
36
|
},
|
|
17
37
|
title: {
|
|
18
38
|
control: 'text',
|
|
19
|
-
description: '
|
|
39
|
+
description: 'Título do alerta (obrigatório)',
|
|
20
40
|
},
|
|
21
41
|
description: {
|
|
22
42
|
control: 'text',
|
|
23
|
-
description: '
|
|
43
|
+
description: 'Descrição complementar do alerta',
|
|
24
44
|
},
|
|
25
45
|
hasButton: {
|
|
26
46
|
control: 'boolean',
|
|
27
|
-
description: '
|
|
47
|
+
description: 'Exibe botão de ação',
|
|
48
|
+
table: { defaultValue: { summary: 'false' } },
|
|
28
49
|
},
|
|
29
50
|
buttonLabel: {
|
|
30
51
|
control: 'text',
|
|
31
|
-
description: '
|
|
52
|
+
description: 'Texto do botão de ação',
|
|
32
53
|
},
|
|
33
54
|
href: {
|
|
34
55
|
control: 'text',
|
|
35
|
-
description: '
|
|
36
|
-
}
|
|
56
|
+
description: 'URL do botão de ação',
|
|
57
|
+
},
|
|
37
58
|
},
|
|
38
59
|
}
|
|
39
60
|
|
|
40
61
|
export default meta
|
|
41
62
|
type Story = StoryObj<typeof meta>
|
|
42
63
|
|
|
43
|
-
export const
|
|
64
|
+
export const Default: Story = {
|
|
65
|
+
args: {
|
|
66
|
+
title: 'Informação importante',
|
|
67
|
+
description: 'Esta é uma mensagem de alerta padrão.',
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const TodasVariantes: Story = {
|
|
72
|
+
name: 'Todas as variantes',
|
|
73
|
+
parameters: {
|
|
74
|
+
docs: { description: { story: 'Visão geral de todas as variantes disponíveis.' } },
|
|
75
|
+
},
|
|
44
76
|
render: () => (
|
|
45
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap:
|
|
46
|
-
<Alert variant="default" title="Default
|
|
47
|
-
<Alert variant="info" title="Info
|
|
48
|
-
<Alert variant="success" title="
|
|
49
|
-
<Alert variant="warning" title="
|
|
50
|
-
<Alert variant="danger" title="
|
|
77
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
78
|
+
<Alert variant="default" title="Default" description="Informação geral ou neutra." />
|
|
79
|
+
<Alert variant="info" title="Info" description="Dica ou orientação complementar." />
|
|
80
|
+
<Alert variant="success" title="Sucesso" description="Ação concluída com sucesso." />
|
|
81
|
+
<Alert variant="warning" title="Atenção" description="Requer atenção, mas não é crítico." />
|
|
82
|
+
<Alert variant="danger" title="Erro" description="Falha ou ação destrutiva detectada." />
|
|
51
83
|
</div>
|
|
52
84
|
),
|
|
53
85
|
}
|
|
54
86
|
|
|
55
|
-
export const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
description: '
|
|
87
|
+
export const ComBotao: Story = {
|
|
88
|
+
name: 'Com botão de ação',
|
|
89
|
+
parameters: {
|
|
90
|
+
docs: { description: { story: 'Use `hasButton` quando houver uma ação clara para o usuário tomar.' } },
|
|
59
91
|
},
|
|
92
|
+
render: () => (
|
|
93
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
94
|
+
<Alert variant="info" title="Nova versão disponível" description="Uma atualização está pronta para ser instalada." hasButton buttonLabel="Atualizar agora" href="#" />
|
|
95
|
+
<Alert variant="warning" title="Sessão expirando" description="Sua sessão expira em 5 minutos." hasButton buttonLabel="Renovar sessão" href="#" />
|
|
96
|
+
<Alert variant="danger" title="Falha no pagamento" description="Não foi possível processar seu pagamento." hasButton buttonLabel="Tentar novamente" href="#" />
|
|
97
|
+
</div>
|
|
98
|
+
),
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const SemDescricao: Story = {
|
|
102
|
+
name: 'Sem descrição',
|
|
103
|
+
parameters: {
|
|
104
|
+
docs: { description: { story: 'Alertas podem ser usados apenas com título quando a mensagem é autoexplicativa.' } },
|
|
105
|
+
},
|
|
106
|
+
render: () => (
|
|
107
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
108
|
+
<Alert variant="success" title="Salvo com sucesso." />
|
|
109
|
+
<Alert variant="danger" title="Erro ao carregar os dados." />
|
|
110
|
+
</div>
|
|
111
|
+
),
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export const ExemploFormulario: Story = {
|
|
115
|
+
name: 'Exemplo: Feedback de formulário',
|
|
116
|
+
parameters: {
|
|
117
|
+
docs: { description: { story: 'Padrão de uso em formulários para comunicar resultado de submissão.' } },
|
|
118
|
+
},
|
|
119
|
+
render: () => (
|
|
120
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12, width: 480 }}>
|
|
121
|
+
<Alert
|
|
122
|
+
variant="success"
|
|
123
|
+
title="Cadastro realizado com sucesso!"
|
|
124
|
+
description="Você receberá um e-mail de confirmação em breve."
|
|
125
|
+
/>
|
|
126
|
+
<Alert
|
|
127
|
+
variant="danger"
|
|
128
|
+
title="Não foi possível salvar"
|
|
129
|
+
description="Verifique os campos obrigatórios e tente novamente."
|
|
130
|
+
hasButton
|
|
131
|
+
buttonLabel="Ver erros"
|
|
132
|
+
href="#"
|
|
133
|
+
/>
|
|
134
|
+
</div>
|
|
135
|
+
),
|
|
60
136
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { CheckCircleIcon, ArrowRightIcon, XCircleIcon, InfoIcon, WarningCircleIcon } from '@phosphor-icons/react'
|
|
3
|
+
import { themes } from '@liguelead/foundation'
|
|
4
|
+
import Badge from './Badge'
|
|
5
|
+
|
|
6
|
+
const colorOptions = Object.keys(themes.spa.colors)
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof Badge> = {
|
|
9
|
+
title: 'Data Display/Badge',
|
|
10
|
+
component: Badge,
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: 'centered',
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component: `
|
|
16
|
+
Badge compacto para destacar status, categorias ou contagens.
|
|
17
|
+
|
|
18
|
+
**Props principais:**
|
|
19
|
+
- \`color\` — qualquer token de cor do tema (ex: \`primary\`, \`danger200\`, \`secondary\`)
|
|
20
|
+
- \`showLeftIcon\` / \`showRightIcon\` — exibe ícones nas extremidades
|
|
21
|
+
`,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
tags: ['autodocs'],
|
|
26
|
+
argTypes: {
|
|
27
|
+
color: {
|
|
28
|
+
control: 'select',
|
|
29
|
+
options: colorOptions,
|
|
30
|
+
description: 'Cor de fundo do badge (token do tema)',
|
|
31
|
+
table: { defaultValue: { summary: 'primary' } },
|
|
32
|
+
},
|
|
33
|
+
children: {
|
|
34
|
+
control: 'text',
|
|
35
|
+
description: 'Texto exibido no badge',
|
|
36
|
+
table: { defaultValue: { summary: 'Badge' } },
|
|
37
|
+
},
|
|
38
|
+
showLeftIcon: {
|
|
39
|
+
control: 'boolean',
|
|
40
|
+
description: 'Exibe ícone à esquerda',
|
|
41
|
+
table: { defaultValue: { summary: 'false' } },
|
|
42
|
+
},
|
|
43
|
+
showRightIcon: {
|
|
44
|
+
control: 'boolean',
|
|
45
|
+
description: 'Exibe ícone à direita',
|
|
46
|
+
table: { defaultValue: { summary: 'false' } },
|
|
47
|
+
},
|
|
48
|
+
leftIcon: { control: false },
|
|
49
|
+
rightIcon: { control: false },
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default meta
|
|
54
|
+
type Story = StoryObj<typeof meta>
|
|
55
|
+
|
|
56
|
+
export const Default: Story = {
|
|
57
|
+
args: {
|
|
58
|
+
children: 'Ativo',
|
|
59
|
+
color: 'success50',
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const Danger: Story = {
|
|
64
|
+
args: {
|
|
65
|
+
children: 'Erro',
|
|
66
|
+
color: 'danger50',
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const Secondary: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
children: 'Categoria',
|
|
73
|
+
color: 'warning50',
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const ComIconeEsquerdo: Story = {
|
|
78
|
+
name: 'Com ícone esquerdo',
|
|
79
|
+
args: {
|
|
80
|
+
children: 'Verificado',
|
|
81
|
+
color: 'success50',
|
|
82
|
+
showLeftIcon: true,
|
|
83
|
+
leftIcon: <CheckCircleIcon size={16} />,
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const ComIconeDireito: Story = {
|
|
88
|
+
name: 'Com ícone direito',
|
|
89
|
+
args: {
|
|
90
|
+
children: 'Ver mais',
|
|
91
|
+
color: 'success50',
|
|
92
|
+
showRightIcon: true,
|
|
93
|
+
rightIcon: <ArrowRightIcon size={16} />,
|
|
94
|
+
},
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const TodasAsCores: Story = {
|
|
98
|
+
name: 'Exemplo: Status de pedido',
|
|
99
|
+
render: () => (
|
|
100
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12, fontFamily: 'Manrope, sans-serif' }}>
|
|
101
|
+
{[
|
|
102
|
+
{ id: '#1042', status: 'Aprovado', color: 'primary' as const, icon: <CheckCircleIcon size={16} /> },
|
|
103
|
+
{ id: '#1043', status: 'Pendente', color: 'warning100' as const, icon: <InfoIcon size={16} /> },
|
|
104
|
+
{ id: '#1044', status: 'Cancelado', color: 'danger200' as const, icon: <XCircleIcon size={16} /> },
|
|
105
|
+
{ id: '#1045', status: 'Em análise', color: 'secondary' as const, icon: <WarningCircleIcon size={16} /> },
|
|
106
|
+
].map(({ id, status, color, icon }) => (
|
|
107
|
+
<div key={id} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '8px 12px', border: '1px solid #e5e7eb', borderRadius: 6, width: 280 }}>
|
|
108
|
+
<span style={{ fontSize: 14, color: '#374151' }}>Pedido {id}</span>
|
|
109
|
+
<Badge color={color} showLeftIcon leftIcon={icon}>{status}</Badge>
|
|
110
|
+
</div>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
113
|
+
),
|
|
114
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import styled, { DefaultTheme } from 'styled-components'
|
|
2
|
+
import { spacing, fontSize, fontWeight, lineHeight, radius } from '@liguelead/foundation'
|
|
3
|
+
import { getTextColor, parseColor } from '../../utils'
|
|
4
|
+
import { colorType } from '../../types'
|
|
5
|
+
|
|
6
|
+
const getBadgeColors = (theme: DefaultTheme, color: colorType) => {
|
|
7
|
+
const parsedColor = parseColor(theme.colors[color])
|
|
8
|
+
return {
|
|
9
|
+
background: parsedColor,
|
|
10
|
+
text: parseColor(theme.colors[getTextColor(parsedColor)]),
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const StyledBadge = styled.span<{ $color: colorType }>`
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
gap: ${spacing.spacing4}px;
|
|
19
|
+
padding: ${spacing.spacing2}px ${spacing.spacing8}px;
|
|
20
|
+
border-radius: ${radius.radius4}px;
|
|
21
|
+
font-size: ${fontSize.fontSize12}px;
|
|
22
|
+
font-weight: ${fontWeight.fontWeight500};
|
|
23
|
+
line-height: ${lineHeight.lineHeight16}px;
|
|
24
|
+
font-family: Manrope, sans-serif;
|
|
25
|
+
white-space: nowrap;
|
|
26
|
+
|
|
27
|
+
background-color: ${({ theme, $color }) => getBadgeColors(theme, $color).background};
|
|
28
|
+
|
|
29
|
+
color: ${({ theme, $color }) => getBadgeColors(theme, $color).text};
|
|
30
|
+
|
|
31
|
+
& svg {
|
|
32
|
+
width: 16px;
|
|
33
|
+
height: 16px;
|
|
34
|
+
flex-shrink: 0;
|
|
35
|
+
}
|
|
36
|
+
`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { StyledBadge } from './Badge.styles'
|
|
2
|
+
import { TBadgeProps } from './Badge.types'
|
|
3
|
+
|
|
4
|
+
const Badge = ({
|
|
5
|
+
children = 'Badge',
|
|
6
|
+
className,
|
|
7
|
+
color = 'primary',
|
|
8
|
+
leftIcon,
|
|
9
|
+
rightIcon,
|
|
10
|
+
showLeftIcon = false,
|
|
11
|
+
showRightIcon = false,
|
|
12
|
+
}: TBadgeProps) => {
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<StyledBadge $color={color} className={className}>
|
|
16
|
+
{showLeftIcon && leftIcon}
|
|
17
|
+
{children}
|
|
18
|
+
{showRightIcon && rightIcon}
|
|
19
|
+
</StyledBadge>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default Badge
|
|
@@ -75,7 +75,7 @@ export const ButtonVariant = (
|
|
|
75
75
|
neutralOutline: `
|
|
76
76
|
background-color: transparent;
|
|
77
77
|
color: ${parseColor(theme.colors.textDark)};
|
|
78
|
-
border: 1px solid ${parseColor(theme.colors.
|
|
78
|
+
border: 1px solid ${parseColor(theme.colors.neutral400)};
|
|
79
79
|
|
|
80
80
|
&:hover {
|
|
81
81
|
background-color: ${parseColor(theme.colors.primaryDarker)};
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import { themes } from '@liguelead/foundation'
|
|
3
|
+
import { PlusIcon, ArrowRightIcon, TrashIcon } from '@phosphor-icons/react'
|
|
3
4
|
import Button from './Button'
|
|
4
5
|
import type { ButtonVariantTypes } from './Button.types'
|
|
5
6
|
|
|
6
7
|
const themeColors = Object.keys(themes.spa.colors)
|
|
7
8
|
const buttonVariantOptions: ButtonVariantTypes[] = [
|
|
8
|
-
'solid',
|
|
9
|
-
'outline',
|
|
10
|
-
'ghost',
|
|
11
|
-
'neutralOutline',
|
|
12
|
-
'neutralGhost'
|
|
9
|
+
'solid', 'outline', 'ghost', 'neutralOutline', 'neutralGhost',
|
|
13
10
|
]
|
|
14
11
|
|
|
15
12
|
const meta: Meta<typeof Button> = {
|
|
@@ -17,35 +14,53 @@ const meta: Meta<typeof Button> = {
|
|
|
17
14
|
component: Button,
|
|
18
15
|
parameters: {
|
|
19
16
|
layout: 'centered',
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: `
|
|
20
|
+
Botão de ação principal do design system.
|
|
21
|
+
|
|
22
|
+
**Quando usar cada variante:**
|
|
23
|
+
- \`solid\` — ação primária da tela (ex: Salvar, Confirmar)
|
|
24
|
+
- \`outline\` — ação secundária com destaque (ex: Editar)
|
|
25
|
+
- \`ghost\` — ação terciária ou em contextos com fundo colorido
|
|
26
|
+
- \`neutralOutline\` / \`neutralGhost\` — ações neutras, cancelar, voltar
|
|
27
|
+
`,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
20
30
|
},
|
|
21
31
|
tags: ['autodocs'],
|
|
22
32
|
argTypes: {
|
|
23
33
|
variant: {
|
|
24
34
|
control: 'select',
|
|
25
35
|
options: buttonVariantOptions,
|
|
26
|
-
description: '
|
|
36
|
+
description: 'Variante visual do botão',
|
|
37
|
+
table: { defaultValue: { summary: 'solid' } },
|
|
27
38
|
},
|
|
28
39
|
size: {
|
|
29
40
|
control: 'select',
|
|
30
41
|
options: ['sm', 'md', 'lg'],
|
|
31
|
-
description: '
|
|
42
|
+
description: 'Tamanho do botão',
|
|
43
|
+
table: { defaultValue: { summary: 'md' } },
|
|
32
44
|
},
|
|
33
45
|
color: {
|
|
34
46
|
control: 'select',
|
|
35
47
|
options: themeColors,
|
|
36
|
-
description: '
|
|
48
|
+
description: 'Cor do botão baseada nos tokens do tema',
|
|
49
|
+
table: { defaultValue: { summary: 'primary' } },
|
|
37
50
|
},
|
|
38
51
|
disabled: {
|
|
39
52
|
control: 'boolean',
|
|
40
|
-
description: '
|
|
53
|
+
description: 'Desabilita o botão',
|
|
54
|
+
table: { defaultValue: { summary: 'false' } },
|
|
41
55
|
},
|
|
42
56
|
fullWidth: {
|
|
43
57
|
control: 'boolean',
|
|
44
|
-
description: '
|
|
58
|
+
description: 'Ocupa 100% da largura do container',
|
|
59
|
+
table: { defaultValue: { summary: 'false' } },
|
|
45
60
|
},
|
|
46
61
|
children: {
|
|
47
62
|
control: 'text',
|
|
48
|
-
description: '
|
|
63
|
+
description: 'Conteúdo do botão',
|
|
49
64
|
},
|
|
50
65
|
},
|
|
51
66
|
}
|
|
@@ -54,17 +69,16 @@ export default meta
|
|
|
54
69
|
type Story = StoryObj<typeof meta>
|
|
55
70
|
|
|
56
71
|
export const Default: Story = {
|
|
57
|
-
args: {
|
|
58
|
-
children: 'Button',
|
|
59
|
-
},
|
|
72
|
+
args: { children: 'Confirmar' },
|
|
60
73
|
}
|
|
61
74
|
|
|
62
|
-
export const
|
|
63
|
-
|
|
64
|
-
|
|
75
|
+
export const Variantes: Story = {
|
|
76
|
+
name: 'Todas as variantes',
|
|
77
|
+
parameters: {
|
|
78
|
+
docs: { description: { story: 'Todas as variantes disponíveis com a cor primária.' } },
|
|
65
79
|
},
|
|
66
80
|
render: (args) => (
|
|
67
|
-
<div style={{ display: 'flex', gap:
|
|
81
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
|
|
68
82
|
<Button {...args} variant="solid">Solid</Button>
|
|
69
83
|
<Button {...args} variant="outline">Outline</Button>
|
|
70
84
|
<Button {...args} variant="ghost">Ghost</Button>
|
|
@@ -73,3 +87,70 @@ export const Variants: Story = {
|
|
|
73
87
|
</div>
|
|
74
88
|
),
|
|
75
89
|
}
|
|
90
|
+
|
|
91
|
+
export const Tamanhos: Story = {
|
|
92
|
+
name: 'Tamanhos',
|
|
93
|
+
parameters: {
|
|
94
|
+
docs: { description: { story: 'Três tamanhos disponíveis: `sm`, `md` e `lg`.' } },
|
|
95
|
+
},
|
|
96
|
+
render: () => (
|
|
97
|
+
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
|
98
|
+
<Button size="sm">Pequeno</Button>
|
|
99
|
+
<Button size="md">Médio</Button>
|
|
100
|
+
<Button size="lg">Grande</Button>
|
|
101
|
+
</div>
|
|
102
|
+
),
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const Desabilitado: Story = {
|
|
106
|
+
name: 'Estado desabilitado',
|
|
107
|
+
parameters: {
|
|
108
|
+
docs: { description: { story: 'Estado `disabled` em todas as variantes.' } },
|
|
109
|
+
},
|
|
110
|
+
render: () => (
|
|
111
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
|
112
|
+
<Button disabled variant="solid">Solid</Button>
|
|
113
|
+
<Button disabled variant="outline">Outline</Button>
|
|
114
|
+
<Button disabled variant="ghost">Ghost</Button>
|
|
115
|
+
</div>
|
|
116
|
+
),
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const LarguraTotal: Story = {
|
|
120
|
+
name: 'Largura total',
|
|
121
|
+
parameters: {
|
|
122
|
+
docs: { description: { story: 'Use `fullWidth` em formulários ou containers de largura definida.' } },
|
|
123
|
+
},
|
|
124
|
+
render: () => (
|
|
125
|
+
<div style={{ width: 320 }}>
|
|
126
|
+
<Button fullWidth>Entrar</Button>
|
|
127
|
+
</div>
|
|
128
|
+
),
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const ComIcones: Story = {
|
|
132
|
+
name: 'Com ícones',
|
|
133
|
+
parameters: {
|
|
134
|
+
docs: { description: { story: 'Combine com ícones do Phosphor para reforçar a ação.' } },
|
|
135
|
+
},
|
|
136
|
+
render: () => (
|
|
137
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
|
|
138
|
+
<Button><PlusIcon size={16} /> Adicionar</Button>
|
|
139
|
+
<Button variant="outline">Próximo <ArrowRightIcon size={16} /></Button>
|
|
140
|
+
<Button variant="ghost" color="danger200"><TrashIcon size={16} /> Excluir</Button>
|
|
141
|
+
</div>
|
|
142
|
+
),
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const ExemploFormulario: Story = {
|
|
146
|
+
name: 'Exemplo: Rodapé de formulário',
|
|
147
|
+
parameters: {
|
|
148
|
+
docs: { description: { story: 'Padrão comum de ações em formulários: ação primária + cancelar.' } },
|
|
149
|
+
},
|
|
150
|
+
render: () => (
|
|
151
|
+
<div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', padding: 16, border: '1px solid #e5e7eb', borderRadius: 8, width: 400 }}>
|
|
152
|
+
<Button variant="neutralGhost">Cancelar</Button>
|
|
153
|
+
<Button variant="solid">Salvar alterações</Button>
|
|
154
|
+
</div>
|
|
155
|
+
),
|
|
156
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { useState } from 'react'
|
|
2
3
|
import Checkbox from './Checkbox'
|
|
3
4
|
|
|
4
5
|
const meta: Meta<typeof Checkbox> = {
|
|
@@ -6,29 +7,48 @@ const meta: Meta<typeof Checkbox> = {
|
|
|
6
7
|
component: Checkbox,
|
|
7
8
|
parameters: {
|
|
8
9
|
layout: 'centered',
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: `
|
|
13
|
+
Checkbox para seleção de uma ou múltiplas opções independentes.
|
|
14
|
+
|
|
15
|
+
**Quando usar:**
|
|
16
|
+
- Seleção múltipla em listas de opções
|
|
17
|
+
- Aceite de termos e condições
|
|
18
|
+
- Filtros que podem ser combinados
|
|
19
|
+
|
|
20
|
+
**Não usar para:**
|
|
21
|
+
- Seleção exclusiva (use RadioButton)
|
|
22
|
+
- Ativar/desativar configurações em tempo real (use Toggle)
|
|
23
|
+
`,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
9
26
|
},
|
|
10
27
|
tags: ['autodocs'],
|
|
11
28
|
argTypes: {
|
|
12
29
|
label: {
|
|
13
30
|
control: 'text',
|
|
14
|
-
description: '
|
|
31
|
+
description: 'Texto do label do checkbox',
|
|
15
32
|
},
|
|
16
33
|
description: {
|
|
17
34
|
control: 'text',
|
|
18
|
-
description: '
|
|
35
|
+
description: 'Descrição complementar abaixo do label',
|
|
19
36
|
},
|
|
20
37
|
checked: {
|
|
21
38
|
control: 'boolean',
|
|
22
|
-
description: '
|
|
39
|
+
description: 'Estado marcado do checkbox',
|
|
40
|
+
table: { defaultValue: { summary: 'false' } },
|
|
23
41
|
},
|
|
24
42
|
disabled: {
|
|
25
43
|
control: 'boolean',
|
|
26
|
-
description: '
|
|
44
|
+
description: 'Desabilita o checkbox',
|
|
45
|
+
table: { defaultValue: { summary: 'false' } },
|
|
27
46
|
},
|
|
28
47
|
$hasError: {
|
|
29
48
|
control: 'boolean',
|
|
30
|
-
description: '
|
|
31
|
-
|
|
49
|
+
description: 'Estado de erro',
|
|
50
|
+
table: { defaultValue: { summary: 'false' } },
|
|
51
|
+
},
|
|
32
52
|
},
|
|
33
53
|
}
|
|
34
54
|
|
|
@@ -37,6 +57,86 @@ type Story = StoryObj<typeof meta>
|
|
|
37
57
|
|
|
38
58
|
export const Default: Story = {
|
|
39
59
|
args: {
|
|
40
|
-
label: '
|
|
60
|
+
label: 'Aceito os termos de uso',
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const ComDescricao: Story = {
|
|
65
|
+
name: 'Com descrição',
|
|
66
|
+
parameters: {
|
|
67
|
+
docs: { description: { story: 'Use a descrição para dar contexto adicional à opção.' } },
|
|
68
|
+
},
|
|
69
|
+
args: {
|
|
70
|
+
label: 'Receber notificações',
|
|
71
|
+
description: 'Enviaremos atualizações sobre sua conta por e-mail.',
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const Marcado: Story = {
|
|
76
|
+
name: 'Estado marcado',
|
|
77
|
+
args: {
|
|
78
|
+
label: 'Opção selecionada',
|
|
79
|
+
checked: true,
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const Desabilitado: Story = {
|
|
84
|
+
name: 'Estado desabilitado',
|
|
85
|
+
parameters: {
|
|
86
|
+
docs: { description: { story: 'Estado desabilitado — marcado e desmarcado.' } },
|
|
87
|
+
},
|
|
88
|
+
render: () => (
|
|
89
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
90
|
+
<Checkbox label="Desabilitado desmarcado" disabled />
|
|
91
|
+
<Checkbox label="Desabilitado marcado" disabled checked />
|
|
92
|
+
</div>
|
|
93
|
+
),
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const ComErro: Story = {
|
|
97
|
+
name: 'Estado de erro',
|
|
98
|
+
parameters: {
|
|
99
|
+
docs: { description: { story: 'Use para indicar que o campo é obrigatório e não foi preenchido.' } },
|
|
100
|
+
},
|
|
101
|
+
args: {
|
|
102
|
+
label: 'Aceito os termos de uso',
|
|
103
|
+
$hasError: true,
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const ExemploGrupo: Story = {
|
|
108
|
+
name: 'Exemplo: Grupo de checkboxes',
|
|
109
|
+
parameters: {
|
|
110
|
+
docs: { description: { story: 'Padrão de uso em formulários com múltiplas opções selecionáveis.' } },
|
|
111
|
+
},
|
|
112
|
+
render: () => {
|
|
113
|
+
const [selected, setSelected] = useState<string[]>(['email'])
|
|
114
|
+
const options = [
|
|
115
|
+
{ value: 'email', label: 'E-mail', description: 'Notificações por e-mail' },
|
|
116
|
+
{ value: 'sms', label: 'SMS', description: 'Mensagens de texto' },
|
|
117
|
+
{ value: 'push', label: 'Push', description: 'Notificações no app' },
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
const toggle = (value: string) =>
|
|
121
|
+
setSelected(prev =>
|
|
122
|
+
prev.includes(value) ? prev.filter(v => v !== value) : [...prev, value]
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
127
|
+
<p style={{ fontSize: 14, fontWeight: 600, marginBottom: 4, fontFamily: 'Manrope, sans-serif' }}>
|
|
128
|
+
Canais de notificação
|
|
129
|
+
</p>
|
|
130
|
+
{options.map(opt => (
|
|
131
|
+
<Checkbox
|
|
132
|
+
key={opt.value}
|
|
133
|
+
label={opt.label}
|
|
134
|
+
description={opt.description}
|
|
135
|
+
checked={selected.includes(opt.value)}
|
|
136
|
+
onChange={() => toggle(opt.value)}
|
|
137
|
+
/>
|
|
138
|
+
))}
|
|
139
|
+
</div>
|
|
140
|
+
)
|
|
41
141
|
},
|
|
42
142
|
}
|
|
@@ -197,6 +197,7 @@ export const DatePickerContent = styled(Popover.Content)`
|
|
|
197
197
|
0 1px 3px 0 rgba(0, 0, 0, 0.10),
|
|
198
198
|
0 1px 2px -1px rgba(0, 0, 0, 0.10);
|
|
199
199
|
min-width: 240px;
|
|
200
|
+
z-index: 9999;
|
|
200
201
|
`
|
|
201
202
|
|
|
202
203
|
export const CalendarWrapper = styled.div<{$singleMonth: boolean}>`
|