@shipfox/react-ui 0.4.0 → 0.6.0

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 (103) hide show
  1. package/.storybook/main.ts +20 -10
  2. package/.storybook/preview.tsx +11 -0
  3. package/.storybook/vitest.setup.ts +4 -0
  4. package/.turbo/turbo-build.log +16 -3
  5. package/.turbo/turbo-check.log +2 -2
  6. package/.turbo/turbo-type.log +1 -1
  7. package/CHANGELOG.md +15 -0
  8. package/README.md +56 -1
  9. package/argos.config.ts +33 -0
  10. package/dist/build-css-entry.js +5 -0
  11. package/dist/build-css-entry.js.map +1 -0
  12. package/dist/components/button/button-link.d.ts +14 -0
  13. package/dist/components/button/button-link.d.ts.map +1 -0
  14. package/dist/components/button/button-link.js +63 -0
  15. package/dist/components/button/button-link.js.map +1 -0
  16. package/dist/components/button/button-link.stories.js +127 -0
  17. package/dist/components/button/button-link.stories.js.map +1 -0
  18. package/dist/components/button/button.d.ts +1 -1
  19. package/dist/components/button/button.d.ts.map +1 -1
  20. package/dist/components/button/button.js +7 -6
  21. package/dist/components/button/button.js.map +1 -1
  22. package/dist/components/button/button.stories.js +1 -13
  23. package/dist/components/button/button.stories.js.map +1 -1
  24. package/dist/components/button/icon-button.d.ts +14 -0
  25. package/dist/components/button/icon-button.d.ts.map +1 -0
  26. package/dist/components/button/icon-button.js +53 -0
  27. package/dist/components/button/icon-button.js.map +1 -0
  28. package/dist/components/button/icon-button.stories.js +254 -0
  29. package/dist/components/button/icon-button.stories.js.map +1 -0
  30. package/dist/components/button/index.d.ts +2 -0
  31. package/dist/components/button/index.d.ts.map +1 -1
  32. package/dist/components/button/index.js +2 -0
  33. package/dist/components/button/index.js.map +1 -1
  34. package/dist/components/code-block/code-block-footer.d.ts.map +1 -1
  35. package/dist/components/code-block/code-block-footer.js +29 -15
  36. package/dist/components/code-block/code-block-footer.js.map +1 -1
  37. package/dist/components/code-block/code-content.d.ts.map +1 -1
  38. package/dist/components/code-block/code-content.js +2 -2
  39. package/dist/components/code-block/code-content.js.map +1 -1
  40. package/dist/components/dynamic-item/dynamic-item.stories.js +1 -1
  41. package/dist/components/dynamic-item/dynamic-item.stories.js.map +1 -1
  42. package/dist/components/icon/icon.d.ts +3 -0
  43. package/dist/components/icon/icon.d.ts.map +1 -1
  44. package/dist/components/icon/icon.js +5 -2
  45. package/dist/components/icon/icon.js.map +1 -1
  46. package/dist/components/index.d.ts +1 -0
  47. package/dist/components/index.d.ts.map +1 -1
  48. package/dist/components/index.js +1 -0
  49. package/dist/components/index.js.map +1 -1
  50. package/dist/components/modal/index.d.ts +3 -0
  51. package/dist/components/modal/index.d.ts.map +1 -0
  52. package/dist/components/modal/index.js +3 -0
  53. package/dist/components/modal/index.js.map +1 -0
  54. package/dist/components/modal/modal.d.ts +37 -0
  55. package/dist/components/modal/modal.d.ts.map +1 -0
  56. package/dist/components/modal/modal.js +262 -0
  57. package/dist/components/modal/modal.js.map +1 -0
  58. package/dist/components/modal/modal.stories.js +497 -0
  59. package/dist/components/modal/modal.stories.js.map +1 -0
  60. package/dist/components/moving-border/index.d.ts +2 -0
  61. package/dist/components/moving-border/index.d.ts.map +1 -0
  62. package/dist/components/moving-border/index.js +3 -0
  63. package/dist/components/moving-border/index.js.map +1 -0
  64. package/dist/components/typography/text.d.ts.map +1 -1
  65. package/dist/components/typography/text.js +1 -1
  66. package/dist/components/typography/text.js.map +1 -1
  67. package/dist/hooks/index.d.ts +1 -0
  68. package/dist/hooks/index.d.ts.map +1 -1
  69. package/dist/hooks/index.js +1 -0
  70. package/dist/hooks/index.js.map +1 -1
  71. package/dist/hooks/useMediaQuery.d.ts +2 -0
  72. package/dist/hooks/useMediaQuery.d.ts.map +1 -0
  73. package/dist/hooks/useMediaQuery.js +74 -0
  74. package/dist/hooks/useMediaQuery.js.map +1 -0
  75. package/dist/onboarding/sign-in.stories.js +93 -0
  76. package/dist/onboarding/sign-in.stories.js.map +1 -0
  77. package/dist/styles.css +1 -0
  78. package/index.css +30 -4
  79. package/package.json +19 -7
  80. package/src/build-css-entry.ts +3 -0
  81. package/src/components/button/button-link.stories.tsx +86 -0
  82. package/src/components/button/button-link.tsx +76 -0
  83. package/src/components/button/button.stories.tsx +1 -7
  84. package/src/components/button/button.tsx +8 -6
  85. package/src/components/button/icon-button.stories.tsx +182 -0
  86. package/src/components/button/icon-button.tsx +69 -0
  87. package/src/components/button/index.ts +2 -0
  88. package/src/components/code-block/code-block-footer.tsx +37 -30
  89. package/src/components/code-block/code-content.tsx +5 -2
  90. package/src/components/dynamic-item/dynamic-item.stories.tsx +1 -1
  91. package/src/components/icon/icon.tsx +6 -0
  92. package/src/components/index.ts +1 -0
  93. package/src/components/modal/index.ts +23 -0
  94. package/src/components/modal/modal.stories.tsx +384 -0
  95. package/src/components/modal/modal.tsx +309 -0
  96. package/src/components/moving-border/index.ts +1 -0
  97. package/src/components/typography/text.tsx +9 -1
  98. package/src/hooks/index.ts +1 -0
  99. package/src/hooks/useMediaQuery.ts +87 -0
  100. package/src/onboarding/sign-in.stories.tsx +73 -0
  101. package/tsconfig.build.json +7 -1
  102. package/vite.css.config.ts +30 -0
  103. package/vitest.config.ts +30 -3
