@beydesign/storybook 0.2.23 → 0.2.24

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.
@@ -4,6 +4,7 @@ import styled from '@emotion/styled';
4
4
  import { DrawerSize, DrawerNavItemState, DrawerNavItemHierarchy, } from './types';
5
5
  import { DrawerNavItem } from './DrawerNavItem';
6
6
  import { DrawerCreditsCard } from './DrawerCreditsCard';
7
+ import { DrawerCreditsCardSkeleton } from './DrawerCreditsCardSkeleton';
7
8
  import { DrawerProfile } from './DrawerProfile';
8
9
  import { Logo, LogoVariant } from '../UI';
9
10
  import { getIconComponent } from '../../utils';
@@ -136,7 +137,7 @@ const resolveState = (item, activeKey) => {
136
137
  * uncontrolled (`defaultCollapsed`). Every colour, space and radius resolves to
137
138
  * `@beydesign/tokens` CSS variables, so it renders correctly in light and dark.
138
139
  */
139
- export const Drawer = ({ navItems, activeKey, collapsed, defaultCollapsed = false, onToggle, showToggle = true, credits, profile, logo, className, style, testId, }) => {
140
+ export const Drawer = ({ navItems, activeKey, collapsed, defaultCollapsed = false, onToggle, showToggle = true, credits, creditsLoading = false, profile, logo, className, style, testId, }) => {
140
141
  const isControlled = collapsed !== undefined;
141
142
  const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);
142
143
  const isCollapsed = isControlled ? collapsed : internalCollapsed;
@@ -157,5 +158,5 @@ export const Drawer = ({ navItems, activeKey, collapsed, defaultCollapsed = fals
157
158
  item.onClick?.();
158
159
  }
159
160
  };
160
- return (_jsxs(Shell, { "$collapsed": isCollapsed, className: className, style: style, "data-testid": testId, children: [_jsxs(Scroll, { children: [_jsx(LogoHeader, { "$collapsed": isCollapsed, children: _jsx(Logo, { variant: isCollapsed ? LogoVariant.Icon : LogoVariant.Horizontal, color: logo?.color ?? 'var(--color-foreground-fg-brand-logo)', gradient: logo?.gradient, svgUrl: logo?.svgUrl }) }), _jsxs(Nav, { children: [_jsx(NavTop, { children: navItems.map((item) => (_jsx(DrawerNavItem, { text: item.text, icon: item.icon, state: resolveState(item, activeKey), size: drawerSize, hierarchy: item.hierarchy ?? DrawerNavItemHierarchy.First, showBadge: item.showBadge, badgeText: item.badgeText, onClick: () => handleItemClick(item) }, item.key ?? item.text))) }), (credits || profile) && (_jsxs(Footer, { children: [credits && (_jsx(FooterSlot, { "$collapsed": isCollapsed, children: _jsx(DrawerCreditsCard, { ...credits, size: drawerSize }) })), profile && (_jsx(FooterSlot, { "$collapsed": isCollapsed, children: _jsx(DrawerProfile, { ...profile, size: drawerSize }) }))] }))] })] }), showToggle && (_jsx(ToggleButton, { type: "button", onClick: handleToggle, "aria-label": isCollapsed ? 'Expand sidebar' : 'Collapse sidebar', children: _jsx(ToggleIcon, { "$collapsed": isCollapsed, children: getIconComponent('CaretLeft', { size: 16, weight: 'bold' }) }) }))] }));
161
+ return (_jsxs(Shell, { "$collapsed": isCollapsed, className: className, style: style, "data-testid": testId, children: [_jsxs(Scroll, { children: [_jsx(LogoHeader, { "$collapsed": isCollapsed, children: _jsx(Logo, { variant: isCollapsed ? LogoVariant.Icon : LogoVariant.Horizontal, color: logo?.color ?? 'var(--color-foreground-fg-brand-logo)', gradient: logo?.gradient, svgUrl: logo?.svgUrl }) }), _jsxs(Nav, { children: [_jsx(NavTop, { children: navItems.map((item) => (_jsx(DrawerNavItem, { text: item.text, icon: item.icon, state: resolveState(item, activeKey), size: drawerSize, hierarchy: item.hierarchy ?? DrawerNavItemHierarchy.First, showBadge: item.showBadge, badgeText: item.badgeText, onClick: () => handleItemClick(item) }, item.key ?? item.text))) }), (credits || creditsLoading || profile) && (_jsxs(Footer, { children: [(credits || creditsLoading) && (_jsx(FooterSlot, { "$collapsed": isCollapsed, children: creditsLoading ? (_jsx(DrawerCreditsCardSkeleton, { size: drawerSize })) : (_jsx(DrawerCreditsCard, { ...credits, size: drawerSize })) })), profile && (_jsx(FooterSlot, { "$collapsed": isCollapsed, children: _jsx(DrawerProfile, { ...profile, size: drawerSize }) }))] }))] })] }), showToggle && (_jsx(ToggleButton, { type: "button", onClick: handleToggle, "aria-label": isCollapsed ? 'Expand sidebar' : 'Collapse sidebar', children: _jsx(ToggleIcon, { "$collapsed": isCollapsed, children: getIconComponent('CaretLeft', { size: 16, weight: 'bold' }) }) }))] }));
161
162
  };
@@ -6,4 +6,6 @@ type Story = StoryObj<typeof Drawer>;
6
6
  export declare const Expanded: Story;
7
7
  export declare const Collapsed: Story;
8
8
  export declare const WithSubItems: Story;
9
+ export declare const CreditsLoading: Story;
10
+ export declare const CreditsLoadingCollapsed: Story;
9
11
  export declare const NoFooter: Story;
@@ -42,6 +42,11 @@ const meta = {
42
42
  description: 'Show the floating collapse/expand toggle',
43
43
  table: { defaultValue: { summary: 'true' } },
44
44
  },
45
+ creditsLoading: {
46
+ control: 'boolean',
47
+ description: 'Render the credits card as a loading skeleton',
48
+ table: { defaultValue: { summary: 'false' } },
49
+ },
45
50
  navItems: { control: false },
46
51
  credits: { control: false },
47
52
  profile: { control: false },
@@ -102,6 +107,12 @@ export const WithSubItems = {
102
107
  ],
103
108
  },
