@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
@@ -0,0 +1,53 @@
1
+ import type {Meta, StoryObj} from '@storybook/react-vite';
2
+
3
+ import Table from './Table';
4
+
5
+ const meta: Meta<typeof Table> = {
6
+ title: 'Data Display/Table',
7
+ component: Table,
8
+ parameters: {
9
+ layout: 'fullscreen',
10
+ },
11
+ tags: ['autodocs'],
12
+ argTypes: {
13
+ data: {
14
+ control: 'object',
15
+ description: 'Array of data objects to be displayed in the table',
16
+ },
17
+ columns: {
18
+ control: 'object',
19
+ description: 'Column definitions for the table',
20
+ },
21
+ footerText: {
22
+ control: {type: undefined},
23
+ description:
24
+ 'Function to render custom footer text, receives total and filtered counts',
25
+ },
26
+ showPagination: {
27
+ control: 'boolean',
28
+ description: 'Whether to enable pagination for the table',
29
+ },
30
+ pageSize: {
31
+ control: 'number',
32
+ description: 'Initial number of rows per page when pagination is enabled',
33
+ },
34
+ },
35
+ };
36
+
37
+ export default meta;
38
+ type Story = StoryObj<typeof meta>;
39
+
40
+ export const Default: Story = {
41
+ args: {
42
+ data: [
43
+ {name: 'John Doe', email: 'john.doe@example.com'},
44
+ {name: 'Jane Smith', email: 'jane.smith@example.com'},
45
+ ],
46
+ columns: [
47
+ {header: 'Name', accessorKey: 'name'},
48
+ {header: 'Email', accessorKey: 'email'},
49
+ ],
50
+ showPagination: true,
51
+ pageSize: 10,
52
+ },
53
+ };
@@ -0,0 +1,76 @@
1
+ import styled from 'styled-components'
2
+ import { spacing, fontSize, fontWeight } from '@liguelead/foundation'
3
+ import { parseColor } from '../../utils'
4
+
5
+ export const TableWrapper = styled.div`
6
+ background: ${({ theme }) => parseColor(theme.colors.white)};
7
+ `
8
+
9
+ export const StyledTable = styled.table`
10
+ width: 100%;
11
+ `
12
+
13
+ export const TableFooter = styled.div<{ $hasPagination: boolean }>`
14
+ display: flex;
15
+ justify-content: center;
16
+ flex-direction: ${({ $hasPagination }) => ($hasPagination ? 'column-reverse' : 'row')};
17
+ align-items: center;
18
+ gap: ${spacing.spacing8}px;
19
+ padding: ${spacing.spacing16}px;
20
+ font-size: ${fontSize.fontSize14}px;
21
+ border-top: 1px solid #e5e7eb;
22
+ `
23
+
24
+ export const FooterText = styled.div`
25
+ display: flex;
26
+ align-items: center;
27
+ `
28
+
29
+ export const PaginationContainer = styled.div`
30
+ display: flex;
31
+ align-items: center;
32
+ `
33
+
34
+ export const PaginationControls = styled.div`
35
+ display: flex;
36
+ gap: ${spacing.spacing4}px;
37
+ `
38
+
39
+ export const PaginationElipsis = styled.span`
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+ padding: ${spacing.spacing8}px;
44
+
45
+ & svg {
46
+ fill: ${({ theme }) => parseColor(theme.colors.primary)};
47
+ font-size: ${fontSize.fontSize14}px;
48
+ color: ${({ theme }) => parseColor(theme.colors.primary)};
49
+ }
50
+ `
51
+
52
+ export const Td = styled.td`
53
+ padding: ${spacing.spacing16}px ${spacing.spacing8}px;
54
+ font-size: ${fontSize.fontSize14}px;
55
+ color: ${({ theme }) => parseColor(theme.colors.textDark)};
56
+ `
57
+
58
+ export const Tr = styled.tr`
59
+ &:not(:last-child) td {
60
+ border-bottom: 1px solid #e5e7eb;
61
+ }
62
+ `
63
+ export const Th = styled.th`
64
+ padding: 12px 16px;
65
+ color: ${({ theme }) => parseColor(theme.colors.textMedium)};
66
+ font-size: ${fontSize.fontSize14}px;
67
+ font-weight: ${fontWeight.fontWeight600};
68
+ border-bottom: 1px solid ${({ theme }) => parseColor(theme.colors.neutral300)};
69
+ `
70
+
71
+ export const EmptyMessage = styled.td`
72
+ padding: ${spacing.spacing16}px;
73
+ color: ${({ theme }) => parseColor(theme.colors.textMedium)};
74
+ font-size: ${fontSize.fontSize14}px;
75
+ text-align: center;
76
+ `
@@ -0,0 +1,157 @@
1
+ import { useState } from 'react'
2
+ import {
3
+ flexRender,
4
+ getCoreRowModel,
5
+ getPaginationRowModel,
6
+ useReactTable,
7
+ } from '@tanstack/react-table'
8
+
9
+ import {
10
+ CaretLeftIcon,
11
+ CaretRightIcon,
12
+ DotsThreeIcon,
13
+ } from '@phosphor-icons/react'
14
+
15
+ import {
16
+ EmptyMessage,
17
+ FooterText,
18
+ PaginationContainer,
19
+ PaginationControls,
20
+ PaginationElipsis,
21
+ StyledTable,
22
+ TableFooter,
23
+ TableWrapper,
24
+ Td,
25
+ Th,
26
+ Tr,
27
+ } from './Table.styles'
28
+ import { TTableProps } from './Table.types'
29
+ import { getPageNumbers } from './utils'
30
+ import IconButton from '../IconButton'
31
+ import Button from '../Button'
32
+
33
+
34
+ function Table<TData>({
35
+ data,
36
+ columns,
37
+ emptyTitle = 'Nenhum registro encontrado.',
38
+ footerText,
39
+ pageSize = 10,
40
+ showPagination = true,
41
+ }: TTableProps<TData>) {
42
+ const [pagination, setPagination] = useState({
43
+ pageIndex: 0,
44
+ pageSize,
45
+ });
46
+
47
+ const table = useReactTable({
48
+ data,
49
+ columns,
50
+ state: {
51
+ pagination,
52
+ },
53
+ onPaginationChange: setPagination,
54
+ getCoreRowModel: getCoreRowModel(),
55
+ getPaginationRowModel: getPaginationRowModel(),
56
+ });
57
+
58
+ const total = table.getFilteredRowModel().rows.length;
59
+ const pageCount = table.getPageCount();
60
+ const hasPagination = showPagination && pageCount > 1;
61
+ const currentPage = pagination.pageIndex + 1;
62
+ const pageNumbersArray = getPageNumbers({ currentPage, pageCount });
63
+
64
+ return (
65
+ <TableWrapper>
66
+ <StyledTable>
67
+ <thead>
68
+ {table.getHeaderGroups().map((hg) => (
69
+ <tr key={hg.id}>
70
+ {hg.headers.map((header) => (
71
+ <Th key={header.id}>
72
+ {flexRender(
73
+ header.column.columnDef.header,
74
+ header.getContext()
75
+ )}
76
+ </Th>
77
+ ))}
78
+ </tr>
79
+ ))}
80
+ </thead>
81
+
82
+ <tbody>
83
+ {table.getRowModel().rows.length === 0 ? (
84
+ <tr>
85
+ <EmptyMessage colSpan={columns.length}>{emptyTitle}</EmptyMessage>
86
+ </tr>
87
+ ) : (
88
+ table.getRowModel().rows.map((row) => (
89
+ <Tr key={row.id}>
90
+ {row.getVisibleCells().map((cell) => (
91
+ <Td key={cell.id}>
92
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
93
+ </Td>
94
+ ))}
95
+ </Tr>
96
+ ))
97
+ )}
98
+ </tbody>
99
+ </StyledTable>
100
+
101
+ {(footerText || hasPagination) && total > 0 && (
102
+ <TableFooter $hasPagination={hasPagination}>
103
+ {footerText && (
104
+ <FooterText>
105
+ {footerText({
106
+ total: data.length,
107
+ filtered: total,
108
+ })}
109
+ </FooterText>
110
+ )}
111
+ {hasPagination && (
112
+ <PaginationContainer>
113
+ <PaginationControls>
114
+ <IconButton
115
+ variant="outline"
116
+ onClick={() => table.previousPage()}
117
+ disabled={!table.getCanPreviousPage()}
118
+ >
119
+ <CaretLeftIcon />
120
+ </IconButton>
121
+ {pageNumbersArray.map((page, index) =>
122
+ page === "ellipsis" ? (
123
+ <PaginationElipsis key={`ellipsis-${index}`}>
124
+ <DotsThreeIcon size={16} />
125
+ </PaginationElipsis>
126
+ ) : (
127
+ <Button
128
+ key={page}
129
+ size="sm"
130
+ variant={page === currentPage ? "solid" : "ghost"}
131
+ onClick={() => {
132
+ if (typeof page === "number") {
133
+ table.setPageIndex(page - 1);
134
+ }
135
+ }}
136
+ >
137
+ {page}
138
+ </Button>
139
+ )
140
+ )}
141
+ <IconButton
142
+ variant="outline"
143
+ onClick={() => table.nextPage()}
144
+ disabled={!table.getCanNextPage()}
145
+ >
146
+ <CaretRightIcon />
147
+ </IconButton>
148
+ </PaginationControls>
149
+ </PaginationContainer>
150
+ )}
151
+ </TableFooter>
152
+ )}
153
+ </TableWrapper>
154
+ );
155
+ }
156
+
157
+ export default Table
@@ -0,0 +1,16 @@
1
+ import { ColumnDef } from '@tanstack/react-table';
2
+
3
+ export type TTableProps<TData> = {
4
+ data: TData[]
5
+ columns: ColumnDef<TData, unknown>[]
6
+
7
+ emptyTitle?: string
8
+ pageSize?: number
9
+ showPagination?: boolean
10
+
11
+ footerText?: (info: {
12
+ total: number
13
+ filtered: number
14
+ }) => string
15
+
16
+ };
@@ -0,0 +1 @@
1
+ export { default } from './Table'
@@ -0,0 +1,35 @@
1
+ import { TPageNumbersProps } from './types'
2
+
3
+ const getPageNumbers = ({ currentPage, pageCount }: TPageNumbersProps) => {
4
+ if (pageCount <= 7) {
5
+ return Array.from({ length: pageCount }, (_, idx) => idx + 1)
6
+ }
7
+
8
+ if (currentPage <= 3) {
9
+ return [1, 2, 3, 'ellipsis', pageCount]
10
+ }
11
+
12
+ if (currentPage >= pageCount - 2) {
13
+ return [
14
+ 1,
15
+ 'ellipsis',
16
+ pageCount - 4,
17
+ pageCount - 3,
18
+ pageCount - 2,
19
+ pageCount - 1,
20
+ pageCount,
21
+ ]
22
+ }
23
+
24
+ return [
25
+ 1,
26
+ 'ellipsis',
27
+ currentPage - 1,
28
+ currentPage,
29
+ currentPage + 1,
30
+ 'ellipsis',
31
+ pageCount,
32
+ ]
33
+ }
34
+
35
+ export default getPageNumbers
@@ -0,0 +1 @@
1
+ export {default as getPageNumbers} from './getPageNumbers'
@@ -0,0 +1,4 @@
1
+ export type TPageNumbersProps = {
2
+ currentPage: number
3
+ pageCount: number
4
+ };
@@ -0,0 +1,61 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import Text from './Text'
3
+ import { themes } from '@liguelead/foundation'
4
+ import { fontWeight } from '@liguelead/foundation'
5
+
6
+ const themeColors = Object.keys(themes.spa.colors)
7
+ const themeTypography = Object.keys(themes.spa.typography)
8
+ const themeFontWeights = Object.keys(fontWeight)
9
+
10
+ const meta: Meta<typeof Text> = {
11
+ title: 'Data Display/Text',
12
+ component: Text,
13
+ parameters: {
14
+ layout: 'centered',
15
+ },
16
+ tags: ['autodocs'],
17
+ argTypes: {
18
+ size: {
19
+ control: 'select',
20
+ options: themeTypography,
21
+ description: 'Text size variant'
22
+ },
23
+ tag: {
24
+ control: 'select',
25
+ options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', 'label', 'small', 'b', 'i', 'em', 'td', 'div', 'a'],
26
+ description: 'HTML tag to render'
27
+ },
28
+ weight: {
29
+ control: 'select',
30
+ options: themeFontWeights,
31
+ description: 'Font weight'
32
+ },
33
+ align: {
34
+ control: 'select',
35
+ options: ['left', 'center', 'right', 'justify'],
36
+ description: 'Text alignment'
37
+ },
38
+ color: {
39
+ control: 'select',
40
+ options: themeColors,
41
+ description: 'Text color'
42
+ },
43
+ isTitle: {
44
+ control: 'boolean',
45
+ description: 'Whether text is a title'
46
+ },
47
+ children: {
48
+ control: 'text',
49
+ description: 'Text content'
50
+ }
51
+ },
52
+ }
53
+
54
+ export default meta
55
+ type Story = StoryObj<typeof meta>
56
+
57
+ export const Default: Story = {
58
+ args: {
59
+ children: 'This is a text component',
60
+ },
61
+ }
@@ -42,4 +42,5 @@ export interface TextProps {
42
42
  size?: SizeType
43
43
  weight?: WeightType
44
44
  className?: string
45
+ style?: React.CSSProperties
45
46
  }