@@ -0,0 +1,86 @@
1
+ import type {Meta, StoryObj} from '@storybook/react';
2
+ import {ButtonLink} from './button-link';
3
+
4
+ const meta = {
5
+ title: 'Components/Button/ButtonLink',
6
+ component: ButtonLink,
7
+ tags: ['autodocs'],
8
+ argTypes: {
9
+ variant: {
10
+ control: 'select',
11
+ options: ['base', 'interactive', 'muted', 'subtle'],
12
+ },
13
+ size: {
14
+ control: 'select',
15
+ options: ['xs', 'sm', 'md', 'xl'],
16
+ },
17
+ underline: {control: 'boolean'},
18
+ asChild: {control: 'boolean'},
19
+ },
20
+ args: {
21
+ children: 'Label',
22
+ variant: 'base',
23
+ size: 'sm',
24
+ underline: false,
25
+ href: '#',
26
+ },
27
+ } satisfies Meta<typeof ButtonLink>;
28
+
29
+ export default meta;
30
+ type Story = StoryObj<typeof meta>;
31
+
32
+ export const Default: Story = {};
33
+
34
+ export const Variants: Story = {
35
+ render: (args) => (
36
+ <div className="flex gap-16 items-center">
37
+ <ButtonLink {...args} variant="base">
38
+ Base
39
+ </ButtonLink>
40
+ <ButtonLink {...args} variant="interactive">
41
+ Interactive
42
+ </ButtonLink>
43
+ <ButtonLink {...args} variant="muted">
44
+ Muted
45
+ </ButtonLink>
46
+ <ButtonLink {...args} variant="subtle">
47
+ Subtle
48
+ </ButtonLink>
49
+ </div>
50
+ ),
51
+ };
52
+
53
+ export const WithUnderline: Story = {
54
+ render: (args) => (
55
+ <div className="flex gap-16 items-center">
56
+ <ButtonLink {...args} variant="base" underline>
57
+ Base
58
+ </ButtonLink>
59
+ <ButtonLink {...args} variant="interactive" underline>
60
+ Interactive
61
+ </ButtonLink>
62
+ <ButtonLink {...args} variant="muted" underline>
63
+ Muted
64
+ </ButtonLink>
65
+ <ButtonLink {...args} variant="subtle" underline>
66
+ Subtle
67
+ </ButtonLink>
68
+ </div>
69
+ ),
70
+ };
71
+
72
+ export const WithIcons: Story = {
73
+ render: (args) => (
74
+ <div className="flex gap-16 items-center">
75
+ <ButtonLink {...args} iconLeft="addLine">
76
+ Icon Left
77
+ </ButtonLink>
78
+ <ButtonLink {...args} iconRight="chevronRight">
79
+ Icon Right
80
+ </ButtonLink>
81
+ <ButtonLink {...args} iconLeft="addLine" iconRight="chevronRight">
82
+ Both Icons
83
+ </ButtonLink>
84
+ </div>
85
+ ),
86
+ };
@@ -0,0 +1,76 @@
1
+ import {Slot} from '@radix-ui/react-slot';
2
+ import {cva, type VariantProps} from 'class-variance-authority';
3
+ import {Icon, type IconName} from 'components/icon';
4
+ import type {ComponentProps} from 'react';
5
+ import {cn} from 'utils/cn';
6
+
7
+ export const buttonLinkVariants = cva(
8
+ 'inline-flex items-center justify-center gap-4 whitespace-nowrap transition-colors disabled:pointer-events-none outline-none font-medium',
9
+ {
10
+ variants: {
11
+ variant: {
12
+ base: 'text-foreground-neutral-base hover:text-foreground-neutral-base focus-visible:text-foreground-neutral-base disabled:text-foreground-neutral-disabled',
13
+ interactive:
14
+ 'text-foreground-highlight-interactive hover:text-foreground-highlight-interactive-hover focus-visible:text-foreground-highlight-interactive disabled:text-foreground-neutral-disabled',
15
+ muted:
16
+ 'text-foreground-neutral-muted hover:text-foreground-neutral-base focus-visible:text-foreground-neutral-base disabled:text-foreground-neutral-disabled',
17
+ subtle:
18
+ 'text-foreground-neutral-subtle hover:text-foreground-neutral-base focus-visible:text-foreground-neutral-base disabled:text-foreground-neutral-disabled',
19
+ },
20
+ size: {
21
+ xs: 'text-xs',
22
+ sm: 'text-sm',
23
+ md: 'text-md',
24
+ xl: 'text-xl',
25
+ },
26
+ underline: {
27
+ true: 'underline decoration-solid [text-underline-position:from-font]',
28
+ false: '',
29
+ },
30
+ },
31
+ defaultVariants: {
32
+ variant: 'base',
33
+ size: 'sm',
34
+ underline: false,
35
+ },
36
+ },
37
+ );
38
+
39
+ const iconSizeMap = {
40
+ xs: 14,
41
+ sm: 14,
42
+ md: 16,
43
+ xl: 20,
44
+ } as const;
45
+
46
+ export function ButtonLink({
47
+ className,
48
+ variant,
49
+ size = 'sm',
50
+ underline,
51
+ asChild = false,
52
+ children,
53
+ iconLeft,
54
+ iconRight,
55
+ ...props
56
+ }: ComponentProps<'a'> &
57
+ VariantProps<typeof buttonLinkVariants> & {
58
+ asChild?: boolean;
59
+ iconLeft?: IconName;
60
+ iconRight?: IconName;
61
+ }) {
62
+ const Comp = asChild ? Slot : 'a';
63
+ const iconSize = iconSizeMap[size as keyof typeof iconSizeMap];
64
+
65
+ return (
66
+ <Comp
67
+ data-slot="button-link"
68
+ className={cn(buttonLinkVariants({variant, size, underline, className}))}
69
+ {...props}
70
+ >
71
+ {iconLeft && <Icon name={iconLeft} size={iconSize} />}
72
+ {children}
73
+ {iconRight && <Icon name={iconRight} size={iconSize} />}
74
+ </Comp>
75
+ );
76
+ }
@@ -6,6 +6,7 @@ const variantOptions = [
6
6
  'primary',
7
7
  'secondary',
8
8
  'danger',
9
+ 'success',
9
10
  'transparent',
10
11
  'transparentMuted',
11
12
  ] as const;