104
109
  };
110
+ export const CreditsLoading = {
111
+ args: { creditsLoading: true },
112
+ };
113
+ export const CreditsLoadingCollapsed = {
114
+ args: { creditsLoading: true, defaultCollapsed: true },
115
+ };
105
116
  export const NoFooter = {
106
117
  args: { credits: undefined, profile: undefined },
107
118
  };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { DrawerCreditsCardSkeletonProps } from './types';
3
+ /**
4
+ * Loading placeholder for {@link DrawerCreditsCard}. Reproduces the card's
5
+ * gem box, title, info icon, progress bar and credits caption (Expanded), or
6
+ * the single gem box (Collapsed), so it occupies the same footprint while the
7
+ * credits data is being fetched. Fully theme-aware.
8
+ */
9
+ export declare const DrawerCreditsCardSkeleton: React.FC<DrawerCreditsCardSkeletonProps>;
@@ -0,0 +1,49 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styled from '@emotion/styled';
3
+ import { SkeletonLoader } from '../UI';
4
+ import { DrawerSize } from './types';
5
+ /** Mirrors {@link DrawerCreditsCard}'s Card so the skeleton snaps in place. */
6
+ const Card = styled.div `
7
+ box-sizing: border-box;
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: var(--spacing-tokens-size-in-px-spacing-spacing-xs, 4px);
11
+ width: 100%;
12
+ padding: var(--spacing-tokens-size-in-px-spacing-spacing-md, 8px)
13
+ var(--spacing-tokens-size-in-px-spacing-spacing-lg, 12px);
14
+ background-color: var(--color-background-bg-card-highlight);
15
+ border: 1px solid var(--color-border-border-divider);
16
+ border-radius: var(--spacing-tokens-size-in-px-spacing-spacing-md, 8px);
17
+ `;
18
+ const HeaderRow = styled.div `
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: space-between;
22
+ width: 100%;
23
+ `;
24
+ const HeaderLeft = styled.div `
25
+ display: flex;
26
+ align-items: center;
27
+ gap: var(--spacing-tokens-size-in-px-spacing-spacing-md, 8px);
28
+ `;
29
+ const ProgressRow = styled.div `
30
+ display: flex;
31
+ align-items: center;
32
+ height: 20px;
33
+ width: 100%;
34
+ `;
35
+ const RADIUS_XS = 'var(--spacing-tokens-size-in-px-radius-radius-xs, 4px)';
36
+ const RADIUS_FULL = 'var(--spacing-tokens-size-in-px-radius-radius-full, 999px)';
37
+ const RADIUS_BOX = 'var(--spacing-tokens-size-in-px-spacing-spacing-md, 8px)';
38
+ /**
39
+ * Loading placeholder for {@link DrawerCreditsCard}. Reproduces the card's
40
+ * gem box, title, info icon, progress bar and credits caption (Expanded), or
41
+ * the single gem box (Collapsed), so it occupies the same footprint while the
42
+ * credits data is being fetched. Fully theme-aware.
43
+ */
44
+ export const DrawerCreditsCardSkeleton = ({ size = DrawerSize.Expanded, className, style, testId }) => {
45
+ if (size === DrawerSize.Collapsed) {
46
+ return (_jsx(SkeletonLoader, { width: "36px", height: "36px", borderRadius: RADIUS_BOX, style: style }));
47
+ }
48
+ return (_jsxs(Card, { className: className, style: style, "data-testid": testId, children: [_jsxs(HeaderRow, { children: [_jsxs(HeaderLeft, { children: [_jsx(SkeletonLoader, { width: "36px", height: "36px", borderRadius: RADIUS_BOX }), _jsx(SkeletonLoader, { width: "96px", height: "20px", borderRadius: RADIUS_XS })] }), _jsx(SkeletonLoader, { width: "20px", height: "20px", borderRadius: RADIUS_FULL })] }), _jsx(ProgressRow, { children: _jsx(SkeletonLoader, { width: "100%", height: "4px", borderRadius: RADIUS_XS }) }), _jsx(SkeletonLoader, { width: "60%", height: "16px", borderRadius: RADIUS_XS })] }));
49
+ };
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { DrawerCreditsCardSkeleton } from './DrawerCreditsCardSkeleton';
3
+ declare const meta: Meta<typeof DrawerCreditsCardSkeleton>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof DrawerCreditsCardSkeleton>;
6
+ export declare const Default: Story;
7
+ export declare const Collapsed: Story;
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DrawerCreditsCardSkeleton } from './DrawerCreditsCardSkeleton';
3
+ import { DrawerSize } from './types';
4
+ const meta = {
5
+ title: 'Design System/Components/Drawer/DrawerCreditsCardSkeleton',
6
+ component: DrawerCreditsCardSkeleton,
7
+ parameters: {
8
+ layout: 'centered',
9
+ design: {
10
+ type: 'figspec',
11
+ url: 'https://www.figma.com/design/mIhjz2yJjcpLlIqw6oUivt/Beyond-Presence?node-id=6940-29126',
12
+ },
13
+ },
14
+ tags: ['autodocs'],
15
+ argTypes: {
16
+ size: {
17
+ control: 'inline-radio',
18
+ options: Object.values(DrawerSize),
19
+ table: { defaultValue: { summary: 'Expanded' } },
20
+ },
21
+ },
22
+ args: {
23
+ size: DrawerSize.Expanded,
24
+ },
25
+ decorators: [
26
+ (Story) => (_jsx("div", { style: {
27
+ width: 230,
28
+ padding: 16,
29
+ backgroundColor: 'var(--color-background-bg-page-contrast)',
30
+ }, children: _jsx(Story, {}) })),
31
+ ],
32
+ };
33
+ export default meta;
34
+ export const Default = {};
35
+ export const Collapsed = {
36
+ args: { size: DrawerSize.Collapsed },
37
+ };
@@ -1,6 +1,7 @@
1
1
  export * from './Drawer';
