@liguelead/design-system 0.0.28 → 0.0.30

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 (37) hide show
  1. package/components/Alert/Alert.stories.tsx +60 -0
  2. package/components/Button/Button.appearance.ts +2 -2
  3. package/components/Button/Button.stories.tsx +75 -0
  4. package/components/Checkbox/Checkbox.stories.tsx +42 -0
  5. package/components/Combobox/Combobox.stories.tsx +112 -0
  6. package/components/Combobox/Combobox.styles.ts +7 -3
  7. package/components/Combobox/Combobox.tsx +3 -10
  8. package/components/DatePicker/DatePicker.stories.tsx +108 -0
  9. package/components/DatePicker/DatePicker.styles.ts +394 -50
  10. package/components/DatePicker/DatePicker.tsx +353 -118
  11. package/components/DatePicker/DatePicker.types.ts +40 -24
  12. package/components/Dialog/Dialog.stories.tsx +63 -0
  13. package/components/IconButton/IconButton.stories.tsx +49 -0
  14. package/components/InputOpt/InputOpt.stories.tsx +61 -0
  15. package/components/LinkButton/LinkButton.stories.tsx +88 -0
  16. package/components/PageWrapper/PageWrapper.stories.tsx +153 -0
  17. package/components/RadioButton/RadioButton.stories.tsx +70 -0
  18. package/components/RequiredAsterisk/RequiredAsterisk.stories.tsx +44 -0
  19. package/components/SegmentedButton/SegmentedButton.stories.tsx +182 -0
  20. package/components/Select/Select.stories.tsx +63 -0
  21. package/components/Table/Table.stories.tsx +53 -0
  22. package/components/Table/Table.styles.ts +76 -0
  23. package/components/Table/Table.tsx +157 -0
  24. package/components/Table/Table.types.ts +16 -0
  25. package/components/Table/index.ts +1 -0
  26. package/components/Table/utils/getPageNumbers.ts +35 -0
  27. package/components/Table/utils/index.ts +1 -0
  28. package/components/Table/utils/types.ts +4 -0
  29. package/components/Text/Text.stories.tsx +61 -0
  30. package/components/Text/Text.types.ts +1 -0
  31. package/components/TextField/TextField.stories.tsx +84 -0
  32. package/components/Toaster/Toaster.stories.tsx +129 -0
  33. package/components/Toaster/Toaster.ts +19 -0
  34. package/components/Toaster/ToasterProvider.tsx +9 -1
  35. package/components/Wizard/Wizard.stories.tsx +186 -0
  36. package/components/index.ts +1 -0
  37. package/package.json +16 -3
@@ -1,139 +1,374 @@
1
- import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
2
1
  import {
3
- Calendar,
4
- CaretLeft,
5
- CaretRight,
6
- CaretDown
7
- } from '@phosphor-icons/react'
8
- import { getYear, getMonth } from 'date-fns'
9
- import { ptBR } from 'date-fns/locale'
10
-
11
- // Substituindo lodash.range por implementação simples
12
- const range = (start: number, end: number, step: number = 1) => {
13
- return Array.from({ length: Math.ceil((end - start) / step) }, (_, i) => start + i * step)
14
- }
15
- import { forwardRef, useState } from 'react'
16
- import TextField from '../TextField'
17
- import { DatePickerProps, Months } from './DatePicker.types'
2
+ ChangeEvent,
3
+ forwardRef,
4
+ useEffect,
5
+ useId,
6
+ useMemo,
7
+ useRef,
8
+ useState
9
+ } from 'react'
10
+ import * as Popover from '@radix-ui/react-popover'
11
+ import { CalendarBlankIcon } from '@phosphor-icons/react'
12
+ import { format, parse, startOfDay, isValid } from 'date-fns'
13
+ import { DateRange, DayPicker } from 'react-day-picker'
14
+ import { ptBR } from 'react-day-picker/locale'
15
+ import 'react-day-picker/dist/style.css'
18
16
  import {
19
- ButtonDatePicker,
20
- HeaderSelectWrapper,
21
- DropdownContent,
22
- DropdownItem,
23
- ArrownDatePicker
17
+ CalendarWrapper,
18
+ DatePickerContent,
19
+ DatePickerError,
20
+ DatePickerHiddenInput,
21
+ DatePickerInput,
22
+ DatePickerLabel,
23
+ DatePickerTrigger,
24
+ DatePickerTriggerWrapper,
25
+ IconSlot,
26
+ Wrapper
24
27
  } from './DatePicker.styles'