@@ -0,0 +1,84 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import TextField from './TextField'
3
+ import { iconMap, iconOptions } from '../../../stories/utils/icons'
4
+
5
+ const meta: Meta<typeof TextField> = {
6
+ title: 'Form/TextField',
7
+ component: TextField,
8
+ parameters: {
9
+ layout: 'padded',
10
+ },
11
+ tags: ['autodocs'],
12
+ argTypes: {
13
+ label: {
14
+ control: 'text',
15
+ description: 'Field label'
16
+ },
17
+ placeholder: {
18
+ control: 'text',
19
+ description: 'Input placeholder'
20
+ },
21
+ helperText: {
22
+ control: 'text',
23
+ description: 'Helper text below input'
24
+ },
25
+ size: {
26
+ control: 'select',
27
+ options: ['sm', 'md', 'lg'],
28
+ description: 'Input size'
29
+ },
30
+ type: {
31
+ control: 'select',
32
+ options: ['text', 'password', 'email', 'number', 'file'],
33
+ description: 'Input type'
34
+ },
35
+ disabled: {
36
+ control: 'boolean',
37
+ description: 'Whether input is disabled'
38
+ },
39
+ requiredSymbol: {
40
+ control: 'boolean',
41
+ description: 'Show required asterisk'
42
+ },
43
+ leftIcon: {
44
+ control: 'select',
45
+ options: iconOptions,
46
+ description: 'Left icon',
47
+ },
48
+ rightIcon: {
49
+ control: 'select',
50
+ options: iconOptions,
51
+ description: 'Right icon',
52
+ },
53
+ },
54
+ }
55
+
56
+ export default meta
57
+ type Story = StoryObj<typeof meta>
58
+
59
+ export const Default: Story = {
60
+ args: {
61
+ label: 'Label',
62
+ placeholder: 'Enter text...',
63
+ leftIcon: 'none',
64
+ rightIcon: 'none',
65
+ },
66
+ render: (args) => {
67
+ const leftIcon = args.leftIcon === 'none' ? undefined : iconMap[args.leftIcon as keyof typeof iconMap]
68
+ const rightIcon = args.rightIcon === 'none' ? undefined : iconMap[args.rightIcon as keyof typeof iconMap]
69
+
70
+ return (
71
+ <TextField
72
+ label={args.label}
73
+ placeholder={args.placeholder}
74
+ helperText={args.helperText}
75
+ size={args.size}
76
+ type={args.type}
77
+ disabled={args.disabled}
78
+ requiredSymbol={args.requiredSymbol}
79
+ leftIcon={leftIcon}
80
+ rightIcon={rightIcon}
81
+ />
82
+ )
83
+ },
84
+ }
@@ -0,0 +1,129 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import { useState } from 'react'
3
+ import Button from '../Button'
4
+ import { ToastType, triggerToast } from './Toaster'
5
+ import ToasterProvider from './ToasterProvider'
6
+
7
+ interface ToasterStoryArgs {
8
+ type: ToastType
9
+ message: string
10
+ autoClose: number
11
+ position: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center'
12
+ theme: 'light' | 'dark' | 'colored'
13
+ }
14
+
15
+ const ToasterDemo = () => <div />
16
+
17
+ const meta = {
18
+ title: 'Feedback/Toaster',
19
+ component: ToasterDemo,
20
+ parameters: {
21
+ layout: 'centered',
22
+ },
23
+ tags: ['autodocs'],
24
+ argTypes: {
25
+ type: {
26
+ control: 'select',
27
+ options: ['success', 'error', 'warning', 'info'],
28
+ description: 'Type of toast notification'
29
+ },
30
+ message: {
31
+ control: 'text',
32
+ description: 'Toast message content'
33
+ },
34
+ autoClose: {
35
+ control: 'number',
36
+ description: 'Auto close time in milliseconds'
37
+ },
38
+ position: {
39
+ control: 'select',
40
+ options: ['top-right', 'top-left', 'bottom-right', 'bottom-left', 'top-center', 'bottom-center'],
41
+ description: 'Toast position'
42
+ },
43
+ theme: {
44
+ control: 'select',
45
+ options: ['light', 'dark', 'colored'],
46
+ description: 'Toast theme'
47
+ }
48
+ },
49
+ } satisfies Meta<typeof ToasterDemo>
50
+
51
+ export default meta
52
+ type Story = StoryObj<ToasterStoryArgs>
53
+
54
+ export const Default: Story = {
55
+ args: {
56
+ type: 'success',
57
+ message: 'This is a toast message!',
58
+ autoClose: 5000,
59
+ position: 'top-right',
60
+ theme: 'light'
61
+ },
62
+ render: (args) => (
63
+ <ToasterProvider>
64
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
65
+ <Button
66
+ onClick={() =>
67
+ triggerToast(args.type, args.message, {
68
+ autoClose: args.autoClose,
69
+ position: args.position,
70
+ theme: args.theme
71
+ })
72
+ }
73
+ color="primary"
74
+ >
75
+ Show Toast
76
+ </Button>
77
+ </div>
78
+ </ToasterProvider>
79
+ ),
80
+ }
81
+
82
+ export const Types: Story = {
83
+ render: () => (
84
+ <ToasterProvider>
85
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
86
+ <Button onClick={() => triggerToast('success', 'Success message!')}>
87
+ Success Toast
88
+ </Button>
89
+ <Button onClick={() => triggerToast('error', 'Error message!')}>
90
+ Error Toast
91
+ </Button>
92
+ <Button onClick={() => triggerToast('warning', 'Warning message!')}>
93
+ Warning Toast
94
+ </Button>
95
+ <Button onClick={() => triggerToast('info', 'Info message!')}>
96
+ Info Toast
97
+ </Button>
98
+ </div>
99
+ </ToasterProvider>
100
+ ),
101
+ }
102
+
103
+ export const Positions: Story = {
104
+ render: () => {
105
+ const [position, setPosition] = useState<'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'>('top-right')
106
+
107
+ return (
108
+ <ToasterProvider>
109
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
110
+ <select
111
+ value={position}
112
+ onChange={(e) => setPosition(e.target.value as any)}
113
+ style={{ padding: '8px', marginBottom: '12px' }}
114
+ >
115
+ <option value="top-right">Top Right</option>
116
+ <option value="top-left">Top Left</option>
117
+ <option value="bottom-right">Bottom Right</option>
118
+ <option value="bottom-left">Bottom Left</option>
119
+ </select>
120
+ <Button
121
+ onClick={() => triggerToast('info', `Toast at ${position}`, { position })}
122
+ >
123
+ Show Toast at {position}
124
+ </Button>
125
+ </div>
126
+ </ToasterProvider>
127
+ )
128
+ },
129
+ }
@@ -9,6 +9,25 @@ const defaultOptions: ToastOptions = {
9
9
  theme: 'light'
10
10
  }
