@beydesign/storybook 0.4.11 → 0.5.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/dist/App.js +1 -1
- package/dist/stories/Buttons/MainButton.js +2 -2
- package/dist/stories/Buttons/types.d.ts +4 -0
- package/dist/stories/EntityCard/EntityCard.js +36 -13
- package/dist/stories/EntityCard/EntityCard.stories.js +8 -37
- package/dist/stories/EntityCard/types.d.ts +6 -12
- package/dist/stories/UI/ButtonCard.js +2 -2
- package/dist/stories/UI/types.d.ts +2 -0
- package/package.json +1 -1
package/dist/App.js
CHANGED
|
@@ -148,7 +148,7 @@ function App() {
|
|
|
148
148
|
gap: '16px',
|
|
149
149
|
}, children: avatars
|
|
150
150
|
.slice(0, 4)
|
|
151
|
-
.map((avatar) => loading ? (_jsx(EntityCardSkeleton, { view: "agent" }, `agent-${avatar.id}`)) : (_jsx(EntityCard, { view: "agent", name: `${avatar.name} Customer Support`, image: avatar.image,
|
|
151
|
+
.map((avatar) => loading ? (_jsx(EntityCardSkeleton, { view: "agent" }, `agent-${avatar.id}`)) : (_jsx(EntityCard, { view: "agent", name: `${avatar.name} Customer Support`, image: avatar.image, stockAgent: true, onPreview: () => console.log('Join', avatar.name), previewButtonText: "Join", previewIcon: "VideoCamera", showMenu: true, menuItems: agentMenuItems }, `agent-${avatar.id}`))) }), _jsx("h2", { style: {
|
|
152
152
|
fontFamily: 'Figtree, sans-serif',
|
|
153
153
|
color: 'var(--color-text-text-title)',
|
|
154
154
|
margin: '40px 0 4px',
|
|
@@ -248,7 +248,7 @@ const StyledButton = styled.button `
|
|
|
248
248
|
var(--global-shadows-shadow-xs-color);
|
|
249
249
|
}
|
|
250
250
|
`;
|
|
251
|
-
export const MainButton = ({ onClick, text, disabled = false, loading = false, type = ButtonType.Button, style, size = ButtonSize.xl, hierarchy = ButtonHierarchy.Primary, displayIcon, iconWeight = 'regular', displayIconMode = ButtonDisplayMode.Default, state = ButtonState.Default, shape = ButtonShape.Square, destructive = false, showLeadingIcon = false, showTrailingIcon = false, leadingIcon = 'Circle', trailingIcon = 'Circle', trailingIconSlot, testId, }) => {
|
|
251
|
+
export const MainButton = ({ onClick, text, disabled = false, loading = false, type = ButtonType.Button, style, size = ButtonSize.xl, hierarchy = ButtonHierarchy.Primary, displayIcon, iconWeight = 'regular', displayIconMode = ButtonDisplayMode.Default, state = ButtonState.Default, shape = ButtonShape.Square, destructive = false, showLeadingIcon = false, showTrailingIcon = false, leadingIcon = 'Circle', trailingIcon = 'Circle', trailingIconSlot, id, className, testId, }) => {
|
|
252
252
|
// Figma draws a 20px icon at every button size.
|
|
253
253
|
const iconSize = 20;
|
|
254
254
|
// Vertical padding comes from TEXT_BUTTON_HEIGHT; only the horizontal value
|
|
@@ -332,5 +332,5 @@ export const MainButton = ({ onClick, text, disabled = false, loading = false, t
|
|
|
332
332
|
(trailingIconSlot ??
|
|
333
333
|
(trailingIcon && getIconComponent(trailingIcon, iconProps)))] }));
|
|
334
334
|
};
|
|
335
|
-
return (_jsx(StyledButton, { onClick: onClick, type: type, disabled: state === ButtonState.Disabled || disabled, "$size": size, "$hierarchy": hierarchy, "$state": state, "$shape": shape, "$destructive": destructive, "$disabled": disabled, "$displayIconMode": displayIconMode, "$sizeStyles": sizeStyles, style: style, "data-testid": testId, children: renderContent() }));
|
|
335
|
+
return (_jsx(StyledButton, { onClick: onClick, type: type, disabled: state === ButtonState.Disabled || disabled, "$size": size, "$hierarchy": hierarchy, "$state": state, "$shape": shape, "$destructive": destructive, "$disabled": disabled, "$displayIconMode": displayIconMode, "$sizeStyles": sizeStyles, style: style, id: id, className: className, "data-testid": testId, children: renderContent() }));
|
|
336
336
|
};
|
|
@@ -112,6 +112,10 @@ export interface MainButtonProps {
|
|
|
112
112
|
* keeping the button's icon slot and spacing intact.
|
|
113
113
|
*/
|
|
114
114
|
trailingIconSlot?: React.ReactNode;
|
|
115
|
+
/** DOM id set on the rendered `<button>` — used by analytics click triggers */
|
|
116
|
+
id?: string;
|
|
117
|
+
/** Extra class names merged onto the rendered `<button>` */
|
|
118
|
+
className?: string;
|
|
115
119
|
/** Test Id */
|
|
116
120
|
testId?: string;
|
|
117
121
|
}
|
|
@@ -19,6 +19,24 @@ const ASPECT_RATIO_BY_VIEW = {
|
|
|
19
19
|
agent: '264 / 268',
|
|
20
20
|
video: '16 / 9',
|
|
21
21
|
};
|
|
22
|
+
/** Empty-state label per view variant, shown over the silhouette when there is no image. */
|
|
23
|
+
const EMPTY_TEXT_BY_VIEW = {
|
|
24
|
+
avatar: 'Avatar is not available',
|
|
25
|
+
agent: 'Agent is not available',
|
|
26
|
+
video: 'Video is not available',
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Height of the empty-state silhouette (avatar/agent views). The empty-state
|
|
30
|
+
* label sits on the silhouette's vertical midpoint, i.e. half of this up from
|
|
31
|
+
* the bottom of the media area.
|
|
32
|
+
*/
|
|
33
|
+
const SILHOUETTE_HEIGHT = 224;
|
|
34
|
+
/** Copy for the stock-agent badge — the card's only badge. */
|
|
35
|
+
const STOCK_AGENT_BADGE_TEXT = 'Stock Agent';
|
|
36
|
+
/** Label shown beneath the spinner while the entity is processing. */
|
|
37
|
+
const PROCESSING_TEXT = 'Processing...';
|
|
38
|
+
/** Accessible label for the error state, on the warning icon. */
|
|
39
|
+
const ERROR_TEXT = 'Something went wrong';
|
|
22
40
|
/** Hook the root's hover/focus rules use to reveal the action buttons. */
|
|
23
41
|
const ACTIONS_CLASS = 'EntityCard-actions';
|
|
24
42
|
const spin = keyframes `
|
|
@@ -27,11 +45,12 @@ const spin = keyframes `
|
|
|
27
45
|
`;
|
|
28
46
|
/** A continuously rotating refresh icon, matching the AgentCard processing spinner. */
|
|
29
47
|
const Spinner = () => (_jsx(Box, { display: 'flex', sx: { animation: `${spin} 1.5s linear infinite` }, children: _jsx(ArrowsClockwise, { size: 24, color: 'var(--color-text-text-white)' }) }));
|
|
30
|
-
export const EntityCard = ({ view = 'avatar', name, image, description = '', showDescription = false, date, aspectRatio, processing = false,
|
|
48
|
+
export const EntityCard = ({ view = 'avatar', name, image, description = '', showDescription = false, date, aspectRatio, processing = false, error = false, onPreview, previewButtonText, previewIcon = 'Play', previewButtonClassName, stockAgent = false, menuItems = [], showMenu = false, width, testId, }) => {
|
|
31
49
|
const [hovered, setHovered] = useState(false);
|
|
32
50
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
33
51
|
const [imageError, setImageError] = useState(false);
|
|
34
52
|
const isVideo = view === 'video';
|
|
53
|
+
const isAgent = view === 'agent';
|
|
35
54
|
const cardWidth = width ?? WIDTH_BY_VIEW[view];
|
|
36
55
|
const imageAspectRatio = aspectRatio ?? ASPECT_RATIO_BY_VIEW[view];
|
|
37
56
|
const entityKey = name?.toLowerCase()?.replace(/\s+/g, '-');
|
|
@@ -40,8 +59,9 @@ export const EntityCard = ({ view = 'avatar', name, image, description = '', sho
|
|
|
40
59
|
const canPreview = !!onPreview && !isProcessing && !error;
|
|
41
60
|
const showActions = canPreview || hasMenu;
|
|
42
61
|
const active = hovered || menuOpen;
|
|
43
|
-
const showBadge =
|
|
62
|
+
const showBadge = isAgent && stockAgent && !error;
|
|
44
63
|
const showImage = !!image && !imageError && !error;
|
|
64
|
+
const emptyText = EMPTY_TEXT_BY_VIEW[view];
|
|
45
65
|
const resolvedTestId = testId ?? `${entityKey}-${isVideo ? 'video' : 'entity'}-card`;
|
|
46
66
|
const handlePreviewButtonClick = (event) => {
|
|
47
67
|
event.stopPropagation();
|
|
@@ -63,21 +83,24 @@ export const EntityCard = ({ view = 'avatar', name, image, description = '', sho
|
|
|
63
83
|
opacity: 1,
|
|
64
84
|
pointerEvents: 'auto',
|
|
65
85
|
},
|
|
66
|
-
}, "data-testid": resolvedTestId, children: [_jsxs(Box, { position: 'relative', width: '100%', borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-sm)', overflow: 'hidden', sx: { aspectRatio: imageAspectRatio }, children: [error ? (_jsx(Box, { width: '100%', height: '100%', bgcolor: 'var(--color-background-bg-badge-accent-red)', display: 'flex', justifyContent: 'center', alignItems: 'center', role: 'img', "aria-label":
|
|
86
|
+
}, "data-testid": resolvedTestId, children: [_jsxs(Box, { position: 'relative', width: '100%', borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-sm)', overflow: 'hidden', sx: { aspectRatio: imageAspectRatio }, children: [error ? (_jsx(Box, { width: '100%', height: '100%', bgcolor: 'var(--color-background-bg-badge-accent-red)', display: 'flex', justifyContent: 'center', alignItems: 'center', role: 'img', "aria-label": ERROR_TEXT, title: ERROR_TEXT, children: _jsx(Warning, { size: 50, color: 'var(--color-foreground-fg-error)' }) })) : showImage ? (_jsx("img", { src: image, alt: name, width: '100%', height: '100%', style: { objectFit: 'cover', height: '100%', width: '100%' }, onError: () => setImageError(true) })) : (_jsxs(Box, { position: 'relative', width: '100%', height: '100%', overflow: 'hidden', bgcolor: view === 'agent'
|
|
67
87
|
? 'var(--color-background-bg-component-disabled)'
|
|
68
|
-
: 'var(--color-background-bg-button-disabled)', children: _jsx(Box, { position: 'absolute', bottom: 0, left: '50%', sx: {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
: 'var(--color-background-bg-button-disabled)', children: [_jsx(Box, { position: 'absolute', bottom: 0, left: '50%', sx: {
|
|
89
|
+
transform: 'translateX(-50%)',
|
|
90
|
+
color: 'var(--color-border-border-subtle)',
|
|
91
|
+
aspectRatio: '206 / 224',
|
|
92
|
+
...(isVideo
|
|
93
|
+
? { height: '100%', maxWidth: '100%' }
|
|
94
|
+
: { width: '206px', height: `${SILHOUETTE_HEIGHT}px` }),
|
|
95
|
+
}, children: _jsx(AvatarSilhouette, {}) }), !!emptyText && (_jsx(Box, { position: 'absolute', left: 0, right: 0, bottom: isVideo ? '50%' : `${SILHOUETTE_HEIGHT / 2}px`, display: 'flex', justifyContent: 'center', padding: '0 var(--spacing-tokens-size-in-px-spacing-spacing-lg)', boxSizing: 'border-box', children: _jsx(Typography, { text: emptyText, size: TypographySize.HeadingXS, weight: TypographyWeight.SemiBold, color: 'var(--color-text-text-subtle)', textStyle: {
|
|
96
|
+
textAlign: 'center',
|
|
97
|
+
wordBreak: 'break-word',
|
|
98
|
+
} }) }))] })), _jsx(Box, { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-sm)', sx: {
|
|
76
99
|
backgroundImage: 'linear-gradient(180deg, rgba(21, 0, 73, 0) 0%, rgba(72, 29, 180, 0.152) 16.76%, rgba(32, 13, 82, 0.36) 100%)',
|
|
77
100
|
opacity: active && !isProcessing && !error ? 1 : 0,
|
|
78
101
|
transition: 'opacity 0.15s ease-in-out',
|
|
79
102
|
pointerEvents: 'none',
|
|
80
|
-
} }), isProcessing && (_jsxs(Box, { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', bgcolor: 'var(--color-background-bg-overlay-2)', sx: { zIndex: 1 }, children: [_jsx(Spinner, {}), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.SemiBold, color: 'var(--color-text-text-white)', children:
|
|
103
|
+
} }), isProcessing && (_jsxs(Box, { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', bgcolor: 'var(--color-background-bg-overlay-2)', sx: { zIndex: 1 }, children: [_jsx(Spinner, {}), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.SemiBold, color: 'var(--color-text-text-white)', children: PROCESSING_TEXT })] })), showBadge && (_jsx(Box, { position: 'absolute', top: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', left: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', sx: { zIndex: 2 }, children: _jsx(Badge, { text: STOCK_AGENT_BADGE_TEXT, color: BadgeColor.Violet, size: BadgeSize.md, testId: `${entityKey}-stock-agent-badge` }) })), showActions && (_jsxs(Box, { className: ACTIONS_CLASS, position: 'absolute', top: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', right: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', sx: {
|
|
81
104
|
zIndex: 4,
|
|
82
105
|
transition: 'opacity 0.15s ease-in-out',
|
|
83
106
|
...(menuOpen
|
|
@@ -89,7 +112,7 @@ export const EntityCard = ({ view = 'avatar', name, image, description = '', sho
|
|
|
89
112
|
},
|
|
90
113
|
}),
|
|
91
114
|
}, children: [canPreview &&
|
|
92
|
-
(previewButtonText ? (_jsx(MainButton, { text: previewButtonText, showLeadingIcon: true, leadingIcon: previewIcon, iconWeight: 'fill', hierarchy: ButtonHierarchy.SecondaryTransparent, size: ButtonSize.xxs, onClick: handlePreviewButtonClick, testId: `${entityKey}-preview-button` })) : (_jsx(MainButton, { displayIcon: previewIcon, displayIconMode: ButtonDisplayMode.Only, hierarchy: ButtonHierarchy.SecondaryTransparent, size: ButtonSize.xxs, onClick: handlePreviewButtonClick, testId: `${entityKey}-preview-button` }))), hasMenu && (_jsx(Box, { onClick: (event) => event.stopPropagation(), children: _jsx(Menu, { items: menuItems, testKey: entityKey, size: ButtonSize.xxs, onOpenChange: setMenuOpen }) }))] })), isVideo ? (_jsxs(Box, { position: 'absolute', left: 0, right: 0, bottom: 0, display: 'flex', flexDirection: 'row', alignItems: 'flex-end', justifyContent: 'space-between', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-3xl) var(--spacing-tokens-size-in-px-spacing-spacing-lg) var(--spacing-tokens-size-in-px-spacing-spacing-lg)', sx: {
|
|
115
|
+
(previewButtonText ? (_jsx(MainButton, { text: previewButtonText, showLeadingIcon: true, leadingIcon: previewIcon, iconWeight: 'fill', hierarchy: ButtonHierarchy.SecondaryTransparent, size: ButtonSize.xxs, onClick: handlePreviewButtonClick, className: previewButtonClassName, testId: `${entityKey}-preview-button` })) : (_jsx(MainButton, { displayIcon: previewIcon, displayIconMode: ButtonDisplayMode.Only, hierarchy: ButtonHierarchy.SecondaryTransparent, size: ButtonSize.xxs, onClick: handlePreviewButtonClick, className: previewButtonClassName, testId: `${entityKey}-preview-button` }))), hasMenu && (_jsx(Box, { onClick: (event) => event.stopPropagation(), children: _jsx(Menu, { items: menuItems, testKey: entityKey, size: ButtonSize.xxs, onOpenChange: setMenuOpen }) }))] })), isVideo ? (_jsxs(Box, { position: 'absolute', left: 0, right: 0, bottom: 0, display: 'flex', flexDirection: 'row', alignItems: 'flex-end', justifyContent: 'space-between', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-3xl) var(--spacing-tokens-size-in-px-spacing-spacing-lg) var(--spacing-tokens-size-in-px-spacing-spacing-lg)', sx: {
|
|
93
116
|
zIndex: 2,
|
|
94
117
|
pointerEvents: 'none',
|
|
95
118
|
backgroundImage: 'linear-gradient(rgba(45, 38, 55, 0) 0%, rgba(45, 38, 55, 0.16) 34%, rgba(45, 38, 55, 0.64) 100%)',
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { EntityCard } from './EntityCard';
|
|
2
|
-
import { BadgeColor } from '../UI';
|
|
3
2
|
const meta = {
|
|
4
3
|
title: 'Design System/Components/EntityCard/EntityCard',
|
|
5
4
|
component: EntityCard,
|
|
@@ -59,27 +58,11 @@ const meta = {
|
|
|
59
58
|
description: 'Show the processing overlay (spinner + label)',
|
|
60
59
|
table: { type: { summary: 'boolean' } },
|
|
61
60
|
},
|
|
62
|
-
processingText: {
|
|
63
|
-
control: 'text',
|
|
64
|
-
description: 'Processing overlay label',
|
|
65
|
-
table: {
|
|
66
|
-
type: { summary: 'string' },
|
|
67
|
-
defaultValue: { summary: 'Please wait' },
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
61
|
error: {
|
|
71
62
|
control: 'boolean',
|
|
72
63
|
description: 'Show the error state (tinted media area + warning icon)',
|
|
73
64
|
table: { type: { summary: 'boolean' } },
|
|
74
65
|
},
|
|
75
|
-
errorText: {
|
|
76
|
-
control: 'text',
|
|
77
|
-
description: "Accessible label for the error state (the warning icon's aria-label/title)",
|
|
78
|
-
table: {
|
|
79
|
-
type: { summary: 'string' },
|
|
80
|
-
defaultValue: { summary: 'Something went wrong' },
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
66
|
showMenu: {
|
|
84
67
|
control: 'boolean',
|
|
85
68
|
description: 'Whether to show the menu on hover',
|
|
@@ -102,23 +85,12 @@ const meta = {
|
|
|
102
85
|
defaultValue: { summary: 'Play' },
|
|
103
86
|
},
|
|
104
87
|
},
|
|
105
|
-
|
|
88
|
+
stockAgent: {
|
|
106
89
|
control: 'boolean',
|
|
107
|
-
description: '
|
|
108
|
-
table: { type: { summary: 'boolean' } },
|
|
109
|
-
},
|
|
110
|
-
statusBadgeText: {
|
|
111
|
-
control: 'text',
|
|
112
|
-
description: 'Status badge text (e.g. "Active")',
|
|
113
|
-
table: { type: { summary: 'string' } },
|
|
114
|
-
},
|
|
115
|
-
statusBadgeColor: {
|
|
116
|
-
control: 'select',
|
|
117
|
-
options: Object.values(BadgeColor),
|
|
118
|
-
description: 'Status badge color',
|
|
90
|
+
description: 'Marks the entity as a stock agent — renders the "Stock Agent" badge (top-left). `agent` view only',
|
|
119
91
|
table: {
|
|
120
|
-
type: { summary: '
|
|
121
|
-
defaultValue: { summary:
|
|
92
|
+
type: { summary: 'boolean' },
|
|
93
|
+
defaultValue: { summary: 'false' },
|
|
122
94
|
},
|
|
123
95
|
},
|
|
124
96
|
menuItems: {
|
|
@@ -158,8 +130,7 @@ export const AgentView = {
|
|
|
158
130
|
onPreview: () => { },
|
|
159
131
|
previewButtonText: 'Join',
|
|
160
132
|
previewIcon: 'VideoCamera',
|
|
161
|
-
|
|
162
|
-
statusBadgeText: 'Active',
|
|
133
|
+
stockAgent: true,
|
|
163
134
|
showMenu: true,
|
|
164
135
|
menuItems: [
|
|
165
136
|
{ label: 'Conversation Link', icon: 'ShareNetwork', onClick: () => { } },
|
|
@@ -177,7 +148,7 @@ export const AgentView = {
|
|
|
177
148
|
},
|
|
178
149
|
docs: {
|
|
179
150
|
description: {
|
|
180
|
-
story: 'The agent view — wider, square image,
|
|
151
|
+
story: 'The agent view — wider, square image, the "Stock Agent" badge, and a labelled "Join" action. Hover to reveal the action row.',
|
|
181
152
|
},
|
|
182
153
|
},
|
|
183
154
|
},
|
|
@@ -213,13 +184,13 @@ export const NoActions = {
|
|
|
213
184
|
export const NoImage = {
|
|
214
185
|
args: {
|
|
215
186
|
...Default.args,
|
|
216
|
-
name: '
|
|
187
|
+
name: 'Nelly Customer Support',
|
|
217
188
|
image: undefined,
|
|
218
189
|
},
|
|
219
190
|
parameters: {
|
|
220
191
|
docs: {
|
|
221
192
|
description: {
|
|
222
|
-
story: 'Fallback placeholder shown when no image is provided or it fails to load.',
|
|
193
|
+
story: 'Fallback placeholder shown when no image is provided or it fails to load — the avatar silhouette plus an "Avatar is not available" label sitting on the silhouette\'s midpoint. The `video` view reads "Video is not available".',
|
|
223
194
|
},
|
|
224
195
|
},
|
|
225
196
|
},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { MenuItemProps
|
|
1
|
+
import { MenuItemProps } from '../UI';
|
|
2
2
|
import { IconName } from '../../utils';
|
|
3
3
|
/**
|
|
4
4
|
* Entity card view variants.
|
|
5
5
|
* - `avatar`: portrait avatar tile (icon-only preview action)
|
|
6
|
-
* - `agent`: wider, square agent tile (labelled action +
|
|
6
|
+
* - `agent`: wider, square agent tile (labelled action + stock-agent badge)
|
|
7
7
|
* - `video`: landscape media tile (name + date footer, optional processing overlay)
|
|
8
8
|
*/
|
|
9
9
|
export type EntityCardView = 'avatar' | 'agent' | 'video';
|
|
@@ -27,24 +27,18 @@ export interface EntityCardProps {
|
|
|
27
27
|
aspectRatio?: string;
|
|
28
28
|
/** Show the processing overlay (spinner + label) over the image */
|
|
29
29
|
processing?: boolean;
|
|
30
|
-
/** Processing overlay label. Defaults to "Please wait" */
|
|
31
|
-
processingText?: string;
|
|
32
30
|
/** Show the error state (tinted media area + warning icon) in place of the image */
|
|
33
31
|
error?: boolean;
|
|
34
|
-
/** Accessible label for the error state — exposed as the warning icon's aria-label/title. Defaults to "Something went wrong" */
|
|
35
|
-
errorText?: string;
|
|
36
32
|
/** Preview handler — renders the action button on hover */
|
|
37
33
|
onPreview?: () => void;
|
|
38
34
|
/** Label for the action button; when set it renders text + icon, otherwise icon-only */
|
|
39
35
|
previewButtonText?: string;
|
|
40
36
|
/** Icon for the action button (defaults to `Play`) */
|
|
41
37
|
previewIcon?: IconName;
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
/** Status badge color (defaults to Green) */
|
|
47
|
-
statusBadgeColor?: BadgeColor;
|
|
38
|
+
/** Extra class names merged onto the action button — used by analytics click triggers */
|
|
39
|
+
previewButtonClassName?: string;
|
|
40
|
+
/** Marks the entity as a stock agent — renders the "Stock Agent" badge (top-left). `agent` view only */
|
|
41
|
+
stockAgent?: boolean;
|
|
48
42
|
/** Menu items for the dropdown — renders the menu button on hover */
|
|
49
43
|
menuItems?: MenuItemProps[];
|
|
50
44
|
/** Whether to show the menu */
|
|
@@ -8,13 +8,13 @@ import { getIconComponent } from '../../utils';
|
|
|
8
8
|
* a short description and an optional corner action button. Matches the Figma
|
|
9
9
|
* "Button card" component with its default and hover states.
|
|
10
10
|
*/
|
|
11
|
-
export const ButtonCard = ({ title, description, icon = 'UserFocus', iconColor = 'var(--color-foreground-fg-accent-yellow)', iconBackgroundColor = 'var(--color-background-bg-badge-accent-yellow)', onClick, showActionButton = false, actionButtonText = 'Contact Us', onActionClick, disabled = false, width = '294px', style, testId, }) => {
|
|
11
|
+
export const ButtonCard = ({ title, description, icon = 'UserFocus', iconColor = 'var(--color-foreground-fg-accent-yellow)', iconBackgroundColor = 'var(--color-background-bg-badge-accent-yellow)', onClick, showActionButton = false, actionButtonText = 'Contact Us', onActionClick, disabled = false, width = '294px', style, id, testId, }) => {
|
|
12
12
|
const cardKey = title?.toLowerCase()?.replace(/\s+/g, '-');
|
|
13
13
|
const isInteractive = !disabled && !!onClick;
|
|
14
14
|
return (_jsxs(Box, { width: width, display: 'flex', alignItems: 'flex-start', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', paddingX: 'var(--spacing-tokens-size-in-px-spacing-spacing-xl)', paddingTop: {
|
|
15
15
|
xs: 'var(--spacing-tokens-size-in-px-spacing-spacing-2xl)',
|
|
16
16
|
sm: 'var(--spacing-tokens-size-in-px-spacing-spacing-3xl)',
|
|
17
|
-
}, paddingBottom: 'var(--spacing-tokens-size-in-px-spacing-spacing-xl)', borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', bgcolor: 'var(--color-background-bg-component)', boxSizing: 'border-box', position: 'relative', onClick: isInteractive ? onClick : undefined, style: style, "data-testid": testId ?? `${cardKey}-button-card`, sx: {
|
|
17
|
+
}, paddingBottom: 'var(--spacing-tokens-size-in-px-spacing-spacing-xl)', borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', bgcolor: 'var(--color-background-bg-component)', boxSizing: 'border-box', position: 'relative', onClick: isInteractive ? onClick : undefined, style: style, id: id, "data-testid": testId ?? `${cardKey}-button-card`, sx: {
|
|
18
18
|
opacity: disabled ? 0.5 : 1,
|
|
19
19
|
cursor: isInteractive ? 'pointer' : 'default',
|
|
20
20
|
pointerEvents: disabled ? 'none' : 'auto',
|