25
- import DatePicker from 'react-datepicker'
28
+ import { DatePickerProps } from './DatePicker.types'
29
+ import RequiredAsterisk from '../RequiredAsterisk'
30
+
31
+ const serializeDate = (date?: Date) => {
32
+ if (!date || Number.isNaN(date.getTime())) return ''
33
+ return format(date, 'yyyy-MM-dd')
34
+ }
26
35
 
27
- const DatePickerCustom = forwardRef<HTMLInputElement, DatePickerProps>(
36
+ const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(
28
37
  (
29
38
  {
30
39
  label,
31
40
  error,
41
+ disabled = false,
42
+ className,
43
+ icon = true,
44
+ size = 'md',
45
+ placeholder = 'DD/MM/AAAA',
46
+ mode = 'single',
47
+ startDate,
48
+ endDate,
49
+ value,
50
+ rangeValue,
32
51
  startYear = 1990,
33
- endYear = 0,
34
- startDate = new Date(),
35
- icon = false,
52
+ endYear,
36
53
  onChange,
37
- size = 'md',
54
+ onRangeChange,
55
+ captionLayout,
56
+ numberOfMonths,
57
+ inline = false,
58
+ required = false,
38
59
  register,
39
- ...rest
40
- }: DatePickerProps,
60
+ dayPickerProps
61
+ },
41
62
  ref
42
63
  ) => {
43
- const [pickerStartDate, setPickerStartDate] = useState<Date | null>(
44
- startDate
64
+ const today = useMemo(() => startOfDay(new Date()), [])
65
+ const {
66
+ captionLayout: dayPickerCaptionLayout,
67
+ numberOfMonths: dayPickerNumberOfMonths,
68
+ fromYear: dayPickerFromYear,
69
+ toYear: dayPickerToYear,
70
+ locale: dayPickerLocale,
71
+ today: dayPickerToday,
72
+ ...restDayPickerProps
73
+ } = dayPickerProps ?? {}
74
+
75
+ const isRange = mode === 'range'
76
+ const resolvedStartYear = startYear ?? dayPickerFromYear ?? 1990
77
+ const resolvedEndYear = endYear ?? dayPickerToYear ?? today.getFullYear()
78
+ const monthsToRender =
79
+ numberOfMonths ?? dayPickerNumberOfMonths ?? (isRange ? 2 : 1)
80
+ const appliedCaptionLayout =
81
+ captionLayout ?? dayPickerCaptionLayout ?? 'label'
82
+ const resolvedLocale = dayPickerLocale ?? ptBR
83
+ const resolvedToday = dayPickerToday ?? today
84
+ const baseId = useId()
85
+ const errorId = `${baseId}-error`
86
+ const inputRef = useRef<HTMLInputElement | null>(null)
87
+ const [inputValue, setInputValue] = useState(() =>
88
+ !isRange && value ? format(value, 'dd/MM/yyyy') : ''
45
89
  )
46
- const lastYear =
47
- endYear > startYear ? endYear + 1 : getYear(new Date()) + 1
48
- const years = range(startYear, lastYear, 1)
49
90
 
50
- return (
51
- <DatePicker
52
- {...register}
53
- {...rest}
54
- locale={ptBR}
55
- renderCustomHeader={({
56
- date,
57
- changeYear,
58
- changeMonth,
59
- decreaseMonth,
60
- increaseMonth,
61
- prevMonthButtonDisabled,
62
- nextMonthButtonDisabled
63
- }) => (
64
- <HeaderSelectWrapper>
65
- <ArrownDatePicker
66
- onClick={decreaseMonth}
67
- disabled={prevMonthButtonDisabled}>
68
- <CaretLeft size={24} weight="bold" />
69
- </ArrownDatePicker>
70
- <DropdownMenu.Root modal={false}>
71
- <DropdownMenu.Trigger asChild>
72
- <ButtonDatePicker>
73
- {getYear(date)} <CaretDown size={16} />
74
- </ButtonDatePicker>
75
- </DropdownMenu.Trigger>
76
- <DropdownContent>
77
- {years.map((option: number) => (
78
- <DropdownItem
79
- key={option}
80
- onSelect={() => {
81
- changeYear(option)
82
- }}>
83
- {option}
84
- </DropdownItem>
85
- ))}
86
- </DropdownContent>
87
- </DropdownMenu.Root>
88
- <DropdownMenu.Root modal={false}>
89
- <DropdownMenu.Trigger asChild>
90
- <ButtonDatePicker>
91
- {Months[getMonth(date)]}{' '}
92
- <CaretDown size={16} />
93
- </ButtonDatePicker>
94
- </DropdownMenu.Trigger>
95
- <DropdownContent>
96
- {Months.map((month, index) => (
97
- <DropdownItem
98
- key={month}
99
- onSelect={() => {
100
- changeMonth(index)
101
- }}>
102
- {month}
103
- </DropdownItem>
104
- ))}
105
- </DropdownContent>
106
- </DropdownMenu.Root>
107
-
108
- <ArrownDatePicker
109
- onClick={increaseMonth}
110
- disabled={nextMonthButtonDisabled}>
111
- <CaretRight size={24} weight="bold" />
112
- </ArrownDatePicker>
113
- </HeaderSelectWrapper>
114
- )}
115
- dateFormat="dd/MM/yyyy"
116
- selected={pickerStartDate}
117
- onChange={(date: Date | null) => {
118
- if (!date) {
119
- return
91
+ useEffect(() => {
92
+ if (!isRange && value) {
93
+ setInputValue(format(value, 'dd/MM/yyyy'))
94
+ } else if (!isRange && !value) {
95
+ setInputValue('')
96
+ }
97
+ }, [value, isRange])
98
+
99
+ const hiddenValue = useMemo(() => {
100
+ if (isRange) {
101
+ if (!rangeValue?.from && !rangeValue?.to) return ''
102
+ return JSON.stringify({
103
+ from: rangeValue?.from ? serializeDate(rangeValue.from) : null,
104
+ to: rangeValue?.to ? serializeDate(rangeValue.to) : null
105
+ })
106
+ }
107
+ return value ? serializeDate(value) : ''
108
+ }, [isRange, rangeValue, value])
109
+
110
+ const displayValue = useMemo(() => {
111
+ if (isRange) {
112
+ if (rangeValue?.from && rangeValue?.to) {
113
+ return `${format(rangeValue.from, 'dd/MM/yyyy')} - ${format(
114
+ rangeValue.to,
115
+ 'dd/MM/yyyy'
116
+ )}`
117
+ }
118
+ if (rangeValue?.from) return format(rangeValue.from, 'dd/MM/yyyy')
119
+ return placeholder
120
+ }
121
+ return value ? format(value, 'dd/MM/yyyy') : placeholder
122
+ }, [isRange, placeholder, rangeValue, value])
123
+
124
+ const isUsingPlaceholder = isRange ? !rangeValue?.from : !value
125
+ const parsedError =
126
+ typeof error === 'string'
127
+ ? error
128
+ : typeof error === 'object' &&
129
+ error !== null &&
130
+ 'message' in error
131
+ ? String((error as { message?: string }).message ?? '')
132
+ : undefined
133
+
134
+ const handleSingleSelect = (date?: Date) => {
135
+ if (disabled) return
136
+ const nextDate = date
137
+ onChange?.(nextDate)
138
+ setInputValue(nextDate ? format(nextDate, 'dd/MM/yyyy') : '')
139
+ register?.onChange({
140
+ target: {
141
+ name: register?.name,
142
+ value: nextDate ? serializeDate(nextDate) : ''
143
+ }
144
+ } as unknown as ChangeEvent<HTMLInputElement>)
145
+ }
146
+
147
+ const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
148
+ if (disabled || isRange) return
149
+ const rawInput = e.target.value
150
+ const caret = e.target.selectionStart ?? rawInput.length
151
+ const digitsBeforeCaret = rawInput
152
+ .slice(0, caret)
153
+ .replace(/\D/g, '').length
154
+ const numbers = rawInput.replace(/\D/g, '').slice(0, 8)
155
+
156
+ let formatted = ''
157
+ if (numbers.length > 0) {
158
+ formatted = numbers.slice(0, 2)
159
+ if (numbers.length >= 3) formatted += '/' + numbers.slice(2, 4)
160
+ if (numbers.length >= 5) formatted += '/' + numbers.slice(4, 8)
161
+ }
162
+
163
+ const nextCaret = (() => {
164
+ if (digitsBeforeCaret <= 2) return digitsBeforeCaret
165
+ if (digitsBeforeCaret <= 4) return digitsBeforeCaret + 1
166
+ return digitsBeforeCaret + 2
167
+ })()
168
+
169
+ setInputValue(formatted)
170
+ requestAnimationFrame(() => {
171
+ const node = inputRef.current
172
+ if (!node) return
173
+ const safePos = Math.min(nextCaret, formatted.length)
174
+ node.setSelectionRange(safePos, safePos)
175
+ })
176
+
177
+ if (formatted.length === 10) {
178
+ const parsedDate = parse(formatted, 'dd/MM/yyyy', resolvedToday)
179
+ if (isValid(parsedDate)) {
180
+ onChange?.(parsedDate)
181
+ register?.onChange({
182
+ target: {
183
+ name: register?.name,
184
+ value: serializeDate(parsedDate)
185
+ }
186
+ } as unknown as ChangeEvent<HTMLInputElement>)
187
+ }
188
+ } else if (formatted === '') {
189
+ onChange?.(undefined)
190
+ register?.onChange({
191
+ target: {
192
+ name: register?.name,
193
+ value: ''
120
194
  }
121
- setPickerStartDate(date)
122
- onChange?.(date)
123
- }}
124
- customInput={
125
- <TextField
126
- error={error}
127
- size={size}
128
- ref={ref}
129
- leftIcon={icon && <Calendar size={22} weight="bold" />}
130
- label={label}
131
- className="example-custom-input"
195
+ } as unknown as ChangeEvent<HTMLInputElement>)
196
+ }
197
+ }
198
+
199
+ const handleInputBlur = () => {
200
+ if (disabled || isRange) return
201
+ if (!inputValue) return
202
+ if (inputValue.length < 10) {
203
+ const fallback = value ? format(value, 'dd/MM/yyyy') : ''
204
+ setInputValue(fallback)
205
+ return
206
+ }
207
+ const parsedDate = parse(inputValue, 'dd/MM/yyyy', resolvedToday)
208
+ if (isValid(parsedDate)) {
209
+ setInputValue(format(parsedDate, 'dd/MM/yyyy'))
210
+ onChange?.(parsedDate)
211
+ register?.onChange({
212
+ target: {
213
+ name: register?.name,
214
+ value: serializeDate(parsedDate)
215
+ }
216
+ } as unknown as ChangeEvent<HTMLInputElement>)
217
+ } else {
218
+ const fallback = value ? format(value, 'dd/MM/yyyy') : ''
219
+ setInputValue(fallback)
220
+ }
221
+ }
222
+
223
+ const handleRangeSelect = (value?: DateRange) => {
224
+ if (disabled) return
225
+ const nextRange = value
226
+ onRangeChange?.(nextRange)
227
+ const serialized = nextRange
228
+ ? JSON.stringify({
229
+ from: nextRange.from
230
+ ? serializeDate(nextRange.from)
231
+ : null,
232
+ to: nextRange.to ? serializeDate(nextRange.to) : null
233
+ })
234
+ : ''
235
+
236
+ register?.onChange({
237
+ target: { name: register?.name, value: serialized }
238
+ } as unknown as ChangeEvent<HTMLInputElement>)
239
+ }
240
+
241
+ const picker = (
242
+ <CalendarWrapper $singleMonth={!isRange}>
243
+ {isRange ? (
244
+ <DayPicker
245
+ {...restDayPickerProps}
246
+ locale={resolvedLocale}
247
+ mode="range"
248
+ selected={rangeValue}
249
+ onSelect={handleRangeSelect}
250
+
251
+ captionLayout={appliedCaptionLayout}
252
+ navLayout="around"
253
+ fromYear={resolvedStartYear}
254
+ toYear={resolvedEndYear}
255
+ fromDate={startDate}
256
+ toDate={endDate}
257
+ today={resolvedToday}
258
+ numberOfMonths={monthsToRender}
259
+ required={false}
260
+ defaultMonth={rangeValue?.from ?? resolvedToday}
132
261
  />
133
- }
134
- />
262
+ ) : (
263
+ <DayPicker
264
+ {...restDayPickerProps}
265
+ locale={resolvedLocale}
266
+ mode="single"
267
+ selected={value}
268
+ onSelect={handleSingleSelect}
269
+ captionLayout={appliedCaptionLayout}
270
+ navLayout="around"
271
+ fromYear={resolvedStartYear}
272
+ toYear={resolvedEndYear}
273
+ fromDate={startDate}
274
+ toDate={endDate}
275
+ today={resolvedToday}
276
+ numberOfMonths={monthsToRender}
277
+ required={false}
278
+ defaultMonth={value ?? resolvedToday}
279
+ />
280
+ )}
281
+ </CalendarWrapper>
282
+ )
283
+
284
+ return (
285
+ <Wrapper className={className}>
286
+ {label && (
287
+ <DatePickerLabel>
288
+ {label} {required && <RequiredAsterisk />}
289
+ </DatePickerLabel>
290
+ )}
291
+
292
+ <DatePickerHiddenInput
293
+ type="hidden"
294
+ value={hiddenValue}
295
+ name={register?.name}
296
+ readOnly
297
+ ref={instance => {
298
+ if (typeof ref === 'function') {
299
+ ref(instance)
300
+ } else if (ref) {
301
+ ref.current = instance
302
+ }
303
+ register?.ref(instance)
304
+ }}
305
+ onChange={register?.onChange}
306
+ onBlur={register?.onBlur}
307
+ />
308
+
309
+ {inline ? (
310
+ picker
311
+ ) : (
312
+ <Popover.Root>
313
+ <DatePickerTriggerWrapper>
314
+ {icon && (
315
+ <Popover.Trigger asChild disabled={disabled}>
316
+ <IconSlot $disabled={disabled} as="button" type="button">
317
+ <CalendarBlankIcon size={16} />
318
+ </IconSlot>
319
+ </Popover.Trigger>
320
+ )}
321
+
322
+ {isRange ? (
323
+ <Popover.Trigger asChild disabled={disabled}>
324
+ <DatePickerTrigger
325
+ type="button"
326
+ disabled={disabled}
327
+ $hasIcon={icon}
328
+ $size={size}
329
+ $error={!!parsedError}
330
+ $isPlaceholder={isUsingPlaceholder}
331
+ aria-invalid={!!parsedError}
332
+ aria-describedby={parsedError ? errorId : undefined}
333
+ >
334
+ {displayValue}
335
+ </DatePickerTrigger>
336
+ </Popover.Trigger>
337
+ ) : (
338
+ <Popover.Trigger asChild disabled={disabled}>
339
+ <DatePickerInput
340
+ type="text"
341
+ disabled={disabled}
342
+ $hasIcon={icon}
343
+ $size={size}
344
+ $error={!!parsedError}
345
+ placeholder={placeholder}
346
+ value={inputValue}
347
+ onChange={handleInputChange}
348
+ onBlur={handleInputBlur}
349
+ aria-invalid={!!parsedError}
350
+ aria-describedby={parsedError ? errorId : undefined}
351
+ ref={inputRef}
352
+ />
353
+ </Popover.Trigger>
354
+ )}
355
+ </DatePickerTriggerWrapper>
356
+
357
+ <Popover.Portal>
358
+ <DatePickerContent sideOffset={8} align="start">
359
+ {picker}
360
+ </DatePickerContent>
361
+ </Popover.Portal>
362
+ </Popover.Root>
363
+ )}
364
+
365
+ {parsedError && (
366
+ <DatePickerError id={errorId}>{parsedError}</DatePickerError>
367
+ )}
368
+ </Wrapper>
135
369
  )
136
370
  }
137
371
  )
138
372
 
139
- export default DatePickerCustom
373
+ DatePicker.displayName = 'DatePicker'
374
+ export default DatePicker
@@ -1,29 +1,45 @@
1
- import { FieldValues, UseFormRegister } from 'react-hook-form'
1
+ import { FieldValues, UseFormRegisterReturn } from 'react-hook-form'
2
+ import { DateRange, DayPickerProps } from 'react-day-picker'
2
3
 
3
- export const Months = [
4
- 'Janeiro',
5
- 'Fevereiro',
6
- 'Março',
7
- 'Abril',
8
- 'Maio',
9
- 'Junho',
10
- 'Julho',
11
- 'Agosto',
12
- 'Setembro',
13
- 'Outubro',
14
- 'Novembro',
15
- 'Dezembro'
16
- ]
4
+ export type DatePickerMode = 'single' | 'range'
5
+ export type DatePickerSize = 'sm' | 'md' | 'lg'
17
6
 
18
- export type DatePickerProps = {
19
- endYear?: number
20
- label: string
21
- startYear?: number
22
- onChange?: (date: Date) => void
23
- error?: FieldValues
24
- startDate?: Date
7
+ type DatePickerBaseProps = {
8
+ label?: string
9
+ error?: FieldValues | string | { message?: string } | null
10
+ disabled?: boolean
25
11
  className?: string
12
+ required?: boolean
26
13
  icon?: boolean
27
- size?: 'sm' | 'md' | 'lg'
28
- register?: UseFormRegister<Date>
14
+ size?: DatePickerSize
15
+ placeholder?: string
16
+ startDate?: Date
17
+ endDate?: Date
18
+ startYear?: number
19
+ endYear?: number
20
+ captionLayout?: 'label' | 'dropdown' | 'dropdown-months' | 'dropdown-years'
21
+ numberOfMonths?: number
22
+ inline?: boolean
23
+ register?: UseFormRegisterReturn<string>
24
+ dayPickerProps?: Partial<
25
+ Omit<DayPickerProps, 'mode' | 'selected' | 'onSelect' | 'defaultMonth'>
26
+ >
29
27
  }
28
+
29
+ export type DatePickerSingleProps = DatePickerBaseProps & {
30
+ mode?: 'single'
31
+ value?: Date | undefined
32
+ onChange?: (date: Date | undefined) => void
33
+ rangeValue?: never
34
+ onRangeChange?: never
35
+ }
36
+
37
+ export type DatePickerRangeProps = DatePickerBaseProps & {
38
+ mode: 'range'
39
+ rangeValue?: DateRange | undefined
40
+ onRangeChange?: (range: DateRange | undefined) => void
41
+ value?: never
42
+ onChange?: never
43
+ }
44
+
45
+ export type DatePickerProps = DatePickerSingleProps | DatePickerRangeProps
@@ -0,0 +1,63 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import Dialog from './Dialog'
3
+ import Button from '../Button/Button'
4
+
5
+ const meta: Meta<typeof Dialog> = {
6
+ title: 'Feedback/Dialog',
7
+ component: Dialog,
8
+ parameters: {
9
+ layout: 'centered'
10
+ },
11
+ tags: ['autodocs'],
12
+ argTypes: {
13
+ title: {
14
+ control: 'text',
15
+ description: 'Dialog title'
16
+ },
17
+ description: {
18
+ control: 'text',
19
+ description: 'Dialog description'
20
+ },
21
+ variant: {
22
+ control: 'select',
23
+ options: ['default', 'danger'],
24
+ description: 'Dialog variant'
25
+ },
26
+ confirmButton: {
27
+ control: 'boolean',
28
+ description: 'Show confirm button'
29
+ },
30
+ cancelButton: {
31
+ control: 'boolean',
32
+ description: 'Show cancel button'
33
+ },
34
+ confirmLabel: {
35
+ control: 'text',
36
+ description: 'Confirm button label'
37
+ },
38
+ cancelLabel: {
39
+ control: 'text',
40
+ description: 'Cancel button label'
41
+ },
42
+ confirmButtonColor: {
43
+ control: 'select',
44
+ options: ['primary', 'secondary'],
45
+ description: 'Confirm button color'
46
+ },
47
+ centerContent: {
48
+ control: 'boolean',
49
+ description: 'Center dialog content'
50
+ }
51
+ }
52
+ }
53
+
54
+ export default meta
55
+ type Story = StoryObj<typeof meta>
56
+
57
+ export const Default: Story = {
58
+ args: {
59
+ title: 'Dialog Title',
60
+ description: 'This is a dialog description.',
61
+ trigger: <Button>Open Dialog</Button>
62
+ }
63
+ }
@@ -0,0 +1,49 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import IconButton from './IconButton'
3
+ import { themes } from '@liguelead/foundation'
4
+ import { iconMap } from '../../../stories/utils/icons'
5
+
6
+ const themeColors = Object.keys(themes.spa.colors)
7
+
8
+ const meta = {
9
+ title: 'Form/IconButton',
10
+ component: IconButton,
11
+ parameters: {
12
+ layout: 'centered',
13
+ },
14
+ tags: ['autodocs'],
15
+ argTypes: {
16
+ variant: {
17
+ control: 'select',
18
+ options: ['solid', 'outline', 'ghost', 'neutralOutline', 'neutralGhost'],
19
+ description: 'Visual style variant of the icon button'
20
+ },
21
+ size: {
22
+ control: 'select',
23
+ options: ['sm', 'md', 'lg'],
24
+ description: 'Size of the icon button'
25
+ },
26
+ color: {
27
+ control: 'select',
28
+ options: themeColors,
29
+ description: 'Color theme of the icon button'
30
+ },
31
+ disabled: {
32
+ control: 'boolean',
33
+ description: 'Whether the icon button is disabled'
34
+ },
35
+ children: {
36
+ control: false,
37
+ description: 'Icon content'
38
+ },
39
+ },
40
+ } satisfies Meta<typeof IconButton>
41
+
42
+ export default meta
43
+ type Story = StoryObj<typeof meta>
44
+
45
+ export const Default: Story = {
46
+ args: {
47
+ children: iconMap.HeartIcon,
48
+ },
49
+ }