@@ -48,7 +49,6 @@ export const Variants: Story = {
48
49
  <th>{size}</th>
49
50
  <th>Default</th>
50
51
  <th>Hover</th>
51
- <th>Active</th>
52
52
  <th>Focus</th>
53
53
  <th>Disabled</th>
54
54
  </tr>
@@ -71,11 +71,6 @@ export const Variants: Story = {
71
71
  Click me
72
72
  </Button>
73
73
  </td>
74
- <td>
75
- <Button {...args} variant={variant} className="active" size={size}>
76
- Click me
77
- </Button>
78
- </td>
79
74
  <td>
80
75
  <Button {...args} variant={variant} className="focus" size={size}>
81
76
  Click me
@@ -98,7 +93,6 @@ export const Variants: Story = {
98
93
  Variants.parameters = {
99
94
  pseudo: {
100
95
  hover: '.hover',
101
- active: '.active',
102
96
  focusVisible: '.focus',
103
97
  },
104
98
  };
@@ -15,18 +15,20 @@ export const buttonVariants = cva(
15
15
  'bg-background-button-neutral-default text-foreground-neutral-base shadow-button-neutral hover:bg-background-button-neutral-hover active:bg-background-button-neutral-pressed disabled:bg-background-neutral-disabled focus-visible:shadow-button-neutral-focus disabled:text-foreground-neutral-disabled disabled:shadow-none',
16
16
  danger:
17
17
  'bg-background-button-danger-default text-foreground-neutral-on-color shadow-button-danger hover:bg-background-button-danger-hover active:bg-background-button-danger-pressed focus-visible:shadow-button-danger-focus disabled:bg-background-neutral-disabled disabled:text-foreground-neutral-disabled disabled:shadow-none',
18
+ success:
19
+ 'bg-background-button-success-default text-foreground-neutral-on-color shadow-button-success hover:bg-background-button-success-hover active:bg-background-button-success-pressed focus-visible:shadow-button-success-focus disabled:bg-background-neutral-disabled disabled:text-foreground-neutral-disabled disabled:shadow-none',
18
20
  transparent:
19
21
  'bg-background-button-transparent-default text-foreground-neutral-base hover:bg-background-button-transparent-hover active:bg-background-button-transparent-pressed focus-visible:shadow-button-neutral-focus disabled:text-foreground-neutral-disabled',
20
22
  transparentMuted:
21
23
  'bg-background-button-transparent-default text-foreground-neutral-muted hover:bg-background-button-transparent-hover active:bg-background-button-transparent-pressed focus-visible:shadow-button-neutral-focus disabled:text-foreground-neutral-disabled',
22
24
  },
23
25
  size: {
24
- '2xs': 'px-6 text-xs gap-4',
25
- xs: 'px-6 py-2 text-xs gap-4',
26
- sm: 'px-8 py-4 text-sm gap-6',
27
- md: 'px-10 py-6 text-md gap-8',
28
- lg: 'px-12 py-8 text-lg gap-8',
29
- xl: 'px-12 py-10 text-xl gap-10',
26
+ '2xs': 'h-20 px-6 text-xs gap-4',
27
+ xs: 'h-24 px-6 text-xs gap-4',
28
+ sm: 'h-28 px-8 text-sm gap-6',
29
+ md: 'h-32 px-10 text-md gap-8',
30
+ lg: 'h-36 px-12 text-lg gap-8',
31
+ xl: 'h-40 px-12 text-xl gap-10',
30
32
  },
31
33
  },
32
34
  defaultVariants: {
@@ -0,0 +1,182 @@
1
+ import type {Meta, StoryObj} from '@storybook/react';
2
+ import {Code} from 'components/typography';
3
+ import {IconButton} from './icon-button';
4
+
5
+ const variantOptions = ['primary', 'transparent'] as const;
6
+ const sizeOptions = ['2xs', 'xs', 'sm', 'md', 'lg', 'xl'] as const;
7
+ const radiusOptions = ['rounded', 'full'] as const;
8
+
9
+ const meta = {
10
+ title: 'Components/Button/IconButton',
11
+ component: IconButton,
12
+ tags: ['autodocs'],
13
+ argTypes: {
14
+ variant: {
15
+ control: 'select',
16
+ options: variantOptions,
17
+ },
18
+ size: {
19
+ control: 'select',
20
+ options: sizeOptions,
21
+ },
22
+ radius: {
23
+ control: 'select',
24
+ options: radiusOptions,
25
+ },
26
+ muted: {control: 'boolean'},
27
+ asChild: {control: 'boolean'},
28
+ },
29
+ args: {
30
+ icon: 'addLine',
31
+ variant: 'primary',
32
+ size: 'md',
33
+ radius: 'rounded',
34
+ muted: false,
35
+ },
36
+ } satisfies Meta<typeof IconButton>;
37
+
38
+ export default meta;
39
+ type Story = StoryObj<typeof meta>;
40
+
41
+ export const Default: Story = {};
42
+
43
+ export const Variants: Story = {
44
+ render: (args) => (
45
+ <div className="flex flex-col gap-32">
46
+ {sizeOptions.map((size) => (
47
+ <div key={size} className="flex flex-col gap-16">
48
+ <Code variant="label" className="text-foreground-neutral-subtle">
49
+ Size: {size}
50
+ </Code>
51
+ {radiusOptions.map((radius) => (
52
+ <table
53
+ key={radius}
54
+ className="w-fit border-separate border-spacing-x-32 border-spacing-y-16"
55
+ >
56
+ <thead>
57
+ <tr>
58
+ <th>{radius}</th>
59
+ <th>Default</th>
60
+ <th>Hover</th>
61
+ <th>Focus</th>
62
+ <th>Disabled</th>
63
+ </tr>
64
+ </thead>
65
+ <tbody>
66
+ {variantOptions.map((variant) => (
67
+ <tr key={variant}>
68
+ <td>
69
+ <Code variant="label" className="text-foreground-neutral-subtle">
70
+ {variant}
71
+ </Code>
72
+ </td>
73
+ <td>
74
+ <IconButton
75
+ {...args}
76
+ icon="addLine"
77
+ aria-label="Add"
78
+ variant={variant}
79
+ size={size}
80
+ radius={radius}
81
+ />
82
+ </td>
83
+ <td>
84
+ <IconButton
85
+ {...args}
86
+ icon="addLine"
87
+ aria-label="Add"
88
+ variant={variant}
89
+ className="hover"
90
+ size={size}
91
+ radius={radius}
92
+ />
93
+ </td>
94
+ <td>
95
+ <IconButton
96
+ {...args}
97
+ icon="addLine"
98
+ aria-label="Add"
99
+ variant={variant}
100
+ className="focus"
101
+ size={size}
102
+ radius={radius}
103
+ />
104
+ </td>
105
+ <td>
106
+ <IconButton
107
+ {...args}
108
+ icon="addLine"
109
+ aria-label="Add"
110
+ variant={variant}
111
+ disabled
112
+ size={size}
113
+ radius={radius}
114
+ />
115
+ </td>
116
+ </tr>
117
+ ))}
118
+ </tbody>
119
+ </table>
120
+ ))}
121
+ </div>
122
+ ))}
123
+ </div>
124
+ ),
125
+ };
126
+
127
+ Variants.parameters = {
128
+ pseudo: {
129
+ hover: '.hover',
130
+ focusVisible: '.focus',
131
+ },
132
+ };
133
+
134
+ export const Muted: Story = {
135
+ render: (args) => (
136
+ <div className="flex flex-col gap-16">
137
+ <div className="flex gap-16 items-center">
138
+ <Code variant="label">Normal:</Code>
139
+ <IconButton {...args} icon="addLine" aria-label="Add" />
140
+ <IconButton {...args} icon="addLine" aria-label="Add" variant="transparent" />
141
+ </div>
142
+ <div className="flex gap-16 items-center">
143
+ <Code variant="label">Muted:</Code>
144
+ <IconButton {...args} icon="addLine" aria-label="Add" muted />
145
+ <IconButton {...args} icon="addLine" aria-label="Add" variant="transparent" muted />
146
+ </div>
147
+ </div>
148
+ ),
149
+ };
150
+
151
+ export const Sizes: Story = {
152
+ render: ({children: _children, ...args}) => (
153
+ <div className="flex flex-col gap-16">
154
+ <div className="flex gap-16 items-center">
155
+ <Code variant="label">Rounded:</Code>
156
+ {sizeOptions.map((size) => (
157
+ <IconButton
158
+ {...args}
159
+ key={size}
160
+ icon="addLine"
161
+ aria-label="Add"
162
+ size={size}
163
+ radius="rounded"
164
+ />
165
+ ))}
166
+ </div>
167
+ <div className="flex gap-16 items-center">
168
+ <Code variant="label">Full:</Code>
169
+ {sizeOptions.map((size) => (
170
+ <IconButton
171
+ {...args}
172
+ key={size}
173
+ icon="addLine"
174
+ aria-label="Add"
175
+ size={size}
176
+ radius="full"
177
+ />
178
+ ))}
179
+ </div>
180
+ </div>
181
+ ),
182
+ };
@@ -0,0 +1,69 @@
1
+ import {Slot} from '@radix-ui/react-slot';
2
+ import {cva, type VariantProps} from 'class-variance-authority';
3
+ import {Icon, type IconName} from 'components/icon';
4
+ import type {ComponentProps} from 'react';
5
+ import {cn} from 'utils/cn';
6
+
7
+ export const iconButtonVariants = cva(
8
+ 'inline-flex items-center justify-center whitespace-nowrap transition-colors disabled:pointer-events-none shrink-0 outline-none',
9
+ {
10
+ variants: {
11
+ variant: {
12
+ primary:
13
+ 'bg-background-button-inverted-default text-tag-neutral-icon shadow-button-inverted hover:bg-background-button-inverted-hover active:bg-background-button-inverted-pressed focus-visible:shadow-button-inverted-focus disabled:bg-background-neutral-disabled disabled:text-foreground-neutral-disabled disabled:shadow-none',
14
+ transparent:
15
+ 'bg-background-button-transparent-default text-tag-neutral-icon hover:bg-background-button-transparent-hover active:bg-background-button-transparent-pressed focus-visible:shadow-button-neutral-focus disabled:text-foreground-neutral-disabled',
16
+ },
17
+ size: {
18
+ '2xs': 'w-20 h-20 text-xs',
19
+ xs: 'w-24 h-24 text-xs',
20
+ sm: 'w-28 h-28 text-sm',
21
+ md: 'w-32 h-32 text-md',
22
+ lg: 'w-36 h-36 text-lg',
23
+ xl: 'w-40 h-40 text-xl',
24
+ },
25
+ radius: {
26
+ rounded: 'rounded-6',
27
+ full: 'rounded-full',
28
+ },
29
+ muted: {
30
+ true: 'opacity-60',
31
+ false: '',
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ variant: 'primary',
36
+ size: 'md',
37
+ radius: 'rounded',
38
+ muted: false,
39
+ },
40
+ },
41
+ );
42
+
43
+ export function IconButton({
44
+ className,
45
+ variant,
46
+ size,
47
+ radius,
48
+ muted,
49
+ asChild = false,
50
+ children,
51
+ icon,
52
+ ...props
53
+ }: ComponentProps<'button'> &
54
+ VariantProps<typeof iconButtonVariants> & {
55
+ asChild?: boolean;
56
+ icon?: IconName;
57
+ }) {
58
+ const Comp = asChild ? Slot : 'button';
59
+
60
+ return (
61
+ <Comp
62
+ data-slot="icon-button"
63
+ className={cn(iconButtonVariants({variant, size, radius, muted}), className)}
64
+ {...props}
65
+ >
66
+ {icon ? <Icon name={icon} /> : children}
67
+ </Comp>
68
+ );
69
+ }
@@ -1 +1,3 @@
1
1
  export * from './button';
2
+ export * from './button-link';
3
+ export * from './icon-button';
@@ -1,5 +1,6 @@
1
1
  import {Slot} from '@radix-ui/react-slot';
2
2
  import {Icon} from 'components/icon/icon';
3
+ import {Text} from 'components/typography';
3
4
  import type {ComponentProps, HTMLAttributes, ReactNode} from 'react';
4
5
  import {cn} from 'utils/cn';
5
6
 
@@ -53,22 +54,12 @@ export function CodeBlockFooter({
53
54
  className={cn('flex w-full items-center justify-start gap-12 px-16 py-12', className)}
54
55
  {...props}
55
56
  >
56
- <div className="flex shrink-0 items-center justify-center size-20 text-tag-success-icon">
57
- {defaultIcon}
58
- </div>
57
+ <CodeBlockFooterIcon className="text-tag-success-icon">{defaultIcon}</CodeBlockFooterIcon>
59
58
  {(message || description) && (
60
- <div className="flex flex-col items-start justify-center gap-0">
61
- {message && (
62
- <div className="overflow-hidden text-ellipsis whitespace-nowrap text-xs leading-20 text-foreground-neutral-base">
63
- {message}
64
- </div>
65
- )}
66
- {description && (
67
- <div className="overflow-hidden text-ellipsis whitespace-nowrap text-xs leading-20 text-foreground-neutral-subtle">
68
- {description}
69
- </div>
70
- )}
71
- </div>
59
+ <CodeBlockFooterContent>
60
+ {message && <CodeBlockFooterMessage>{message}</CodeBlockFooterMessage>}
61
+ {description && <CodeBlockFooterDescription>{description}</CodeBlockFooterDescription>}
62
+ </CodeBlockFooterContent>
72
63
  )}
73
64
  </Comp>
74
65
  );
@@ -112,7 +103,7 @@ export function CodeBlockFooterContent({
112
103
  return (
113
104
  <Comp
114
105
  data-slot="code-block-footer-content"
115
- className={cn('flex flex-col items-start justify-center gap-0', className)}
106
+ className={cn('flex flex-col items-start justify-center gap-0 min-w-0 flex-1', className)}
116
107
  {...props}
117
108
  >
118
109
  {children}
@@ -130,19 +121,27 @@ export function CodeBlockFooterMessage({
130
121
  children,
131
122
  ...props
132
123
  }: CodeBlockFooterMessageProps) {
133
- const Comp = asChild ? Slot : 'div';
124
+ if (asChild) {
125
+ return (
126
+ <Slot
127
+ data-slot="code-block-footer-message"
128
+ className={cn('overflow-hidden text-ellipsis whitespace-nowrap text-xs', className)}
129
+ {...props}
130
+ >
131
+ {children}
132
+ </Slot>
133
+ );
134
+ }
134
135
 
135
136
  return (
136
- <Comp
137
+ <Text
137
138
  data-slot="code-block-footer-message"
138
- className={cn(
139
- 'overflow-hidden text-ellipsis whitespace-nowrap text-xs leading-20 text-foreground-neutral-base',
140
- className,
141
- )}
139
+ size="xs"
140
+ className={cn('overflow-hidden text-ellipsis whitespace-nowrap', className)}
142
141
  {...props}
143
142
  >
144
143
  {children}
145
- </Comp>
144
+ </Text>
146
145
  );
147
146
  }
148
147
 
@@ -156,18 +155,26 @@ export function CodeBlockFooterDescription({
156
155
  children,
157
156
  ...props
158
157
  }: CodeBlockFooterDescriptionProps) {
159
- const Comp = asChild ? Slot : 'div';
158
+ if (asChild) {
159
+ return (
160
+ <Slot
161
+ data-slot="code-block-footer-description"
162
+ className={cn('text-xs text-foreground-neutral-subtle', className)}
163
+ {...props}
164
+ >
165
+ {children}
166
+ </Slot>
167
+ );
168
+ }
160
169
 
161
170
  return (
162
- <Comp
171
+ <Text
163
172
  data-slot="code-block-footer-description"
164
- className={cn(
165
- 'overflow-hidden text-ellipsis whitespace-nowrap text-xs leading-20 text-foreground-neutral-subtle',
166
- className,
167
- )}
173
+ size="xs"
174
+ className={cn('text-foreground-neutral-subtle', className)}
168
175
  {...props}
169
176
  >
170
177
  {children}
171
- </Comp>
178
+ </Text>
172
179
  );
173
180
  }
@@ -49,8 +49,11 @@ export function CodeContent({
49
49
  '[counter-reset:line] [counter-increment:line_0] [&_.line]:before:content-[counter(line)] [&_.line]:before:inline-block [&_.line]:before:[counter-increment:line] [&_.line]:before:w-16 [&_.line]:before:mr-16 [&_.line]:before:text-xs [&_.line]:before:text-right [&_.line]:before:text-foreground-neutral-subtle [&_.line]:before:font-code [&_.line]:before:select-none',
50
50
  )}
51
51
  >
52
- {lines.map((line) => (
53
- <span className="line px-12 w-full relative font-code text-xs leading-20" key={line}>
52
+ {lines.map((line, index) => (
53
+ <span
54
+ className="line px-12 w-full relative font-code text-xs leading-20"
55
+ key={`${index}-${line}`}
56
+ >
54
57
  {line}
55
58
  </span>
56
59
  ))}
@@ -1,6 +1,7 @@
1
1
  import type {Meta, StoryObj} from '@storybook/react';
2
2
  import {Button} from 'components/button/button';
3
3
  import {ItemTitle} from 'components/item';
4
+ import {MovingBorder} from 'components/moving-border';
4
5
  import {cn} from 'utils/cn';
5
6
  import illustration1 from '../../assets/illustration-1.svg';
6
7
  import illustration2 from '../../assets/illustration-2.svg';
@@ -8,7 +9,6 @@ import illustrationBg from '../../assets/illustration-gradient.svg';
8
9
  import {Avatar} from '../avatar/avatar';
9
10
  import {AvatarGroup, AvatarGroupTooltip} from '../avatar/avatar-group';
10
11
  import {Icon} from '../icon/icon';
11
- import {MovingBorder} from '../moving-border/moving-border';
12
12
  import {DynamicItem} from './dynamic-item';
13
13
 
14
14
  const meta = {
@@ -1,5 +1,8 @@
1
1
  import {
2
2
  type RemixiconComponentType,
3
+ RiAddLine,
4
+ RiArrowRightSLine,
5
+ RiBookOpenFill,
3
6
  RiCheckLine,
4
7
  RiCloseLine,
5
8
  RiFileCopyLine,
@@ -56,6 +59,9 @@ const iconsMap = {
56
59
  money: RiMoneyDollarCircleLine,
57
60
  homeSmile: RiHomeSmileFill,
58
61
  copy: RiFileCopyLine,
62
+ addLine: RiAddLine,
63
+ chevronRight: RiArrowRightSLine,
64
+ bookOpen: RiBookOpenFill,
59
65
  } as const satisfies Record<string, RemixiconComponentType>;
60
66
 
61
67
  export type IconName = keyof typeof iconsMap;
@@ -10,6 +10,7 @@ export * from './inline-tips';
10
10
  export * from './input';
11
11
  export * from './item';
12
12
  export * from './label';
13
+ export * from './modal';
13
14
  export * from './textarea';
14
15
  export * from './theme';
15
16
  export * from './toast';
@@ -0,0 +1,23 @@
1
+ export type {
2
+ ModalContentProps,
3
+ ModalDescriptionProps,
4
+ ModalHeaderProps,
5
+ ModalOverlayProps,
6
+ ModalTitleProps,
7
+ } from './modal';
8
+ export {
9
+ Modal,
10
+ ModalBody,
11
+ ModalClose,
12
+ ModalContent,
13
+ ModalDescription,
14
+ ModalFooter,
15
+ ModalHeader,
16
+ ModalOverlay,
17
+ ModalPortal,
18
+ ModalTitle,
19
+ ModalTrigger,
20
+ modalContentVariants,
21
+ modalDefaultTransition,
22
+ modalOverlayVariants,
23
+ } from './modal';