@shipfox/react-ui 0.1.0 → 0.3.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 (98) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/.turbo/turbo-check.log +3 -3
  3. package/.turbo/turbo-type.log +1 -1
  4. package/CHANGELOG.md +12 -0
  5. package/dist/components/alert/alert.d.ts +18 -0
  6. package/dist/components/alert/alert.d.ts.map +1 -0
  7. package/dist/components/alert/alert.js +123 -0
  8. package/dist/components/alert/alert.js.map +1 -0
  9. package/dist/components/alert/alert.stories.js +112 -0
  10. package/dist/components/alert/alert.stories.js.map +1 -0
  11. package/dist/components/alert/index.d.ts +2 -0
  12. package/dist/components/alert/index.d.ts.map +1 -0
  13. package/dist/components/alert/index.js +3 -0
  14. package/dist/components/alert/index.js.map +1 -0
  15. package/dist/components/avatar/avatar-group.d.ts +18 -0
  16. package/dist/components/avatar/avatar-group.d.ts.map +1 -0
  17. package/dist/components/avatar/avatar-group.js +132 -0
  18. package/dist/components/avatar/avatar-group.js.map +1 -0
  19. package/dist/components/avatar/avatar.d.ts +21 -0
  20. package/dist/components/avatar/avatar.d.ts.map +1 -0
  21. package/dist/components/avatar/avatar.js +166 -0
  22. package/dist/components/avatar/avatar.js.map +1 -0
  23. package/dist/components/avatar/avatar.stories.js +255 -0
  24. package/dist/components/avatar/avatar.stories.js.map +1 -0
  25. package/dist/components/avatar/index.d.ts +3 -0
  26. package/dist/components/avatar/index.d.ts.map +1 -0
  27. package/dist/components/avatar/index.js +4 -0
  28. package/dist/components/avatar/index.js.map +1 -0
  29. package/dist/components/icon/custom/index.d.ts +1 -0
  30. package/dist/components/icon/custom/index.d.ts.map +1 -1
  31. package/dist/components/icon/custom/index.js +1 -0
  32. package/dist/components/icon/custom/index.js.map +1 -1
  33. package/dist/components/icon/custom/shipfox-logo.d.ts +8 -0
  34. package/dist/components/icon/custom/shipfox-logo.d.ts.map +1 -0
  35. package/dist/components/icon/custom/shipfox-logo.js +22 -0
  36. package/dist/components/icon/custom/shipfox-logo.js.map +1 -0
  37. package/dist/components/icon/icon.d.ts +4 -1
  38. package/dist/components/icon/icon.d.ts.map +1 -1
  39. package/dist/components/icon/icon.js +6 -3
  40. package/dist/components/icon/icon.js.map +1 -1
  41. package/dist/components/index.d.ts +4 -0
  42. package/dist/components/index.d.ts.map +1 -1
  43. package/dist/components/index.js +4 -0
  44. package/dist/components/index.js.map +1 -1
  45. package/dist/components/inline-tips/index.d.ts +2 -0
  46. package/dist/components/inline-tips/index.d.ts.map +1 -0
  47. package/dist/components/inline-tips/index.js +3 -0
  48. package/dist/components/inline-tips/index.js.map +1 -0
  49. package/dist/components/inline-tips/inline-tips.d.ts +19 -0
  50. package/dist/components/inline-tips/inline-tips.d.ts.map +1 -0
  51. package/dist/components/inline-tips/inline-tips.js +98 -0
  52. package/dist/components/inline-tips/inline-tips.js.map +1 -0
  53. package/dist/components/inline-tips/inline-tips.stories.js +214 -0
  54. package/dist/components/inline-tips/inline-tips.stories.js.map +1 -0
  55. package/dist/components/textarea/index.d.ts +2 -0
  56. package/dist/components/textarea/index.d.ts.map +1 -0
  57. package/dist/components/textarea/index.js +3 -0
  58. package/dist/components/textarea/index.js.map +1 -0
  59. package/dist/components/textarea/textarea.d.ts +10 -0
  60. package/dist/components/textarea/textarea.d.ts.map +1 -0
  61. package/dist/components/textarea/textarea.js +31 -0
  62. package/dist/components/textarea/textarea.js.map +1 -0
  63. package/dist/components/textarea/textarea.stories.js +333 -0
  64. package/dist/components/textarea/textarea.stories.js.map +1 -0
  65. package/dist/components/tooltip/tooltip.d.ts +7 -0
  66. package/dist/components/tooltip/tooltip.d.ts.map +1 -0
  67. package/dist/components/tooltip/tooltip.js +38 -0
  68. package/dist/components/tooltip/tooltip.js.map +1 -0
  69. package/dist/utils/avatar.d.ts +3 -0
  70. package/dist/utils/avatar.d.ts.map +1 -0
  71. package/dist/utils/avatar.js +32 -0
  72. package/dist/utils/avatar.js.map +1 -0
  73. package/dist/utils/index.d.ts +1 -0
  74. package/dist/utils/index.d.ts.map +1 -1
  75. package/dist/utils/index.js +1 -0
  76. package/dist/utils/index.js.map +1 -1
  77. package/index.css +32 -1
  78. package/package.json +5 -5
  79. package/src/components/alert/alert.stories.tsx +77 -0
  80. package/src/components/alert/alert.tsx +144 -0
  81. package/src/components/alert/index.ts +1 -0
  82. package/src/components/avatar/avatar-group.tsx +186 -0
  83. package/src/components/avatar/avatar.stories.tsx +172 -0
  84. package/src/components/avatar/avatar.tsx +215 -0
  85. package/src/components/avatar/index.ts +2 -0
  86. package/src/components/icon/custom/index.ts +1 -0
  87. package/src/components/icon/custom/shipfox-logo.tsx +20 -0
  88. package/src/components/icon/icon.tsx +11 -1
  89. package/src/components/index.ts +4 -0
  90. package/src/components/inline-tips/index.ts +1 -0
  91. package/src/components/inline-tips/inline-tips.stories.tsx +126 -0
  92. package/src/components/inline-tips/inline-tips.tsx +132 -0
  93. package/src/components/textarea/index.ts +1 -0
  94. package/src/components/textarea/textarea.stories.tsx +190 -0
  95. package/src/components/textarea/textarea.tsx +42 -0
  96. package/src/components/tooltip/tooltip.tsx +52 -0
  97. package/src/utils/avatar.ts +27 -0
  98. package/src/utils/index.ts +1 -0