2
2
  export * from './DrawerNavItem';
3
3
  export * from './DrawerCreditsCard';
4
+ export * from './DrawerCreditsCardSkeleton';
4
5
  export * from './DrawerProfile';
5
6
  export * from './DrawerIcons';
6
7
  export * from './types';
@@ -1,6 +1,7 @@
1
1
  export * from './Drawer';
2
2
  export * from './DrawerNavItem';
3
3
  export * from './DrawerCreditsCard';
4
+ export * from './DrawerCreditsCardSkeleton';
4
5
  export * from './DrawerProfile';
5
6
  export * from './DrawerIcons';
6
7
  export * from './types';
@@ -77,6 +77,16 @@ export interface DrawerCreditsCardProps {
77
77
  style?: CSSProperties;
78
78
  testId?: string;
79
79
  }
80
+ /**
81
+ * Props for the {@link DrawerCreditsCardSkeleton} loading placeholder.
82
+ */
83
+ export interface DrawerCreditsCardSkeletonProps {
84
+ /** Expanded (full card) or Collapsed (icon-only box). */
85
+ size?: DrawerSize;
86
+ className?: string;
87
+ style?: CSSProperties;
88
+ testId?: string;
89
+ }
80
90
  /**
81
91
  * An item in the {@link DrawerProfile} click menu.
82
92
  */
@@ -150,6 +160,8 @@ export interface DrawerProps {
150
160
  showToggle?: boolean;
151
161
  /** Credits card configuration. Omit to hide the card. */
152
162
  credits?: Omit<DrawerCreditsCardProps, 'size' | 'className' | 'style'>;
163
+ /** Render the credits card as a loading skeleton instead of its content. */
164
+ creditsLoading?: boolean;
153
165
  /** User profile footer configuration. Omit to hide the footer. */
154
166
  profile?: Omit<DrawerProfileProps, 'size' | 'className' | 'style'>;
155
167
  /** Logo appearance overrides. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@beydesign/storybook",
3
3
  "private": false,
4
- "version": "0.2.23",
4
+ "version": "0.2.24",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",