11
11
 
12
+ export type ToastType = 'success' | 'error' | 'warning' | 'info'
13
+
14
+ export const triggerToast = (type: ToastType, message: string, options?: ToastOptions) => {
15
+ const mergedOptions = { ...defaultOptions, ...options }
16
+
17
+ switch (type) {
18
+ case 'success':
19
+ return toast.success(message, mergedOptions)
20
+ case 'error':
21
+ return toast.error(message, mergedOptions)
22
+ case 'warning':
23
+ return toast.warning(message, mergedOptions)
24
+ case 'info':
25
+ return toast.info(message, mergedOptions)
26
+ default:
27
+ return toast(message, mergedOptions)
28
+ }
29
+ }
30
+
12
31
  const Toaster = {
13
32
  success: (message: string, options?: ToastOptions) =>
14
33
  toast.success(message, { ...defaultOptions, ...options }),
@@ -1,9 +1,17 @@
1
1
  import 'react-toastify/dist/ReactToastify.css'
2
2
  import { ToasterStyledContainer } from './Toaster.style'
3
+ import { ReactNode } from 'react'
3
4
 
4
- const ToastProvider = () => {
5
+ interface ToasterProviderProps {
6
+ children?: ReactNode
7
+ }
8
+
9
+ const ToastProvider = ({ children }: ToasterProviderProps) => {
5
10
  return(
11
+ <>
12
+ {children}
6
13
  <ToasterStyledContainer newestOnTop />
14
+ </>
7
15
  )
8
16
  }
9
17