@@ -0,0 +1,215 @@
1
+ import * as AvatarPrimitive from '@radix-ui/react-avatar';
2
+ import {cva, type VariantProps} from 'class-variance-authority';
3
+ import type {ComponentProps, ReactNode} from 'react';
4
+ import {getInitial, getPlaceholderImageUrl} from 'utils';
5
+ import {cn} from 'utils/cn';
6
+ import {Icon} from '../icon/icon';
7
+
8
+ export const avatarVariants = cva(
9
+ 'relative flex shrink-0 overflow-hidden bg-background-button-neutral-default text-foreground-neutral-base ring-1 ring-border-neutral-base-component ring-offset-1 ring-offset-background-neutral-base shadow-button-neutral',
10
+ {
11
+ variants: {
12
+ radius: {
13
+ full: 'rounded-full',
14
+ rounded: 'rounded-6',
15
+ },
16
+ size: {
17
+ '3xs': 'size-[18px]',
18
+ '2xs': 'size-[20px]',
19
+ xs: 'size-[24px]',
20
+ sm: 'size-[28px]',
21
+ md: 'size-[32px]',
22
+ lg: 'size-[36px]',
23
+ xl: 'size-[40px]',
24
+ '2xl': 'size-[80px]',
25
+ '3xl': 'size-[120px]',
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ radius: 'full',
30
+ size: 'md',
31
+ },
32
+ },
33
+ );
34
+
35
+ const avatarInnerVariants = cva('flex h-full w-full items-center justify-center', {
36
+ variants: {
37
+ size: {
38
+ '3xs': 'text-[10px] leading-[10px]',
39
+ '2xs': 'text-[11px] leading-[11px]',
40
+ xs: 'text-xs leading-4',
41
+ sm: 'text-xs leading-5',
42
+ md: 'text-sm leading-5',
43
+ lg: 'text-sm leading-5',
44
+ xl: 'text-base leading-6',
45
+ '2xl': 'text-2xl leading-8',
46
+ '3xl': 'text-4xl leading-[56px]',
47
+ },
48
+ },
49
+ defaultVariants: {
50
+ size: 'md',
51
+ },
52
+ });
53
+
54
+ export type AvatarContent = 'letters' | 'logo' | 'logoPlaceholder' | 'image' | 'upload';
55
+
56
+ const UPLOAD_ICON_SIZE_MAP: Record<
57
+ NonNullable<VariantProps<typeof avatarVariants>['size']>,
58
+ string
59
+ > = {
60
+ '3xs': 'size-[10px]',
61
+ '2xs': 'size-[12px]',
62
+ xs: 'size-[14px]',
63
+ sm: 'size-[16px]',
64
+ md: 'size-[18px]',
65
+ lg: 'size-[20px]',
66
+ xl: 'size-[24px]',
67
+ '2xl': 'size-[40px]',
68
+ '3xl': 'size-[60px]',
69
+ } as const;
70
+
71
+ function AvatarRoot({
72
+ className,
73
+ radius,
74
+ size,
75
+ ...props
76
+ }: ComponentProps<typeof AvatarPrimitive.Root> & VariantProps<typeof avatarVariants>) {
77
+ return (
78
+ <AvatarPrimitive.Root
79
+ data-slot="avatar"
80
+ className={cn(avatarVariants({radius, size}), className)}
81
+ {...props}
82
+ />
83
+ );
84
+ }
85
+
86
+ function AvatarImage({className, ...props}: ComponentProps<typeof AvatarPrimitive.Image>) {
87
+ return (
88
+ <AvatarPrimitive.Image
89
+ data-slot="avatar-image"
90
+ className={cn('aspect-square size-full', className)}
91
+ {...props}
92
+ />
93
+ );
94
+ }
95
+
96
+ function AvatarFallback({className, ...props}: ComponentProps<typeof AvatarPrimitive.Fallback>) {
97
+ return (
98
+ <AvatarPrimitive.Fallback
99
+ data-slot="avatar-name"
100
+ className={cn('flex size-full items-center justify-center', className)}
101
+ {...props}
102
+ />
103
+ );
104
+ }
105
+
106
+ export type AvatarProps = ComponentProps<typeof AvatarPrimitive.Root> &
107
+ VariantProps<typeof avatarVariants> & {
108
+ content?: AvatarContent;
109
+ src?: string;
110
+ alt?: string;
111
+ fallback?: string;
112
+ animateOnHover?: boolean;
113
+ };
114
+
115
+ export function Avatar({
116
+ className,
117
+ radius,
118
+ size = 'md',
119
+ content = 'letters',
120
+ src,
121
+ alt,
122
+ fallback,
123
+ animateOnHover = false,
124
+ ...props
125
+ }: AvatarProps) {
126
+ const innerClassName =
127
+ 'flex h-full w-full items-center justify-center rounded-inherit relative bg-background-neutral-base dark:bg-background-components-base text-foreground-neutral-subtle';
128
+
129
+ const renderContent = (): ReactNode => {
130
+ if (content === 'image') {
131
+ const imageSrc = src || getPlaceholderImageUrl(fallback);
132
+ return (
133
+ <>
134
+ <AvatarImage
135
+ src={imageSrc}
136
+ alt={alt || 'Avatar image'}
137
+ className="object-scale-down rounded-inherit"
138
+ />
139
+ <AvatarFallback className={innerClassName}>
140
+ <div
141
+ className={cn(
142
+ 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
143
+ avatarInnerVariants({size}),
144
+ )}
145
+ >
146
+ <span className="font-medium">{getInitial(fallback)}</span>
147
+ </div>
148
+ </AvatarFallback>
149
+ </>
150
+ );
151
+ }
152
+
153
+ if (content === 'logo') {
154
+ return (
155
+ <AvatarFallback className={cn(innerClassName, 'p-[15%]')}>
156
+ <Icon name="shipfoxLogo" color="#FF4B00" className="h-full w-full p-2" />
157
+ </AvatarFallback>
158
+ );
159
+ }
160
+
161
+ if (content === 'logoPlaceholder') {
162
+ return (
163
+ <AvatarFallback className={cn(innerClassName, 'p-[15%]')}>
164
+ <Icon
165
+ name="shipfoxLogo"
166
+ color="var(--foreground-neutral-subtle, #a1a1aa)"
167
+ className="h-full w-full p-2 opacity-50"
168
+ />
169
+ </AvatarFallback>
170
+ );
171
+ }
172
+
173
+ if (content === 'letters') {
174
+ return (
175
+ <AvatarFallback className={innerClassName}>
176
+ <div
177
+ className={cn(
178
+ 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
179
+ avatarInnerVariants({size}),
180
+ )}
181
+ >
182
+ <span className="font-medium">{getInitial(fallback)}</span>
183
+ </div>
184
+ </AvatarFallback>
185
+ );
186
+ }
187
+
188
+ if (content === 'upload') {
189
+ const iconSizeClass = UPLOAD_ICON_SIZE_MAP[size as keyof typeof UPLOAD_ICON_SIZE_MAP];
190
+ return (
191
+ <AvatarFallback className={innerClassName}>
192
+ <Icon name="imageAdd" className={cn('text-foreground-neutral-subtle', iconSizeClass)} />
193
+ </AvatarFallback>
194
+ );
195
+ }
196
+
197
+ return null;
198
+ };
199
+
200
+ return (
201
+ <AvatarRoot
202
+ className={cn(
203
+ animateOnHover ? 'hover:-translate-y-8 transition-transform duration-300 ease-out' : '',
204
+ className,
205
+ )}
206
+ radius={radius}
207
+ size={size}
208
+ {...props}
209
+ >
210
+ {renderContent()}
211
+ </AvatarRoot>
212
+ );
213
+ }
214
+
215
+ export {AvatarRoot, AvatarImage, AvatarFallback};
@@ -0,0 +1,2 @@
1
+ export * from './avatar';
2
+ export * from './avatar-group';
@@ -6,6 +6,7 @@ export * from './component-line';
6
6
  export * from './ellipse-mini-solid';
7
7
  export * from './info-tooltip-fill';
8
8
  export * from './resize';
9
+ export * from './shipfox-logo';
9
10
  export * from './spinner';
10
11
  export * from './thunder';
11
12
  export * from './x-circle-solid';
@@ -0,0 +1,20 @@
1
+ import type {RemixiconComponentType} from '@remixicon/react';
2
+ import type {ComponentProps} from 'react';
3
+
4
+ type ShipfoxLogoProps = ComponentProps<RemixiconComponentType> & {
5
+ color?: string;
6
+ };
7
+
8
+ export function ShipfoxLogo({color = '#FF4B00', ...props}: ShipfoxLogoProps) {
9
+ return (
10
+ <svg viewBox="0 0 88 88" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
11
+ <title>Shipfox Logo</title>
12
+ <path
13
+ fillRule="evenodd"
14
+ clipRule="evenodd"
15
+ d="M17.9759 32.3751L39.0987 74.1549C41.1536 78.2196 46.847 78.2196 48.902 74.1549L70.0247 32.3751L81.2835 38.122C84.6511 39.8409 85.3794 44.4228 82.7171 47.1406L47.9008 82.684C45.7466 84.8831 42.254 84.8831 40.0999 82.684L5.28351 47.1406C2.62124 44.4227 3.34957 39.8409 6.7171 38.122L17.9759 32.3751ZM44.0003 19.0912L73.0051 4.28593C77.7786 1.84936 82.8214 7.06388 80.3737 11.9054L70.0247 32.3751L44.0003 19.0912ZM44.0003 19.0912L14.9955 4.28593C10.2221 1.84936 5.17926 7.06388 7.62699 11.9054L17.9759 32.3751L44.0003 19.0912Z"
16
+ fill={color}
17
+ />
18
+ </svg>
19
+ );
20
+ }
@@ -1,4 +1,10 @@
1
- import {type RemixiconComponentType, RiGoogleFill, RiMicrosoftFill} from '@remixicon/react';
1
+ import {
2
+ type RemixiconComponentType,
3
+ RiCloseLine,
4
+ RiGoogleFill,
5
+ RiImageAddFill,
6
+ RiMicrosoftFill,
7
+ } from '@remixicon/react';
2
8
  import type {ComponentProps} from 'react';
3
9
  import {
4
10
  BadgeIcon,
@@ -9,6 +15,7 @@ import {
9
15
  EllipseMiniSolidIcon,
10
16
  InfoTooltipFillIcon,
11
17
  ResizeIcon,
18
+ ShipfoxLogo,
12
19
  SpinnerIcon,
13
20
  ThunderIcon,
14
21
  XCircleSolidIcon,
@@ -28,6 +35,9 @@ const iconsMap = {
28
35
  spinner: SpinnerIcon,
29
36
  ellipseMiniSolid: EllipseMiniSolidIcon,
30
37
  componentLine: ComponentLineIcon,
38
+ imageAdd: RiImageAddFill,
39
+ close: RiCloseLine,
40
+ shipfoxLogo: ShipfoxLogo,
31
41
  } as const satisfies Record<string, RemixiconComponentType>;
32
42
 
33
43
  export type IconName = keyof typeof iconsMap;
@@ -1,4 +1,8 @@
1
+ export * from './alert';
2
+ export * from './avatar';
1
3
  export * from './button';
2
4
  export * from './icon';
5
+ export * from './inline-tips';
6
+ export * from './textarea';
3
7
  export * from './theme-provider';
4
8
  export * from './typography';
@@ -0,0 +1 @@
1
+ export * from './inline-tips';
@@ -0,0 +1,126 @@
1
+ import type {Meta, StoryObj} from '@storybook/react';
2
+ import {Code, Header} from 'components/typography';
3
+ import {
4
+ InlineTips,
5
+ InlineTipsAction,
6
+ InlineTipsActions,
7
+ InlineTipsContent,
8
+ InlineTipsDescription,
9
+ InlineTipsTitle,
10
+ } from './inline-tips';
11
+
12
+ const meta = {
13
+ title: 'Components/InlineTips',
14
+ component: InlineTips,
15
+ tags: ['autodocs'],
16
+ argTypes: {
17
+ type: {
18
+ control: 'select',
19
+ options: ['default', 'info', 'success', 'destructive'],
20
+ },
21
+ variant: {
22
+ control: 'select',
23
+ options: ['primary', 'secondary'],
24
+ },
25
+ },
26
+ args: {
27
+ type: 'default',
28
+ variant: 'primary',
29
+ },
30
+ } satisfies Meta<typeof InlineTips>;
31
+
32
+ export default meta;
33
+
34
+ type Story = StoryObj<typeof meta>;
35
+
36
+ const types = ['default', 'info', 'success', 'destructive'] as const;
37
+ const variants = ['primary', 'secondary'] as const;
38
+
39
+ export const Default: Story = {
40
+ render: (args) => {
41
+ return (
42
+ <InlineTips {...args}>
43
+ <InlineTipsContent>
44
+ <InlineTipsTitle>Title</InlineTipsTitle>
45
+ <InlineTipsDescription>Description</InlineTipsDescription>
46
+ </InlineTipsContent>
47
+ <InlineTipsActions>
48
+ <InlineTipsAction variant={args.variant}>Label</InlineTipsAction>
49
+ <InlineTipsAction variant={args.variant}>Label</InlineTipsAction>
50
+ </InlineTipsActions>
51
+ </InlineTips>
52
+ );
53
+ },
54
+ };
55
+
56
+ export const Variants: Story = {
57
+ render: () => {
58
+ return (
59
+ <div className="flex flex-col gap-16">
60
+ {variants.map((variant) => (
61
+ <InlineTips key={variant} type="default" variant={variant}>
62
+ <InlineTipsContent>
63
+ <InlineTipsTitle>Title</InlineTipsTitle>
64
+ <InlineTipsDescription>Description</InlineTipsDescription>
65
+ </InlineTipsContent>
66
+ <InlineTipsActions>
67
+ <InlineTipsAction variant="primary">Label</InlineTipsAction>
68
+ <InlineTipsAction variant="secondary">Label</InlineTipsAction>
69
+ </InlineTipsActions>
70
+ </InlineTips>
71
+ ))}
72
+ </div>
73
+ );
74
+ },
75
+ };
76
+
77
+ export const DesignMock: Story = {
78
+ render: () => {
79
+ const content = {
80
+ default: {title: 'Title', description: 'Description'},
81
+ info: {title: 'Title', description: 'Description'},
82
+ success: {title: 'Title', description: 'Description'},
83
+ destructive: {title: "Don't's", description: 'Title'},
84
+ };
85
+
86
+ return (
87
+ <div className="flex flex-col gap-32 pb-64 pt-32 px-32 bg-background-neutral-base">
88
+ <Header variant="h3" className="text-foreground-neutral-subtle">
89
+ INLINE TIPS
90
+ </Header>
91
+ <div className="flex flex-col gap-16">
92
+ <Code variant="label" className="text-foreground-neutral-subtle">
93
+ Primary
94
+ </Code>
95
+ {types.map((type) => (
96
+ <InlineTips key={type} type={type} variant="primary">
97
+ <InlineTipsContent>
98
+ <InlineTipsTitle>{content[type].title}</InlineTipsTitle>
99
+ <InlineTipsDescription>{content[type].description}</InlineTipsDescription>
100
+ </InlineTipsContent>
101
+ <InlineTipsActions>
102
+ <InlineTipsAction variant="primary">Label</InlineTipsAction>
103
+ <InlineTipsAction variant="secondary">Label</InlineTipsAction>
104
+ </InlineTipsActions>
105
+ </InlineTips>
106
+ ))}
107
+ <Code variant="label" className="text-foreground-neutral-subtle">
108
+ Secondary
109
+ </Code>
110
+ {types.map((type) => (
111
+ <InlineTips key={type} type={type} variant="secondary">
112
+ <InlineTipsContent>
113
+ <InlineTipsTitle>{content[type].title}</InlineTipsTitle>
114
+ <InlineTipsDescription>{content[type].description}</InlineTipsDescription>
115
+ </InlineTipsContent>
116
+ <InlineTipsActions>
117
+ <InlineTipsAction variant="primary">Label</InlineTipsAction>
118
+ <InlineTipsAction variant="secondary">Label</InlineTipsAction>
119
+ </InlineTipsActions>
120
+ </InlineTips>
121
+ ))}
122
+ </div>
123
+ </div>
124
+ );
125
+ },
126
+ };
@@ -0,0 +1,132 @@
1
+ import {cva, type VariantProps} from 'class-variance-authority';
2
+ import type {ComponentProps} from 'react';
3
+ import {cn} from 'utils/cn';
4
+
5
+ const inlineTipsBaseVariants = cva('w-full text-sm flex gap-12 items-center', {
6
+ variants: {
7
+ variant: {
8
+ primary:
9
+ 'bg-background-components-base text-foreground-neutral-base border border-border-neutral-base shadow-button-neutral rounded-8 px-12 py-8',
10
+ secondary: 'bg-transparent text-foreground-neutral-base',
11
+ },
12
+ },
13
+ defaultVariants: {
14
+ variant: 'primary',
15
+ },
16
+ });
17
+
18
+ const inlineTipsLineVariants = cva('w-4 self-stretch my-4 rounded-full', {
19
+ variants: {
20
+ type: {
21
+ default: 'bg-tag-neutral-icon',
22
+ info: 'bg-tag-warning-icon',
23
+ success: 'bg-tag-success-icon',
24
+ destructive: 'bg-tag-error-icon',
25
+ },
26
+ },
27
+ defaultVariants: {
28
+ type: 'default',
29
+ },
30
+ });
31
+
32
+ type InlineTipsProps = ComponentProps<'div'> &
33
+ VariantProps<typeof inlineTipsBaseVariants> & {
34
+ type?: 'default' | 'info' | 'success' | 'destructive';
35
+ };
36
+
37
+ function InlineTips({className, variant, type = 'default', children, ...props}: InlineTipsProps) {
38
+ return (
39
+ <div
40
+ data-slot="inline-tips"
41
+ className={cn(inlineTipsBaseVariants({variant}), className)}
42
+ {...props}
43
+ >
44
+ <div
45
+ data-slot="inline-tips-line"
46
+ className={cn(inlineTipsLineVariants({type}))}
47
+ aria-hidden="true"
48
+ />
49
+ {children}
50
+ </div>
51
+ );
52
+ }
53
+
54
+ function InlineTipsContent({className, ...props}: ComponentProps<'div'>) {
55
+ return (
56
+ <div data-slot="inline-tips-content" className={cn('flex-1 min-w-0', className)} {...props} />
57
+ );
58
+ }
59
+
60
+ function InlineTipsTitle({className, ...props}: ComponentProps<'div'>) {
61
+ return (
62
+ <div
63
+ data-slot="inline-tips-title"
64
+ className={cn('font-medium text-sm leading-20 text-foreground-neutral-base mb-4', className)}
65
+ {...props}
66
+ />
67
+ );
68
+ }
69
+
70
+ function InlineTipsDescription({className, ...props}: ComponentProps<'div'>) {
71
+ return (
72
+ <div
73
+ data-slot="inline-tips-description"
74
+ className={cn(
75
+ 'text-xs leading-20 text-foreground-neutral-muted [&_p]:leading-relaxed',
76
+ className,
77
+ )}
78
+ {...props}
79
+ />
80
+ );
81
+ }
82
+
83
+ function InlineTipsActions({className, ...props}: ComponentProps<'div'>) {
84
+ return (
85
+ <div
86
+ data-slot="inline-tips-actions"
87
+ className={cn('flex items-center gap-8 shrink-0', className)}
88
+ {...props}
89
+ />
90
+ );
91
+ }
92
+
93
+ const inlineTipsActionVariants = cva(
94
+ 'rounded-6 px-10 py-6 text-xs font-medium leading-20 transition-colors duration-150 outline-none focus-visible:ring-2 focus-visible:ring-background-accent-blue-base focus-visible:ring-offset-2',
95
+ {
96
+ variants: {
97
+ variant: {
98
+ primary:
99
+ 'bg-background-button-inverted-default text-foreground-contrast-primary 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 ',
100
+ secondary:
101
+ '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',
102
+ },
103
+ },
104
+ defaultVariants: {
105
+ variant: 'primary',
106
+ },
107
+ },
108
+ );
109
+
110
+ function InlineTipsAction({
111
+ className,
112
+ variant,
113
+ ...props
114
+ }: ComponentProps<'button'> & VariantProps<typeof inlineTipsActionVariants>) {
115
+ return (
116
+ <button
117
+ data-slot="inline-tips-action"
118
+ type="button"
119
+ className={cn(inlineTipsActionVariants({variant}), className)}
120
+ {...props}
121
+ />
122
+ );
123
+ }
124
+
125
+ export {
126
+ InlineTips,
127
+ InlineTipsContent,
128
+ InlineTipsTitle,
129
+ InlineTipsDescription,
130
+ InlineTipsActions,
131
+ InlineTipsAction,
132
+ };
@@ -0,0 +1 @@
1
+ export * from './textarea';