@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.
- package/.turbo/turbo-build.log +2 -2
- package/.turbo/turbo-check.log +3 -3
- package/.turbo/turbo-type.log +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/components/alert/alert.d.ts +18 -0
- package/dist/components/alert/alert.d.ts.map +1 -0
- package/dist/components/alert/alert.js +123 -0
- package/dist/components/alert/alert.js.map +1 -0
- package/dist/components/alert/alert.stories.js +112 -0
- package/dist/components/alert/alert.stories.js.map +1 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.d.ts.map +1 -0
- package/dist/components/alert/index.js +3 -0
- package/dist/components/alert/index.js.map +1 -0
- package/dist/components/avatar/avatar-group.d.ts +18 -0
- package/dist/components/avatar/avatar-group.d.ts.map +1 -0
- package/dist/components/avatar/avatar-group.js +132 -0
- package/dist/components/avatar/avatar-group.js.map +1 -0
- package/dist/components/avatar/avatar.d.ts +21 -0
- package/dist/components/avatar/avatar.d.ts.map +1 -0
- package/dist/components/avatar/avatar.js +166 -0
- package/dist/components/avatar/avatar.js.map +1 -0
- package/dist/components/avatar/avatar.stories.js +255 -0
- package/dist/components/avatar/avatar.stories.js.map +1 -0
- package/dist/components/avatar/index.d.ts +3 -0
- package/dist/components/avatar/index.d.ts.map +1 -0
- package/dist/components/avatar/index.js +4 -0
- package/dist/components/avatar/index.js.map +1 -0
- package/dist/components/icon/custom/index.d.ts +1 -0
- package/dist/components/icon/custom/index.d.ts.map +1 -1
- package/dist/components/icon/custom/index.js +1 -0
- package/dist/components/icon/custom/index.js.map +1 -1
- package/dist/components/icon/custom/shipfox-logo.d.ts +8 -0
- package/dist/components/icon/custom/shipfox-logo.d.ts.map +1 -0
- package/dist/components/icon/custom/shipfox-logo.js +22 -0
- package/dist/components/icon/custom/shipfox-logo.js.map +1 -0
- package/dist/components/icon/icon.d.ts +4 -1
- package/dist/components/icon/icon.d.ts.map +1 -1
- package/dist/components/icon/icon.js +6 -3
- package/dist/components/icon/icon.js.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/inline-tips/index.d.ts +2 -0
- package/dist/components/inline-tips/index.d.ts.map +1 -0
- package/dist/components/inline-tips/index.js +3 -0
- package/dist/components/inline-tips/index.js.map +1 -0
- package/dist/components/inline-tips/inline-tips.d.ts +19 -0
- package/dist/components/inline-tips/inline-tips.d.ts.map +1 -0
- package/dist/components/inline-tips/inline-tips.js +98 -0
- package/dist/components/inline-tips/inline-tips.js.map +1 -0
- package/dist/components/inline-tips/inline-tips.stories.js +214 -0
- package/dist/components/inline-tips/inline-tips.stories.js.map +1 -0
- package/dist/components/textarea/index.d.ts +2 -0
- package/dist/components/textarea/index.d.ts.map +1 -0
- package/dist/components/textarea/index.js +3 -0
- package/dist/components/textarea/index.js.map +1 -0
- package/dist/components/textarea/textarea.d.ts +10 -0
- package/dist/components/textarea/textarea.d.ts.map +1 -0
- package/dist/components/textarea/textarea.js +31 -0
- package/dist/components/textarea/textarea.js.map +1 -0
- package/dist/components/textarea/textarea.stories.js +333 -0
- package/dist/components/textarea/textarea.stories.js.map +1 -0
- package/dist/components/tooltip/tooltip.d.ts +7 -0
- package/dist/components/tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip/tooltip.js +38 -0
- package/dist/components/tooltip/tooltip.js.map +1 -0
- package/dist/utils/avatar.d.ts +3 -0
- package/dist/utils/avatar.d.ts.map +1 -0
- package/dist/utils/avatar.js +32 -0
- package/dist/utils/avatar.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/index.css +32 -1
- package/package.json +5 -5
- package/src/components/alert/alert.stories.tsx +77 -0
- package/src/components/alert/alert.tsx +144 -0
- package/src/components/alert/index.ts +1 -0
- package/src/components/avatar/avatar-group.tsx +186 -0
- package/src/components/avatar/avatar.stories.tsx +172 -0
- package/src/components/avatar/avatar.tsx +215 -0
- package/src/components/avatar/index.ts +2 -0
- package/src/components/icon/custom/index.ts +1 -0
- package/src/components/icon/custom/shipfox-logo.tsx +20 -0
- package/src/components/icon/icon.tsx +11 -1
- package/src/components/index.ts +4 -0
- package/src/components/inline-tips/index.ts +1 -0
- package/src/components/inline-tips/inline-tips.stories.tsx +126 -0
- package/src/components/inline-tips/inline-tips.tsx +132 -0
- package/src/components/textarea/index.ts +1 -0
- package/src/components/textarea/textarea.stories.tsx +190 -0
- package/src/components/textarea/textarea.tsx +42 -0
- package/src/components/tooltip/tooltip.tsx +52 -0
- package/src/utils/avatar.ts +27 -0
- 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};
|
|
@@ -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 {
|
|
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;
|
package/src/components/index.ts
CHANGED
|
@@ -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';
|