uikit-react-public 0.45.4 → 0.47.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 (45) hide show
  1. package/dist/components/DropZone/DropZone.d.ts +21 -0
  2. package/dist/components/DropZone/DropZone.stories.d.ts +52 -0
  3. package/dist/components/DropZone/__tests__/DropZone.test.d.ts +1 -0
  4. package/dist/components/DropZone/index.d.ts +2 -0
  5. package/dist/components/Label/Label.d.ts +1 -0
  6. package/dist/components/Label/Label.stories.d.ts +1 -0
  7. package/dist/components/Skeleton/Skeleton.d.ts +35 -0
  8. package/dist/components/Skeleton/Skeleton.stories.d.ts +27 -0
  9. package/dist/components/Skeleton/SkeletonAvatar.d.ts +7 -0
  10. package/dist/components/Skeleton/SkeletonInput.d.ts +4 -0
  11. package/dist/components/Skeleton/SkeletonTableRow.d.ts +9 -0
  12. package/dist/components/Skeleton/SkeletonText.d.ts +4 -0
  13. package/dist/components/Skeleton/__tests__/Skeleton.test.d.ts +1 -0
  14. package/dist/components/Skeleton/index.d.ts +6 -0
  15. package/dist/components/index.d.ts +4 -0
  16. package/dist/hooks/__tests__/useDraggable.test.d.ts +1 -0
  17. package/dist/hooks/index.d.ts +4 -0
  18. package/dist/hooks/useDraggable.d.ts +31 -0
  19. package/dist/hooks/useDropZone.d.ts +57 -0
  20. package/dist/index.js +7247 -6685
  21. package/lib/components/DropZone/DropZone.mdx +72 -0
  22. package/lib/components/DropZone/DropZone.stories.tsx +139 -0
  23. package/lib/components/DropZone/DropZone.tsx +213 -0
  24. package/lib/components/DropZone/__tests__/DropZone.test.tsx +378 -0
  25. package/lib/components/DropZone/__tests__/__snapshots__/DropZone.test.tsx.snap +46 -0
  26. package/lib/components/DropZone/index.ts +2 -0
  27. package/lib/components/Label/Label.stories.tsx +17 -0
  28. package/lib/components/Label/Label.tsx +4 -7
  29. package/lib/components/Label/__tests__/Label.test.tsx +15 -0
  30. package/lib/components/Label/__tests__/__snapshots__/Label.test.tsx.snap +1 -3
  31. package/lib/components/Skeleton/Skeleton.mdx +34 -0
  32. package/lib/components/Skeleton/Skeleton.stories.tsx +77 -0
  33. package/lib/components/Skeleton/Skeleton.tsx +158 -0
  34. package/lib/components/Skeleton/SkeletonAvatar.tsx +20 -0
  35. package/lib/components/Skeleton/SkeletonInput.tsx +13 -0
  36. package/lib/components/Skeleton/SkeletonTableRow.tsx +44 -0
  37. package/lib/components/Skeleton/SkeletonText.tsx +13 -0
  38. package/lib/components/Skeleton/__tests__/Skeleton.test.tsx +86 -0
  39. package/lib/components/Skeleton/index.ts +6 -0
  40. package/lib/components/index.ts +13 -0
  41. package/lib/hooks/__tests__/useDraggable.test.tsx +184 -0
  42. package/lib/hooks/index.ts +19 -0
  43. package/lib/hooks/useDraggable.ts +243 -0
  44. package/lib/hooks/useDropZone.ts +418 -0
  45. package/package.json +1 -1
