@beydesign/storybook 0.6.1 → 0.7.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.
@@ -44,7 +44,13 @@ const fileIconMap = {
44
44
  };
45
45
  // Default icon for unknown file types
46
46
  const defaultIcon = FileCode;
47
- export const FileUpload = ({ disabled, sx, acceptedFileTypes = '.pdf,.doc,.docx,.txt', maxFileSizeMB = 10, onFileSelect, }) => {
47
+ /**
48
+ * Figma draws the upload glyph in a 28px frame with the stroke inside it.
49
+ * Deriving the box from padding puts the CSS border outside, leaving it 2px
50
+ * oversized, so pin the frame and let border-box absorb the stroke.
51
+ */
52
+ const ICON_BOX_SIZE = 28;
53
+ export const FileUpload = ({ disabled, sx, acceptedFileTypes = '.pdf,.doc,.docx,.txt', maxFileSizeMB = 10, onFileSelect, hintText, showFileTypeIcons = true, }) => {
48
54
  const [isDragging, setIsDragging] = useState(false);
49
55
  const fileInputRef = useRef(null);
50
56
  // Function to get the icons to display based on acceptedFileTypes
@@ -124,7 +130,7 @@ export const FileUpload = ({ disabled, sx, acceptedFileTypes = '.pdf,.doc,.docx,
124
130
  ? 'var(--color-background-bg-component-disabled)'
125
131
  : isDragging
126
132
  ? 'var(--color-background-bg-component-hover)'
127
- : 'var(--color-background-bg-element)', sx: { cursor: disabled ? 'not-allowed' : 'pointer', ...sx }, onClick: handleClick, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [_jsx("input", { type: "file", ref: fileInputRef, style: { display: 'none' }, accept: acceptedFileTypes, onChange: handleInputChange, disabled: disabled }), _jsx(Box, { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', border: `1px solid ${disabled
133
+ : 'var(--color-background-bg-element)', sx: { cursor: disabled ? 'not-allowed' : 'pointer', ...sx }, onClick: handleClick, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [_jsx("input", { type: "file", ref: fileInputRef, style: { display: 'none' }, accept: acceptedFileTypes, onChange: handleInputChange, disabled: disabled }), _jsx(Box, { display: 'flex', alignItems: 'center', justifyContent: 'center', width: ICON_BOX_SIZE, height: ICON_BOX_SIZE, boxSizing: 'border-box', border: `1px solid ${disabled
128
134
  ? 'var(--color-border-border-disabled)'
129
135
  : 'var(--color-border-border-component)'}`, borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-sm)', bgcolor: disabled
130
136
  ? 'var(--color-background-bg-button-disabled)'
@@ -134,5 +140,7 @@ export const FileUpload = ({ disabled, sx, acceptedFileTypes = '.pdf,.doc,.docx,
134
140
  ? 'var(--color-text-text-inactive)'
135
141
  : 'var(--color-text-text-clicable)', textStyle: { cursor: disabled ? 'not-allowed' : 'pointer' }, children: "Click to upload" }), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: disabled
136
142
  ? 'var(--color-text-text-disabled)'
137
- : 'var(--color-text-text-paragraph)', children: "or drag and drop" }), _jsxs(Box, { display: 'flex', flexDirection: 'row', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', children: [fileIcons.map((Icon, index) => (_jsx(Icon, { ...iconProps }, index))), fileIcons.length === 0 && _jsx(FileCode, { ...iconProps })] })] })] }));
143
+ : 'var(--color-text-text-paragraph)', children: "or drag and drop" }), showFileTypeIcons && (_jsxs(Box, { display: 'flex', flexDirection: 'row', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', children: [fileIcons.map((Icon, index) => (_jsx(Icon, { ...iconProps }, index))), fileIcons.length === 0 && _jsx(FileCode, { ...iconProps })] }))] }), hintText && (_jsx(Typography, { size: TypographySize.TextXS, weight: TypographyWeight.Regular, color: disabled
144
+ ? 'var(--color-text-text-disabled)'
145
+ : 'var(--color-text-text-paragraph)', children: hintText }))] }));
138
146
  };
@@ -5,3 +5,4 @@ export default meta;
5
5
  type Story = StoryObj<typeof FileUpload>;
6
6
  export declare const Default: Story;
7
7
  export declare const Disabled: Story;
8
+ export declare const WithHintText: Story;
@@ -31,6 +31,19 @@ const meta = {
31
31
  description: 'Callback function when a file is selected',
32
32
  table: { type: { summary: 'function' } },
33
33
  },
34
+ hintText: {
35
+ control: 'text',
36
+ description: 'Supporting line rendered under the label',
37
+ table: { type: { summary: 'string' } },
38
+ },
39
+ showFileTypeIcons: {
40
+ control: 'boolean',
41
+ description: 'Whether to render the per-extension file icons',
42
+ table: {
43
+ type: { summary: 'boolean' },
44
+ defaultValue: { summary: 'true' },
45
+ },
46
+ },
34
47
  sx: {
35
48
  control: 'object',
36
49
  description: 'Style of the file upload',
@@ -49,3 +62,12 @@ export const Disabled = {
49
62
  disabled: true,
50
63
  },
51
64
  };
65
+ export const WithHintText = {
66
+ args: {
67
+ acceptedFileTypes: '.mp4,.mov',
68
+ maxFileSizeMB: 500,
69
+ hintText: 'MP4 or MOV, up to 500MB',
70
+ showFileTypeIcons: false,
71
+ sx: { width: '537px', aspectRatio: '537 / 293' },
72
+ },
73
+ };
@@ -150,6 +150,16 @@ export interface FileUploadProps {
150
150
  maxFileSizeMB?: number;
151
151
  /** Callback function when a file is selected */
152
152
  onFileSelect?: (file: File) => void;
153
+ /**
154
+ * Supporting line rendered under the label, e.g. "MP4 or MOV, up to 500MB".
155
+ * Figma centres it inside the drop area as part of the label cluster.
156
+ */
157
+ hintText?: string;
158
+ /**
159
+ * Whether to render the per-extension file icons beside the label.
160
+ * Defaults to true; turn it off when `hintText` states the formats instead.
161
+ */
162
+ showFileTypeIcons?: boolean;
153
163
  /** Style of the file upload */
154
164
  sx?: SxProps<Theme>;
155
165
  }
@@ -6,5 +6,4 @@ export * from './MobileNavBar';
6
6
  export * from './NavItem';
7
7
  export * from './Sidebar';
8
8
  export * from './types';
9
- export * from './ProcessHeader';
10
9
  export * from './ComplexHeader';
@@ -6,5 +6,4 @@ export * from './MobileNavBar';
6
6
  export * from './NavItem';
7
7
  export * from './Sidebar';
8
8
  export * from './types';
9
- export * from './ProcessHeader';
10
9
  export * from './ComplexHeader';
@@ -168,24 +168,6 @@ export interface SidebarProps {
168
168
  color?: string;
169
169
  };
170
170
  }
171
- export interface ProcessHeaderProps {
172
- /** The title of the process */
173
- title: string;
174
- /** The subtitle of the process */
175
- subtitle: string;
176
- /** The current step of the process */
177
- currentStep: number;
178
- /** The total steps of the process */
179
- totalSteps: number;
180
- /** The text to display in the header right */
181
- headerRightText?: string;
182
- /** The callback to handle the cancel button click */
183
- onCancelClick?: () => void;
184
- /** The style object to apply to the component */
185
- sx?: SxProps<Theme>;
186
- /** The class name to apply to the component */
187
- className?: string;
188
- }
189
171
  /**
190
172
  * Props for the {@link MobileNav} overlay — the single navigation panel used
191
173
  * below the mobile breakpoint, which holds the `Drawer` and any `subNav` as
@@ -3,6 +3,18 @@ import { BadgeColor, BadgeSize } from './types';
3
3
  import { Box } from '@mui/material';
4
4
  import { Typography, TypographySize, TypographyWeight } from '../Typography';
5
5
  import { getIconComponent } from '../../utils';
6
+ /**
7
+ * Figma sizes a badge by its height, with the label centred inside and the
8
+ * 1px stroke drawn within that box. A CSS border sits outside instead, so
9
+ * deriving the height from vertical padding leaves every badge 2px taller
10
+ * than the design. Pin the height and let border-box absorb the stroke —
11
+ * the same fix MainButton applies to text buttons.
12
+ */
13
+ const BADGE_HEIGHT = {
14
+ [BadgeSize.lg]: 32,
15
+ [BadgeSize.md]: 28,
16
+ [BadgeSize.xs]: 24,
17
+ };
6
18
  export const Badge = ({ color = BadgeColor.Default, size = BadgeSize.md, text, children, style: customStyle, icon = 'Cactus', showIcon = false, fill = true, iconWeight = 'regular', iconSize, iconColor, testId, }) => {
7
19
  const getBackgroundColor = (color) => {
8
20
  switch (color) {
@@ -82,14 +94,14 @@ export const Badge = ({ color = BadgeColor.Default, size = BadgeSize.md, text, c
82
94
  return '1px solid rgba(0, 0, 0, 0.3)';
83
95
  }
84
96
  };
85
- const getPadding = (size) => {
97
+ const getPaddingX = (size) => {
86
98
  switch (size) {
87
99
  case BadgeSize.lg:
88
- return 'var(--spacing-tokens-size-in-px-spacing-spacing-sm) var(--spacing-tokens-size-in-px-spacing-spacing-lg)';
100
+ return 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)';
89
101
  case BadgeSize.md:
90
- return 'var(--spacing-tokens-size-in-px-spacing-spacing-xs) 10px';
102
+ return '10px';
91
103
  case BadgeSize.xs:
92
- return 'var(--spacing-tokens-size-in-px-spacing-spacing-xs) var(--spacing-tokens-size-in-px-spacing-spacing-md)';
104
+ return 'var(--spacing-tokens-size-in-px-spacing-spacing-md)';
93
105
  }
94
106
  };
95
107
  const getIconSize = (size) => {
@@ -114,11 +126,14 @@ export const Badge = ({ color = BadgeColor.Default, size = BadgeSize.md, text, c
114
126
  };
115
127
  const backgroundColor = getBackgroundColor(color);
116
128
  const border = getBorder(color);
117
- const padding = getPadding(size);
129
+ // Figma measures padding from the frame edge with the stroke drawn inside
130
+ // it, so subtract the border to keep the label the same distance in.
131
+ const figmaPaddingX = getPaddingX(size);
132
+ const paddingX = fill ? `calc(${figmaPaddingX} - 1px)` : figmaPaddingX;
118
133
  const iconProps = {
119
134
  size: iconSize || getIconSize(size),
120
135
  color: iconColor || getTextColor(),
121
136
  weight: iconWeight,
122
137
  };
123
- return (_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "center", bgcolor: fill ? backgroundColor : 'transparent', border: fill ? border : 'none', borderRadius: fill ? 'var(--spacing-tokens-size-in-px-radius-radius-full)' : 'none', padding: padding, margin: 0, gap: "4px", sx: customStyle, "data-testid": testId, children: [showIcon && icon && getIconComponent(icon, iconProps), text && (_jsx(Typography, { size: getTypographySize(size), weight: TypographyWeight.Medium, color: getTextColor(), children: text })), children] }));
138
+ return (_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "center", bgcolor: fill ? backgroundColor : 'transparent', border: fill ? border : 'none', borderRadius: fill ? 'var(--spacing-tokens-size-in-px-radius-radius-full)' : 'none', height: BADGE_HEIGHT[size], boxSizing: "border-box", paddingX: paddingX, margin: 0, gap: "4px", sx: customStyle, "data-testid": testId, children: [showIcon && icon && getIconComponent(icon, iconProps), text && (_jsx(Typography, { size: getTypographySize(size), weight: TypographyWeight.Medium, color: getTextColor(), children: text })), children] }));
124
139
  };
@@ -28,6 +28,7 @@ const FRAME_MAP = {
28
28
  [CheckIconSize.sm]: 20,
29
29
  [CheckIconSize.md]: 24,
30
30
  [CheckIconSize.lg]: 28,
31
+ [CheckIconSize.xl]: 32,
31
32
  };
32
33
  /**
33
34
  * Figma draws the glyph on a grid of 32 units per frame, with the ink inset
@@ -237,7 +237,8 @@ export declare enum CheckIconSize {
237
237
  xs = "xs",
238
238
  sm = "sm",
239
239
  md = "md",
240
- lg = "lg"
240
+ lg = "lg",
241
+ xl = "xl"
241
242
  }
242
243
  /**
243
244
  * Check icon type variants.
@@ -90,6 +90,7 @@ export var CheckIconSize;
90
90
  CheckIconSize["sm"] = "sm";
91
91
  CheckIconSize["md"] = "md";
92
92
  CheckIconSize["lg"] = "lg";
93
+ CheckIconSize["xl"] = "xl";
93
94
  })(CheckIconSize || (CheckIconSize = {}));
94
95
  /**
95
96
  * Check icon type variants.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@beydesign/storybook",
3
3
  "private": false,
4
- "version": "0.6.1",
4
+ "version": "0.7.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- import { ProcessHeaderProps } from './types';
3
- export declare const ProcessHeader: React.FC<ProcessHeaderProps>;
@@ -1,11 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box } from '@mui/material';
3
- import { Badge, BadgeColor, BadgeSize } from '../UI';
4
- import { Typography, TypographySize, TypographyWeight } from '../Typography';
5
- import { ButtonHierarchy, ButtonSize, MainButton } from '../Buttons';
6
- export const ProcessHeader = ({ title, currentStep, subtitle, totalSteps, headerRightText, onCancelClick, sx, className, }) => {
7
- const stepChecks = () => {
8
- return (currentStep && totalSteps && currentStep >= 1 && currentStep <= totalSteps);
9
- };
10
- return (_jsxs(Box, { display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingX: 'var(--spacing-tokens-size-in-px-spacing-spacing-3xl)', paddingY: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', sx: sx, className: className, children: [_jsxs(Box, { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)', children: [_jsxs(Box, { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)', children: [headerRightText && (_jsx(Badge, { text: headerRightText, size: BadgeSize.lg, color: BadgeColor.Green })), stepChecks() && (_jsx(Badge, { text: `Step ${currentStep} of ${totalSteps}`, size: BadgeSize.lg, color: BadgeColor.Violet }))] }), _jsxs(Box, { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', children: [title && (_jsx(Typography, { size: TypographySize.TextM, weight: TypographyWeight.SemiBold, children: `${title}.` })), subtitle && (_jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, children: subtitle }))] })] }), onCancelClick && (_jsx(MainButton, { text: 'Cancel Process', onClick: onCancelClick, size: ButtonSize.md, hierarchy: ButtonHierarchy.TertiaryColor, trailingIcon: 'X', showTrailingIcon: true }))] }));
11
- };
@@ -1,6 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
2
- import { ProcessHeader } from './ProcessHeader';
3
- declare const meta: Meta<typeof ProcessHeader>;
4
- export default meta;
5
- type Story = StoryObj<typeof ProcessHeader>;
6
- export declare const Default: Story;
@@ -1,76 +0,0 @@
1
- import { ProcessHeader } from './ProcessHeader';
2
- import styles from './Header.module.css';
3
- const meta = {
4
- title: 'Design System/Components/Navigation/ProcessHeader',
5
- component: ProcessHeader,
6
- parameters: {
7
- layout: 'centered',
8
- design: {
9
- type: 'figspec',
10
- url: 'https://www.figma.com/design/Ze4bBHgBQYinBDZr1COHuk/Agents?node-id=1928-68769&t=ff7acatvxaY98hGj-1',
11
- },
12
- },
13
- tags: ['autodocs'],
14
- argTypes: {
15
- title: {
16
- control: 'text',
17
- description: 'Title of the header',
18
- table: {
19
- type: { summary: 'string' },
20
- },
21
- },
22
- subtitle: {
23
- control: 'text',
24
- description: 'Subtitle of the header',
25
- table: {
26
- type: { summary: 'string' },
27
- },
28
- },
29
- currentStep: {
30
- control: 'number',
31
- description: 'Current step of the process',
32
- table: {
33
- type: { summary: 'number' },
34
- },
35
- },
36
- totalSteps: {
37
- control: 'number',
38
- description: 'Total steps of the process',
39
- table: {
40
- type: { summary: 'number' },
41
- },
42
- },
43
- headerRightText: {
44
- control: 'text',
45
- description: 'Text to display in the header right',
46
- table: {
47
- type: { summary: 'string' },
48
- },
49
- },
50
- onCancelClick: {
51
- description: 'Callback to handle the cancel button click',
52
- table: {
53
- type: { summary: 'function' },
54
- },
55
- },
56
- sx: {
57
- control: 'object',
58
- description: 'Style object to apply to the component',
59
- table: {
60
- type: { summary: 'object' },
61
- },
62
- },
63
- },
64
- };
65
- export default meta;
66
- export const Default = {
67
- args: {
68
- title: 'Train Agent',
69
- subtitle: 'Please fill in the necessary information for your agent & upload knowledge files.',
70
- currentStep: 3,
71
- totalSteps: 3,
72
- headerRightText: 'New Agent',
73
- onCancelClick: () => { },
74
- className: styles['responsive-width'],
75
- },
76
- };