@@ -0,0 +1,378 @@
1
+ import { ReactElement } from 'react';
2
+ import { afterEach, describe, expect, test, vitest } from 'vitest';
3
+ import { fireEvent, render, screen } from '@testing-library/react';
4
+ import DropZone from '../DropZone';
5
+ import { ThemeContextProvider } from '../../../theme/useTheme';
6
+ import { useDraggable, useDropZone } from '../../../hooks';
7
+ import {
8
+ clearActiveKeyboardDrag,
9
+ getActiveKeyboardDrag,
10
+ } from '../../../hooks/useDropZone';
11
+
12
+ const TABLE_CELL_TYPE = 'application/x-ucl-uikit-table-cell';
13
+
14
+ const wrap = (ui: ReactElement) =>
15
+ render(<ThemeContextProvider>{ui}</ThemeContextProvider>);
16
+
17
+ const createDataTransfer = (data: Record<string, string>) =>
18
+ ({
19
+ dropEffect: 'none',
20
+ files: [],
21
+ getData: vitest.fn((type: string) => data[type] ?? ''),
22
+ setData: vitest.fn(),
23
+ types: Object.keys(data),
24
+ }) as unknown as DataTransfer;
25
+
26
+ describe('DropZone', () => {
27
+ afterEach(() => {
28
+ clearActiveKeyboardDrag();
29
+ });
30
+
31
+ test('snapshot: no props', () => {
32
+ const renderResult = wrap(<DropZone />);
33
+
34
+ expect(renderResult.container.firstChild).toMatchSnapshot();
35
+ });
36
+
37
+ test('renders with default test id and labelled group role', () => {
38
+ wrap(<DropZone />);
39
+
40
+ expect(screen.getByTestId('ucl-uikit-drop-zone')).toBeInTheDocument();
41
+ expect(
42
+ screen.getByRole('group', { name: 'Drop zone' })
43
+ ).toBeInTheDocument();
44
+ });
45
+
46
+ test('falls back to generic copy when accepted types are empty', () => {
47
+ wrap(<DropZone acceptedTypes={[]} />);
48
+
49
+ expect(screen.getByText('Drop an item here')).toBeInTheDocument();
50
+ });
51
+
52
+ test('does not add a role when using the hook directly', () => {
53
+ const HookDropZone = () => {
54
+ const { getRootProps } = useDropZone();
55
+
56
+ return (
57
+ <section
58
+ data-testid='hook-drop-zone'
59
+ {...getRootProps()}
60
+ />
61
+ );
62
+ };
63
+
64
+ render(<HookDropZone />);
65
+
66
+ expect(screen.getByTestId('hook-drop-zone')).not.toHaveAttribute('role');
67
+ });
68
+
69
+ test('sets drag state data attributes during an accepted drag', () => {
70
+ wrap(<DropZone acceptedTypes={TABLE_CELL_TYPE} />);
71
+
72
+ const dropZone = screen.getByTestId('ucl-uikit-drop-zone');
73
+
74
+ fireEvent.dragEnter(dropZone, {
75
+ dataTransfer: createDataTransfer({
76
+ [TABLE_CELL_TYPE]: JSON.stringify({
77
+ column: 'Status',
78
+ row: 'Research proposal',
79
+ value: 'Approved',
80
+ }),
81
+ }),
82
+ });
83
+
84
+ expect(dropZone).toHaveAttribute('data-drag-active', 'true');
85
+ expect(dropZone).toHaveAttribute('data-drag-accept', 'true');
86
+ expect(dropZone).toHaveAttribute('data-drag-reject', 'false');
87
+ });
88
+
89
+ test('calls onDrop with parsed app data when a matching type is dropped', () => {
90
+ const onDrop = vitest.fn();
91
+ const dataTransfer = createDataTransfer({
92
+ [TABLE_CELL_TYPE]: JSON.stringify({
93
+ column: 'Status',
94
+ row: 'Research proposal',
95
+ value: 'Approved',
96
+ }),
97
+ });
98
+
99
+ wrap(
100
+ <DropZone
101
+ acceptedTypes={TABLE_CELL_TYPE}
102
+ onDrop={onDrop}
103
+ />
104
+ );
105
+
106
+ fireEvent.drop(screen.getByTestId('ucl-uikit-drop-zone'), {
107
+ dataTransfer,
108
+ });
109
+
110
+ expect(onDrop).toHaveBeenCalledWith(
111
+ expect.objectContaining({
112
+ data: {
113
+ column: 'Status',
114
+ row: 'Research proposal',
115
+ value: 'Approved',
116
+ },
117
+ dataTransfer,
118
+ rawData: JSON.stringify({
119
+ column: 'Status',
120
+ row: 'Research proposal',
121
+ value: 'Approved',
122
+ }),
123
+ type: TABLE_CELL_TYPE,
124
+ }),
125
+ expect.any(Object)
126
+ );
127
+ });
128
+
129
+ test('calls onReject when a dropped type is not accepted', () => {
130
+ const onDrop = vitest.fn();
131
+ const onReject = vitest.fn();
132
+
133
+ wrap(
134
+ <DropZone
135
+ acceptedTypes={TABLE_CELL_TYPE}
136
+ onDrop={onDrop}
137
+ onReject={onReject}
138
+ />
139
+ );
140
+
141
+ fireEvent.drop(screen.getByTestId('ucl-uikit-drop-zone'), {
142
+ dataTransfer: createDataTransfer({
143
+ 'text/plain': 'Approved',
144
+ }),
145
+ });
146
+
147
+ expect(onDrop).not.toHaveBeenCalled();
148
+ expect(onReject).toHaveBeenCalledWith(
149
+ {
150
+ drop: null,
151
+ reason: 'invalid-type',
152
+ },
153
+ expect.any(Object)
154
+ );
155
+ });
156
+
157
+ test('shows rejection copy before release copy for rejected drags', () => {
158
+ wrap(<DropZone acceptedTypes={TABLE_CELL_TYPE} />);
159
+
160
+ fireEvent.dragEnter(screen.getByTestId('ucl-uikit-drop-zone'), {
161
+ dataTransfer: createDataTransfer({
162
+ 'text/plain': 'Approved',
163
+ }),
164
+ });
165
+
166
+ expect(
167
+ screen.getByText('This item cannot be dropped here')
168
+ ).toBeInTheDocument();
169
+ expect(screen.queryByText('Release to drop')).not.toBeInTheDocument();
170
+ });
171
+
172
+ test('calls onReject when canDrop returns false', () => {
173
+ const onReject = vitest.fn();
174
+
175
+ wrap(
176
+ <DropZone<{ locked: boolean }>
177
+ acceptedTypes={TABLE_CELL_TYPE}
178
+ canDrop={(drop) => !drop.data.locked}
179
+ onReject={onReject}
180
+ />
181
+ );
182
+
183
+ fireEvent.drop(screen.getByTestId('ucl-uikit-drop-zone'), {
184
+ dataTransfer: createDataTransfer({
185
+ [TABLE_CELL_TYPE]: JSON.stringify({ locked: true }),
186
+ }),
187
+ });
188
+
189
+ expect(onReject).toHaveBeenCalledWith(
190
+ {
191
+ drop: expect.objectContaining({
192
+ data: { locked: true },
193
+ type: TABLE_CELL_TYPE,
194
+ }),
195
+ reason: 'cannot-drop',
196
+ },
197
+ expect.any(Object)
198
+ );
199
+ });
200
+
201
+ test('does not call onDrop when disabled', () => {
202
+ const onDrop = vitest.fn();
203
+
204
+ wrap(
205
+ <DropZone
206
+ acceptedTypes={TABLE_CELL_TYPE}
207
+ disabled
208
+ onDrop={onDrop}
209
+ />
210
+ );
211
+
212
+ fireEvent.drop(screen.getByTestId('ucl-uikit-drop-zone'), {
213
+ dataTransfer: createDataTransfer({
214
+ [TABLE_CELL_TYPE]: 'Approved',
215
+ }),
216
+ });
217
+
218
+ expect(onDrop).not.toHaveBeenCalled();
219
+ });
220
+
221
+ test('passes drag state to render-prop children', () => {
222
+ wrap(
223
+ <DropZone acceptedTypes={TABLE_CELL_TYPE}>
224
+ {({ isDragActive }) => (
225
+ <span>{isDragActive ? 'Release to drop' : 'Drop a table cell'}</span>
226
+ )}
227
+ </DropZone>
228
+ );
229
+
230
+ const dropZone = screen.getByTestId('ucl-uikit-drop-zone');
231
+
232
+ expect(screen.getByText('Drop a table cell')).toBeInTheDocument();
233
+
234
+ fireEvent.dragEnter(dropZone, {
235
+ dataTransfer: createDataTransfer({
236
+ [TABLE_CELL_TYPE]: 'Approved',
237
+ }),
238
+ });
239
+
240
+ expect(screen.getByText('Release to drop')).toBeInTheDocument();
241
+ });
242
+
243
+ test('supports keyboard drag and drop between UIKit hooks', () => {
244
+ const onDrop = vitest.fn();
245
+
246
+ const KeyboardDndDemo = () => {
247
+ const { getDragProps } = useDraggable({
248
+ data: { value: 'Approved' },
249
+ type: TABLE_CELL_TYPE,
250
+ });
251
+ const { getRootProps } = useDropZone<{ value: string }>({
252
+ acceptedTypes: TABLE_CELL_TYPE,
253
+ onDrop,
254
+ });
255
+
256
+ return (
257
+ <>
258
+ <button
259
+ data-testid='drag-source'
260
+ type='button'
261
+ {...getDragProps()}
262
+ >
263
+ Approved
264
+ </button>
265
+ <div
266
+ data-testid='drop-target'
267
+ {...getRootProps()}
268
+ />
269
+ </>
270
+ );
271
+ };
272
+
273
+ render(<KeyboardDndDemo />);
274
+
275
+ fireEvent.keyDown(screen.getByTestId('drag-source'), { key: ' ' });
276
+ fireEvent.keyDown(screen.getByTestId('drop-target'), { key: 'Enter' });
277
+
278
+ expect(onDrop).toHaveBeenCalledWith(
279
+ expect.objectContaining({
280
+ data: { value: 'Approved' },
281
+ dataTransfer: null,
282
+ files: [],
283
+ rawData: JSON.stringify({ value: 'Approved' }),
284
+ type: TABLE_CELL_TYPE,
285
+ }),
286
+ expect.any(Object)
287
+ );
288
+ });
289
+
290
+ test('honours keyboardDrop false on the DropZone component', () => {
291
+ const onDrop = vitest.fn();
292
+
293
+ const KeyboardDndDemo = () => {
294
+ const { getDragProps } = useDraggable({
295
+ data: { value: 'Approved' },
296
+ type: TABLE_CELL_TYPE,
297
+ });
298
+
299
+ return (
300
+ <>
301
+ <button
302
+ data-testid='drag-source'
303
+ type='button'
304
+ {...getDragProps()}
305
+ >
306
+ Approved
307
+ </button>
308
+ <DropZone
309
+ acceptedTypes={TABLE_CELL_TYPE}
310
+ keyboardDrop={false}
311
+ onDrop={onDrop}
312
+ testId='drop-target'
313
+ />
314
+ </>
315
+ );
316
+ };
317
+
318
+ wrap(<KeyboardDndDemo />);
319
+
320
+ fireEvent.keyDown(screen.getByTestId('drag-source'), { key: 'Enter' });
321
+ fireEvent.keyDown(screen.getByTestId('drop-target'), { key: 'Enter' });
322
+
323
+ expect(onDrop).not.toHaveBeenCalled();
324
+ expect(screen.getByTestId('drop-target')).not.toHaveAttribute(
325
+ 'keyboardDrop'
326
+ );
327
+ });
328
+
329
+ test('supports keyboard drop when drag and drop props are composed on one item', () => {
330
+ const onDrop = vitest.fn();
331
+ const onReject = vitest.fn();
332
+
333
+ const ReorderItem = ({ id }: { id: string }) => {
334
+ const { getDragProps } = useDraggable({
335
+ data: { id },
336
+ type: TABLE_CELL_TYPE,
337
+ });
338
+ const { getRootProps } = useDropZone<{ id: string }>({
339
+ acceptedTypes: TABLE_CELL_TYPE,
340
+ canDrop: (drop) => drop.data.id !== id,
341
+ onDrop,
342
+ onReject,
343
+ });
344
+
345
+ return (
346
+ <li
347
+ data-testid={`item-${id}`}
348
+ {...getRootProps<HTMLLIElement>(getDragProps<HTMLLIElement>())}
349
+ >
350
+ {id}
351
+ </li>
352
+ );
353
+ };
354
+
355
+ render(
356
+ <ul>
357
+ <ReorderItem id='first' />
358
+ <ReorderItem id='second' />
359
+ </ul>
360
+ );
361
+
362
+ fireEvent.keyDown(screen.getByTestId('item-first'), { key: 'Enter' });
363
+
364
+ expect(onDrop).not.toHaveBeenCalled();
365
+ expect(onReject).not.toHaveBeenCalled();
366
+ expect(getActiveKeyboardDrag()?.data).toEqual({ id: 'first' });
367
+
368
+ fireEvent.keyDown(screen.getByTestId('item-second'), { key: 'Enter' });
369
+
370
+ expect(onDrop).toHaveBeenCalledWith(
371
+ expect.objectContaining({
372
+ data: { id: 'first' },
373
+ type: TABLE_CELL_TYPE,
374
+ }),
375
+ expect.any(Object)
376
+ );
377
+ });
378
+ });
@@ -0,0 +1,46 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`DropZone > snapshot: no props 1`] = `
4
+ <div
5
+ aria-label="Drop zone"
6
+ class="ucl-uikit-drop-zone css-vpriu7"
7
+ data-drag-accept="false"
8
+ data-drag-active="false"
9
+ data-drag-reject="false"
10
+ data-testid="ucl-uikit-drop-zone"
11
+ role="group"
12
+ tabindex="0"
13
+ >
14
+ <svg
15
+ aria-hidden="true"
16
+ class="ucl-uikit-icon css-17h2vfb"
17
+ data-testid="ucl-uikit-icon"
18
+ fill="none"
19
+ focusable="false"
20
+ height="24"
21
+ stroke="currentColor"
22
+ stroke-linecap="round"
23
+ stroke-linejoin="round"
24
+ stroke-width="2"
25
+ viewBox="0 0 24 24"
26
+ width="24"
27
+ xmlns="http://www.w3.org/2000/svg"
28
+ >
29
+ <path
30
+ d="m5 9-3 3 3 3M9 5l3-3 3 3m0 14-3 3-3-3M19 9l3 3-3 3M2 12h20M12 2v20"
31
+ />
32
+ </svg>
33
+ <div
34
+ class="ucl-uikit-paragraph css-12ufxmf"
35
+ data-testid="ucl-uikit-paragraph"
36
+ >
37
+ Drop an item here
38
+ </div>
39
+ <span
40
+ class="ucl-uikit-text css-v0obke"
41
+ data-testid="ucl-uikit-text"
42
+ >
43
+ Drag a compatible item into this area
44
+ </span>
45
+ </div>
46
+ `;
@@ -0,0 +1,2 @@
1
+ export { default } from './DropZone';
2
+ export type { DropZoneProps, DropZoneRenderProps } from './DropZone';
@@ -38,6 +38,23 @@ export const Optional: Story = {
38
38
  },
39
39
  };
40
40
 
41
+ export const OptionalWithCustomStyle: Story = {
42
+ name: 'Optional with custom style',
43
+ args: {
44
+ children: 'Optional label',
45
+ optional: true,
46
+ optionalClassName: 'custom-optional-style',
47
+ },
48
+ decorators: [
49
+ (Story) => (
50
+ <>
51
+ <style>{`.custom-optional-style { font-weight: normal; color: #565656; }`}</style>
52
+ <Story />
53
+ </>
54
+ ),
55
+ ],
56
+ };
57
+
41
58
  export const WithLongText: Story = {
42
59
  name: 'With long text',
43
60
  args: {
@@ -10,6 +10,7 @@ export interface LabelBaseProps extends LabelHTMLAttributes<HTMLLabelElement> {
10
10
  type?: 'block' | 'inline';
11
11
  disabled?: boolean;
12
12
  optional?: boolean;
13
+ optionalClassName?: string;
13
14
  testId?: string;
14
15
  }
15
16
 
@@ -23,6 +24,7 @@ const Label = forwardRef<Ref, LabelProps>(
23
24
  type = 'block',
24
25
  disabled,
25
26
  optional,
27
+ optionalClassName,
26
28
  testId = NAME,
27
29
  className,
28
30
  children,
@@ -40,7 +42,7 @@ const Label = forwardRef<Ref, LabelProps>(
40
42
  disabled = disabled ?? contextDisabled;
41
43
  optional = optional ?? contextOptional;
42
44
  const htmlFor = props.htmlFor ?? contextId;
43
- const { md, mdSemibold } = theme.typography.body;
45
+ const { mdSemibold } = theme.typography.body;
44
46
 
45
47
  const baseStyle = css`
46
48
  width: 100%;
@@ -74,11 +76,6 @@ const Label = forwardRef<Ref, LabelProps>(
74
76
  className
75
77
  );
76
78
 
77
- const optionalStyle = css`
78
- font-weight: ${md.fontWeight};
79
- font-style: italic;
80
- `;
81
-
82
79
  return (
83
80
  <label
84
81
  ref={ref}
@@ -91,7 +88,7 @@ const Label = forwardRef<Ref, LabelProps>(
91
88
  {optional && (
92
89
  <>
93
90
  {' '}
94
- <span className={optionalStyle}>(optional)</span>
91
+ <span className={optionalClassName}>(optional)</span>
95
92
  </>
96
93
  )}
97
94
  </label>
@@ -51,6 +51,21 @@ describe('Label', () => {
51
51
  expect(renderResult.container.firstChild).toMatchSnapshot();
52
52
  });
53
53
 
54
+ test('optional text can accept a custom class name', () => {
55
+ render(
56
+ <ThemeContextProvider>
57
+ <Label
58
+ optional
59
+ optionalClassName='custom-optional-class'
60
+ >
61
+ Name
62
+ </Label>
63
+ </ThemeContextProvider>
64
+ );
65
+
66
+ expect(screen.getByText('(optional)')).toHaveClass('custom-optional-class');
67
+ });
68
+
54
69
  test('snapshot: testId prop', () => {
55
70
  const renderResult = render(
56
71
  <ThemeContextProvider>
@@ -68,9 +68,7 @@ exports[`Label > snapshot: with optional prop 1`] = `
68
68
  >
69
69
  Name
70
70
 
71
- <span
72
- class="css-1fd72bb"
73
- >
71
+ <span>
74
72
  (optional)
75
73
  </span>
76
74
  </label>
@@ -0,0 +1,34 @@
1
+ import * as SkeletonStories from "./Skeleton.stories";
2
+ import { Meta, Title, Subtitle, Canvas, Controls } from "@storybook/addon-docs/blocks";
3
+
4
+ <Meta of={SkeletonStories} />
5
+ <Title />
6
+ <Subtitle>A placeholder that mirrors the shape of content while it loads.</Subtitle>
7
+
8
+ Use `<Skeleton>` when a region's layout is known but its data is still loading. Numeric `width` and `height` values are treated as pixels; CSS strings such as `40%` are passed through.
9
+
10
+ ## Variants
11
+
12
+ ### Circle
13
+ The default 72px circle matches the Figma avatar placeholder.
14
+
15
+ <Canvas of={SkeletonStories.Circle} />
16
+
17
+ ### Rectangle
18
+ Use explicit dimensions to reserve the final content's space. Rectangles have square corners by default; pass a `radius` token when the content will be rounded.
19
+
20
+ <Canvas of={SkeletonStories.Landscape} />
21
+
22
+ ### Text
23
+ Text placeholders are 8px high with a 16px gap. With multiple lines, the final line is 61.8% wide.
24
+
25
+ <Canvas of={SkeletonStories.TextLines} />
26
+
27
+ ## Accessibility
28
+
29
+ Skeleton shapes are decorative and hidden from assistive technology. Set `aria-busy="true"` on the region whose content is loading and provide one visually hidden loading message for that region. The shimmer is removed when the user prefers reduced motion.
30
+
31
+ ## Props
32
+
33
+ <Canvas of={SkeletonStories.Default} sourceState="hidden" />
34
+ <Controls of={SkeletonStories.Default} />
@@ -0,0 +1,77 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { css } from '@emotion/css';
3
+ import Skeleton from './Skeleton';
4
+
5
+ const meta = {
6
+ title: 'Components/Skeleton',
7
+ component: Skeleton,
8
+ parameters: { layout: 'padded' },
9
+ args: {
10
+ variant: 'text',
11
+ },
12
+ argTypes: {
13
+ variant: {
14
+ options: ['text', 'circle', 'rect'],
15
+ control: { type: 'radio' },
16
+ },
17
+ },
18
+ } satisfies Meta<typeof Skeleton>;
19
+
20
+ export default meta;
21
+ type Story = StoryObj<typeof meta>;
22
+
23
+ export const Default: Story = {};
24
+
25
+ export const Circle: Story = {
26
+ args: { variant: 'circle', width: 72, height: 72 },
27
+ };
28
+
29
+ export const Landscape: Story = {
30
+ args: { variant: 'rect', width: 637, height: 359 },
31
+ };
32
+
33
+ export const Portrait: Story = {
34
+ args: { variant: 'rect', width: 358, height: 620.69 },
35
+ };
36
+
37
+ export const TextLines: Story = {
38
+ args: { variant: 'text', width: 461, count: 4 },
39
+ };
40
+
41
+ export const FigmaExamples: Story = {
42
+ parameters: { layout: 'padded' },
43
+ render: () => (
44
+ <div
45
+ className={css`
46
+ position: relative;
47
+ width: 677px;
48
+ height: 1504px;
49
+ `}
50
+ >
51
+ <Skeleton
52
+ variant='circle'
53
+ width={72}
54
+ height={72}
55
+ style={{ position: 'absolute', top: 20, left: 20 }}
56
+ />
57
+ <Skeleton
58
+ variant='rect'
59
+ width={637}
60
+ height={359}
61
+ style={{ position: 'absolute', top: 139, left: 20 }}
62
+ />
63
+ <Skeleton
64
+ variant='rect'
65
+ width={358}
66
+ height={620.69}
67
+ style={{ position: 'absolute', top: 545, left: 20 }}
68
+ />
69
+ <Skeleton
70
+ variant='text'
71
+ width={461}
72
+ count={4}
73
+ style={{ position: 'absolute', top: 1246, left: 20 }}
74
+ />
75
+ </div>
76
+ ),
77
+ };