@dxos/react-ui-stack 0.8.4-main.67995b8 → 0.8.4-main.a4bbb77

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 (76) hide show
  1. package/dist/lib/browser/{chunk-P3TQV4BA.mjs → chunk-K76XHALI.mjs} +399 -177
  2. package/dist/lib/browser/chunk-K76XHALI.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +5 -1
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/playwright/index.mjs +23 -6
  6. package/dist/lib/browser/playwright/index.mjs.map +2 -2
  7. package/dist/lib/browser/testing/index.mjs +3 -3
  8. package/dist/lib/browser/testing/index.mjs.map +3 -3
  9. package/dist/lib/node-esm/{chunk-3WVEPAJ4.mjs → chunk-2UOARV5Q.mjs} +399 -177
  10. package/dist/lib/node-esm/chunk-2UOARV5Q.mjs.map +7 -0
  11. package/dist/lib/node-esm/index.mjs +5 -1
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/playwright/index.mjs +23 -6
  14. package/dist/lib/node-esm/playwright/index.mjs.map +2 -2
  15. package/dist/lib/node-esm/testing/index.mjs +3 -3
  16. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  17. package/dist/types/src/components/Image/Image.d.ts +11 -0
  18. package/dist/types/src/components/Image/Image.d.ts.map +1 -0
  19. package/dist/types/src/components/Image/Image.stories.d.ts +30 -0
  20. package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -0
  21. package/dist/types/src/components/Image/index.d.ts +2 -0
  22. package/dist/types/src/components/Image/index.d.ts.map +1 -0
  23. package/dist/types/src/components/Stack/Stack.d.ts +10 -2
  24. package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
  25. package/dist/types/src/components/Stack/Stack.stories.d.ts +12 -3
  26. package/dist/types/src/components/Stack/Stack.stories.d.ts.map +1 -1
  27. package/dist/types/src/components/StackContext.d.ts +2 -1
  28. package/dist/types/src/components/StackContext.d.ts.map +1 -1
  29. package/dist/types/src/components/StackItem/StackItem.d.ts +4 -4
  30. package/dist/types/src/components/StackItem/StackItem.d.ts.map +1 -1
  31. package/dist/types/src/components/StackItem/StackItem.stories.d.ts +13 -5
  32. package/dist/types/src/components/StackItem/StackItem.stories.d.ts.map +1 -1
  33. package/dist/types/src/components/StackItem/StackItemContent.d.ts.map +1 -1
  34. package/dist/types/src/components/StackItem/StackItemHeading.d.ts +1 -1
  35. package/dist/types/src/components/StackItem/StackItemHeading.d.ts.map +1 -1
  36. package/dist/types/src/components/StackItem/StackItemResizeHandle.d.ts.map +1 -1
  37. package/dist/types/src/components/StackItem/StackItemSigil.d.ts.map +1 -1
  38. package/dist/types/src/components/index.d.ts +1 -0
  39. package/dist/types/src/components/index.d.ts.map +1 -1
  40. package/dist/types/src/exemplars/Card/Card.d.ts +3 -5
  41. package/dist/types/src/exemplars/Card/Card.d.ts.map +1 -1
  42. package/dist/types/src/exemplars/Card/Card.stories.d.ts +12 -4
  43. package/dist/types/src/exemplars/Card/Card.stories.d.ts.map +1 -1
  44. package/dist/types/src/exemplars/Card/fragments.d.ts +3 -2
  45. package/dist/types/src/exemplars/Card/fragments.d.ts.map +1 -1
  46. package/dist/types/src/exemplars/CardStack/CardStack.d.ts +3 -1
  47. package/dist/types/src/exemplars/CardStack/CardStack.d.ts.map +1 -1
  48. package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts +9 -3
  49. package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts.map +1 -1
  50. package/dist/types/src/hooks/useStackDropForElements.d.ts +1 -1
  51. package/dist/types/src/hooks/useStackDropForElements.d.ts.map +1 -1
  52. package/dist/types/src/testing/CardContainer.d.ts.map +1 -1
  53. package/dist/types/tsconfig.tsbuildinfo +1 -1
  54. package/package.json +27 -27
  55. package/src/components/Image/Image.stories.tsx +56 -0
  56. package/src/components/Image/Image.tsx +137 -0
  57. package/src/components/Image/index.ts +5 -0
  58. package/src/components/Stack/Stack.stories.tsx +8 -9
  59. package/src/components/Stack/Stack.tsx +215 -18
  60. package/src/components/StackContext.tsx +2 -1
  61. package/src/components/StackItem/StackItem.stories.tsx +15 -13
  62. package/src/components/StackItem/StackItem.tsx +26 -18
  63. package/src/components/StackItem/StackItemContent.tsx +1 -0
  64. package/src/components/StackItem/StackItemHeading.tsx +3 -3
  65. package/src/components/StackItem/StackItemResizeHandle.tsx +2 -1
  66. package/src/components/StackItem/StackItemSigil.tsx +2 -1
  67. package/src/components/index.ts +1 -0
  68. package/src/exemplars/Card/Card.stories.tsx +29 -43
  69. package/src/exemplars/Card/Card.tsx +11 -11
  70. package/src/exemplars/Card/fragments.ts +3 -2
  71. package/src/exemplars/CardStack/CardStack.stories.tsx +11 -10
  72. package/src/exemplars/CardStack/CardStack.tsx +12 -9
  73. package/src/hooks/useStackDropForElements.ts +1 -1
  74. package/src/testing/CardContainer.tsx +9 -6
  75. package/dist/lib/browser/chunk-P3TQV4BA.mjs.map +0 -7
  76. package/dist/lib/node-esm/chunk-3WVEPAJ4.mjs.map +0 -7
@@ -2,21 +2,17 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React from 'react';
9
7
 
10
- import { Icon, DropdownMenu } from '@dxos/react-ui';
11
- import { withTheme } from '@dxos/storybook-utils';
8
+ import { DropdownMenu, Icon } from '@dxos/react-ui';
9
+ import { withTheme } from '@dxos/react-ui/testing';
12
10
 
13
- import { StackItem } from './StackItem';
11
+ import { StackItem, type StackItemRootProps } from './StackItem';
14
12
 
15
- const meta: Meta<typeof StackItem.Root> = {
16
- title: 'ui/react-ui-stack/StackItem',
17
- component: StackItem.Root,
18
- render: (args) => (
19
- <StackItem.Root role='section' {...args} classNames='w-[20rem] border border-separator'>
13
+ const DefaultStory = (props: StackItemRootProps) => {
14
+ return (
15
+ <StackItem.Root role='section' {...props} classNames='w-[20rem] border border-separator'>
20
16
  <StackItem.Heading>
21
17
  <span className='sr-only'>Title</span>
22
18
  <div role='none' className='sticky -block-start-px bg-[--sticky-bg] p-1 is-full'>
@@ -31,16 +27,22 @@ const meta: Meta<typeof StackItem.Root> = {
31
27
  </StackItem.Heading>
32
28
  <StackItem.Content classNames='p-2'>Content</StackItem.Content>
33
29
  </StackItem.Root>
34
- ),
30
+ );
31
+ };
32
+
33
+ const meta = {
34
+ title: 'ui/react-ui-stack/StackItem',
35
+ component: StackItem.Root as any,
36
+ render: DefaultStory,
35
37
  decorators: [withTheme],
36
38
  parameters: {
37
39
  layout: 'centered',
38
40
  },
39
- };
41
+ } satisfies Meta<typeof DefaultStory>;
40
42
 
41
43
  export default meta;
42
44
 
43
- type Story = StoryObj<typeof StackItem.Root>;
45
+ type Story = StoryObj<typeof meta>;
44
46
 
45
47
  export const Default: Story = {
46
48
  args: {
@@ -7,46 +7,47 @@ import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-d
7
7
  import { preserveOffsetOnSource } from '@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source';
8
8
  import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
9
9
  import {
10
+ type Edge,
10
11
  attachClosestEdge,
11
12
  extractClosestEdge,
12
- type Edge,
13
13
  } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
14
14
  import { useFocusableGroup } from '@fluentui/react-tabster';
15
15
  import { composeRefs } from '@radix-ui/react-compose-refs';
16
16
  import React, {
17
- forwardRef,
18
- useLayoutEffect,
19
- useState,
20
17
  type ComponentPropsWithRef,
21
- useCallback,
22
18
  type ReactNode,
19
+ forwardRef,
20
+ useCallback,
21
+ useLayoutEffect,
23
22
  useMemo,
23
+ useState,
24
24
  } from 'react';
25
25
  import { createPortal } from 'react-dom';
26
26
 
27
- import { type ThemedClassName, ListItem } from '@dxos/react-ui';
27
+ import { ListItem, type ThemedClassName } from '@dxos/react-ui';
28
28
  import { resizeAttributes, sizeStyle } from '@dxos/react-ui-dnd';
29
29
  import { mx } from '@dxos/react-ui-theme';
30
30
 
31
+ import { type StackItemData, type StackItemSize } from '../defs';
32
+ import { type ItemDragState, StackItemContext, idle, useStack, useStackItem } from '../StackContext';
33
+
31
34
  import { StackItemContent, type StackItemContentProps } from './StackItemContent';
32
35
  import { StackItemDragHandle, type StackItemDragHandleProps } from './StackItemDragHandle';
33
36
  import {
34
37
  StackItemHeading,
35
38
  StackItemHeadingLabel,
36
- type StackItemHeadingProps,
37
39
  type StackItemHeadingLabelProps,
40
+ type StackItemHeadingProps,
38
41
  StackItemHeadingStickyContent,
39
42
  } from './StackItemHeading';
40
43
  import { StackItemResizeHandle, type StackItemResizeHandleProps } from './StackItemResizeHandle';
41
44
  import {
42
45
  StackItemSigil,
43
- type StackItemSigilProps,
44
46
  type StackItemSigilAction,
45
- type StackItemSigilButtonProps,
46
47
  StackItemSigilButton,
48
+ type StackItemSigilButtonProps,
49
+ type StackItemSigilProps,
47
50
  } from './StackItemSigil';
48
- import { useStack, StackItemContext, idle, type ItemDragState, useStackItem } from '../StackContext';
49
- import { type StackItemSize, type StackItemData } from '../defs';
50
51
 
51
52
  // NOTE: 48rem fills the screen on a MacbookPro with the sidebars closed.
52
53
  export const DEFAULT_HORIZONTAL_SIZE = 48 satisfies StackItemSize;
@@ -62,7 +63,7 @@ type StackItemRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {
62
63
  onSizeChange?: (nextSize: StackItemSize) => void;
63
64
  role?: 'article' | 'section';
64
65
  disableRearrange?: boolean;
65
- focusIndicatorVariant?: 'over-all' | 'group';
66
+ focusIndicatorVariant?: 'over-all' | 'group' | 'over-all-always' | 'group-always';
66
67
  };
67
68
 
68
69
  const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
@@ -89,7 +90,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
89
90
  const [closestEdge, setEdge] = useState<Edge | null>(null);
90
91
  const [sourceId, setSourceId] = useState<string | null>(null);
91
92
  const [dragState, setDragState] = useState<ItemDragState>(idle);
92
- const { orientation, rail, onRearrange } = useStack();
93
+ const { orientation, rail, onRearrange, size: stackSize, stackId } = useStack();
93
94
  const [size = orientation === 'horizontal' ? DEFAULT_HORIZONTAL_SIZE : DEFAULT_VERTICAL_SIZE, setInternalSize] =
94
95
  useState(propsSize);
95
96
 
@@ -231,18 +232,25 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
231
232
  'group/stack-item grid relative',
232
233
  focusIndicatorVariant === 'over-all'
233
234
  ? 'dx-focus-ring-inset-over-all'
234
- : orientation === 'horizontal'
235
- ? 'dx-focus-ring-group-x'
236
- : 'dx-focus-ring-group-y',
235
+ : focusIndicatorVariant === 'over-all-always'
236
+ ? 'dx-focus-ring-inset-over-all-always'
237
+ : orientation === 'horizontal'
238
+ ? focusIndicatorVariant === 'group-always'
239
+ ? 'dx-focus-ring-group-x-always'
240
+ : 'dx-focus-ring-group-x'
241
+ : focusIndicatorVariant === 'group-always'
242
+ ? 'dx-focus-ring-group-y-always'
243
+ : 'dx-focus-ring-group-y',
237
244
  orientation === 'horizontal' ? 'grid-rows-subgrid' : 'grid-cols-subgrid',
238
245
  rail && (orientation === 'horizontal' ? 'row-span-2' : 'col-span-2'),
239
246
  role === 'section' && orientation !== 'horizontal' && 'border-be border-subduedSeparator',
240
247
  classNames,
241
248
  )}
242
- data-dx-stack-item
249
+ data-dx-stack-item={stackId}
250
+ data-dx-item-id={item.id}
243
251
  {...resizeAttributes}
244
252
  style={{
245
- ...sizeStyle(size, orientation),
253
+ ...(stackSize !== 'split' && sizeStyle(size, orientation)),
246
254
  ...(Number.isFinite(order) && {
247
255
  [orientation === 'horizontal' ? 'gridColumn' : 'gridRow']: `${order}`,
248
256
  }),
@@ -54,6 +54,7 @@ export const StackItemContent = forwardRef<HTMLDivElement, StackItemContentProps
54
54
  },
55
55
  [toolbar, statusbar, layoutManaged],
56
56
  );
57
+
57
58
  return (
58
59
  <div
59
60
  role='none'
@@ -5,14 +5,14 @@
5
5
  import { useFocusableGroup } from '@fluentui/react-tabster';
6
6
  import { Slot } from '@radix-ui/react-slot';
7
7
  import React, {
8
- type ComponentPropsWithoutRef,
9
8
  type ComponentPropsWithRef,
10
- forwardRef,
9
+ type ComponentPropsWithoutRef,
11
10
  type PropsWithChildren,
11
+ forwardRef,
12
12
  } from 'react';
13
13
 
14
14
  import { type ThemedClassName } from '@dxos/react-ui';
15
- import { useAttention, type AttendableId, type Related } from '@dxos/react-ui-attention';
15
+ import { type AttendableId, type Related, useAttention } from '@dxos/react-ui-attention';
16
16
  import { mx } from '@dxos/react-ui-theme';
17
17
 
18
18
  import { useStack } from '../StackContext';
@@ -6,9 +6,10 @@ import React from 'react';
6
6
 
7
7
  import { ResizeHandle } from '@dxos/react-ui-dnd';
8
8
 
9
- import { DEFAULT_EXTRINSIC_SIZE } from './StackItem';
10
9
  import { useStack, useStackItem } from '../StackContext';
11
10
 
11
+ import { DEFAULT_EXTRINSIC_SIZE } from './StackItem';
12
+
12
13
  const MIN_WIDTH = 20;
13
14
  const MIN_HEIGHT = 3;
14
15
 
@@ -11,9 +11,10 @@ import { type AttendableId, type Related, useAttention } from '@dxos/react-ui-at
11
11
  import { descriptionText, mx } from '@dxos/react-ui-theme';
12
12
  import { getHostPlatform } from '@dxos/util';
13
13
 
14
- import { MenuSignifierHorizontal } from './MenuSignifier';
15
14
  import { translationKey } from '../../translations';
16
15
 
16
+ import { MenuSignifierHorizontal } from './MenuSignifier';
17
+
17
18
  export type KeyBinding = {
18
19
  windows?: string;
19
20
  macos?: string;
@@ -4,5 +4,6 @@
4
4
 
5
5
  export type * from './defs';
6
6
 
7
+ export * from './Image';
7
8
  export * from './Stack';
8
9
  export * from './StackItem';
@@ -2,17 +2,14 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React from 'react';
9
7
 
10
8
  import { faker } from '@dxos/random';
11
- import { withTheme } from '@dxos/storybook-utils';
9
+ import { withTheme } from '@dxos/react-ui/testing';
12
10
 
13
11
  import { Card } from './Card';
14
12
 
15
- // Set a seed for reproducible random values
16
13
  faker.seed(0);
17
14
 
18
15
  type CardStoryProps = {
@@ -23,44 +20,8 @@ type CardStoryProps = {
23
20
  showIcon: boolean;
24
21
  };
25
22
 
26
- const meta: Meta<CardStoryProps> = {
27
- title: 'ui/react-ui-stack/Card',
28
- decorators: [withTheme],
29
- argTypes: {
30
- title: {
31
- control: 'text',
32
- description: 'Card title',
33
- },
34
- description: {
35
- control: 'text',
36
- description: 'Card description',
37
- },
38
- image: {
39
- control: 'text',
40
- description: 'URL for the poster image',
41
- },
42
- showImage: {
43
- control: 'boolean',
44
- description: 'Whether to show the image',
45
- },
46
- showIcon: {
47
- control: 'boolean',
48
- description: 'Whether to show an icon (when image is not shown)',
49
- },
50
- },
51
- args: {
52
- title: faker.commerce.productName(),
53
- description: faker.lorem.paragraph(),
54
- image: faker.image.url(),
55
- showImage: true,
56
- showIcon: true,
57
- },
58
- };
59
-
60
- export default meta;
61
-
62
- export const Default: StoryObj<CardStoryProps> = {
63
- render: ({ title, description, image, showImage, showIcon }: CardStoryProps) => (
23
+ const DefaultStory = ({ title, description, image, showImage, showIcon }: CardStoryProps) => {
24
+ return (
64
25
  <div className='max-is-md'>
65
26
  <Card.StaticRoot>
66
27
  <Card.Toolbar>
@@ -74,5 +35,30 @@ export const Default: StoryObj<CardStoryProps> = {
74
35
  {description && <Card.Text classNames='line-clamp-2'>{description}</Card.Text>}
75
36
  </Card.StaticRoot>
76
37
  </div>
77
- ),
38
+ );
39
+ };
40
+
41
+ const meta = {
42
+ title: 'ui/react-ui-stack/Card',
43
+ render: DefaultStory,
44
+ decorators: [withTheme],
45
+ parameters: {
46
+ layout: 'centered',
47
+ },
48
+ } satisfies Meta<typeof DefaultStory>;
49
+
50
+ export default meta;
51
+
52
+ type Story = StoryObj<typeof meta>;
53
+
54
+ const image = faker.image.url();
55
+
56
+ export const Default: Story = {
57
+ args: {
58
+ title: faker.commerce.productName(),
59
+ description: faker.lorem.paragraph(),
60
+ image,
61
+ showImage: true,
62
+ showIcon: true,
63
+ },
78
64
  };
@@ -5,20 +5,21 @@
5
5
  import { Primitive } from '@radix-ui/react-primitive';
6
6
  import { Slot } from '@radix-ui/react-slot';
7
7
  import React, {
8
- type ComponentPropsWithoutRef,
9
8
  type ComponentPropsWithRef,
9
+ type ComponentPropsWithoutRef,
10
10
  type FC,
11
- forwardRef,
12
11
  type PropsWithChildren,
12
+ forwardRef,
13
13
  } from 'react';
14
14
 
15
15
  import { Icon, IconButton, type ThemedClassName, Toolbar, type ToolbarRootProps, useTranslation } from '@dxos/react-ui';
16
16
  import { hoverableControls, mx } from '@dxos/react-ui-theme';
17
17
 
18
- import { cardChrome, cardRoot, cardHeading, cardText, cardSpacing } from './fragments';
19
- import { StackItem } from '../../components';
18
+ import { Image, StackItem } from '../../components';
20
19
  import { translationKey } from '../../translations';
21
20
 
21
+ import { cardChrome, cardHeading, cardRoot, cardSpacing, cardText } from './fragments';
22
+
22
23
  type SharedCardProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> & { asChild?: boolean };
23
24
 
24
25
  const CardStaticRoot = forwardRef<HTMLDivElement, SharedCardProps>(
@@ -62,7 +63,7 @@ const CardSurfaceRoot = ({
62
63
  return (
63
64
  <CardStaticRoot
64
65
  classNames={[
65
- role === 'card--transclusion' && 'mlb-[1em]',
66
+ role === 'card--transclusion' && 'mlb-1',
66
67
  role === 'card--transclusion' && hoverableControls,
67
68
  classNames,
68
69
  ]}
@@ -125,15 +126,14 @@ type CardPosterProps = {
125
126
  const CardPoster = (props: CardPosterProps) => {
126
127
  const aspect = props.aspect === 'auto' ? 'aspect-auto' : 'aspect-video';
127
128
  if (props.image) {
128
- return (
129
- <img className={`dx-card__poster ${aspect} object-cover is-full bs-auto`} src={props.image} alt={props.alt} />
130
- );
129
+ return <Image classNames={[`dx-card__poster is-full __bs-auto`, aspect]} src={props.image} alt={props.alt} />;
131
130
  }
131
+
132
132
  if (props.icon) {
133
133
  return (
134
134
  <div
135
135
  role='image'
136
- className={`dx-card__poster grid ${aspect} place-items-center bg-inputSurface text-subdued`}
136
+ className={mx(`dx-card__poster grid place-items-center bg-inputSurface text-subdued`, aspect)}
137
137
  aria-label={props.alt}
138
138
  >
139
139
  <Icon icon={props.icon} size={10} />
@@ -156,9 +156,9 @@ const CardChrome = forwardRef<HTMLDivElement, SharedCardProps>(
156
156
  },
157
157
  );
158
158
 
159
- const CardText = forwardRef<HTMLParagraphElement, SharedCardProps>(
159
+ const CardText = forwardRef<HTMLDivElement, SharedCardProps>(
160
160
  ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
161
- const Root = asChild ? Slot : 'p';
161
+ const Root = asChild ? Slot : 'div';
162
162
  const rootProps = asChild ? { classNames: [cardText, classNames] } : { className: mx(cardText, classNames), role };
163
163
  return (
164
164
  <Root {...props} {...rootProps} ref={forwardedRef}>
@@ -6,6 +6,7 @@ export const cardRoot =
6
6
  'rounded overflow-hidden bg-cardSurface border border-separator dark:border-subduedSeparator dx-focus-ring-group-y-indicator relative min-bs-[--rail-item] group/card';
7
7
 
8
8
  export const cardSpacing = 'pli-cardSpacingInline mlb-cardSpacingBlock';
9
+ export const cardNoSpacing = 'pli-0 mlb-0';
9
10
  export const labelSpacing = 'mbs-inputSpacingBlock mbe-labelSpacingBlock';
10
11
 
11
12
  export const cardDialogContent = 'p-0 bs-content min-bs-[8rem] max-bs-full md:max-is-[32rem] overflow-hidden';
@@ -17,7 +18,7 @@ export const cardDialogSearchListRoot =
17
18
 
18
19
  export const cardText = cardSpacing;
19
20
 
20
- export const cardHeading = 'text-lg font-medium line-clamp-2';
21
+ export const cardHeading = 'text-lg font-medium line-clamp-2 grow';
21
22
 
22
23
  export const cardChrome =
23
- 'pli-[--dx-cardSpacingChrome] mlb-[--dx-cardSpacingChrome] [&_.dx-button]:text-start [&_.dx-button]:is-full';
24
+ 'pli-[--dx-cardSpacingChrome] mlb-[--dx-cardSpacingChrome] [&_.dx-button]:text-start [&_.dx-button]:is-full [&_.dx-button]:pis-[calc(var(--dx-cardSpacingInline)-var(--dx-cardSpacingChrome))]';
@@ -2,21 +2,19 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
8
6
  import { type Meta, type StoryObj } from '@storybook/react-vite';
9
- import React, { useState, useCallback } from 'react';
7
+ import React, { useCallback, useState } from 'react';
10
8
 
11
9
  import { faker } from '@dxos/random';
12
10
  import { IconButton } from '@dxos/react-ui';
13
- import { withLayout, withTheme } from '@dxos/storybook-utils';
11
+ import { withTheme } from '@dxos/react-ui/testing';
14
12
 
15
- import { CardStack } from './CardStack';
16
13
  import { StackItem } from '../../components';
17
14
  import { Card, CardDragPreview } from '../Card';
18
15
 
19
- // Set a seed for reproducible random values
16
+ import { CardStack } from './CardStack';
17
+
20
18
  faker.seed(0);
21
19
 
22
20
  type CardItem = {
@@ -130,7 +128,7 @@ const CardStackStory = () => {
130
128
  <Card.Text classNames='line-clamp-2'>{card.description}</Card.Text>
131
129
  </Card.StaticRoot>
132
130
  <StackItem.DragPreview>
133
- {({ item }) => (
131
+ {() => (
134
132
  <CardDragPreview.Root>
135
133
  <CardDragPreview.Content>
136
134
  <Card.Toolbar>
@@ -159,11 +157,14 @@ const CardStackStory = () => {
159
157
  );
160
158
  };
161
159
 
162
- const meta: Meta<typeof CardStackStory> = {
160
+ const meta = {
163
161
  title: 'ui/react-ui-stack/CardStack',
164
162
  component: CardStackStory,
165
- decorators: [withTheme, withLayout({ fullscreen: true })],
166
- };
163
+ decorators: [withTheme],
164
+ parameters: {
165
+ layout: 'fullscreen',
166
+ },
167
+ } satisfies Meta<typeof CardStackStory>;
167
168
 
168
169
  export default meta;
169
170
 
@@ -8,7 +8,7 @@ import React, { type ComponentPropsWithoutRef, forwardRef } from 'react';
8
8
  import type { ThemedClassName } from '@dxos/react-ui';
9
9
  import { mx } from '@dxos/react-ui-theme';
10
10
 
11
- import { railGridHorizontalContainFitContent, Stack, type StackProps } from '../../components';
11
+ import { Stack, type StackProps, railGridHorizontalContainFitContent } from '../../components';
12
12
  import { Card } from '../Card';
13
13
 
14
14
  type SharedCardStackProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> & { asChild?: boolean };
@@ -72,17 +72,20 @@ const CardStackFooter = forwardRef<HTMLDivElement, SharedCardStackProps>(
72
72
  },
73
73
  );
74
74
 
75
- const cardStackContent = [
76
- 'shrink min-bs-0 bg-baseSurface border border-separator rounded-md grid dx-focus-ring-group-x-indicator kanban-drop',
77
- railGridHorizontalContainFitContent,
78
- ];
75
+ const cardStackContent =
76
+ 'shrink min-bs-0 bg-baseSurface border border-separator rounded-md grid dx-focus-ring-group-x-indicator kanban-drop';
79
77
 
80
- const CardStackContent = forwardRef<HTMLDivElement, SharedCardStackProps>(
81
- ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
78
+ type CardStackContentProps = SharedCardStackProps & {
79
+ footer?: boolean;
80
+ };
81
+
82
+ const CardStackContent = forwardRef<HTMLDivElement, CardStackContentProps>(
83
+ ({ children, classNames, asChild, role = 'none', footer = true, ...props }, forwardedRef) => {
82
84
  const Root = asChild ? Slot : 'div';
85
+ const baseClassNames = footer ? [cardStackContent, railGridHorizontalContainFitContent] : [cardStackContent];
83
86
  const rootProps = asChild
84
- ? { classNames: [...cardStackContent, classNames] }
85
- : { className: mx(...cardStackContent, classNames), role };
87
+ ? { classNames: [...baseClassNames, classNames] }
88
+ : { className: mx(...baseClassNames, classNames), role };
86
89
  return (
87
90
  <Root {...props} {...rootProps} data-scroll-separator='false' ref={forwardedRef}>
88
91
  {children}
@@ -8,7 +8,7 @@ import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-sc
8
8
  import { attachClosestEdge, extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
9
9
  import { useLayoutEffect, useState } from 'react';
10
10
 
11
- import { type StackItemRearrangeHandler, type StackItemData, type Orientation } from '../components';
11
+ import { type Orientation, type StackItemData, type StackItemRearrangeHandler } from '../components';
12
12
 
13
13
  /**
14
14
  * Hook to handle drag and drop functionality for Stack components.
@@ -16,18 +16,21 @@ export const CardContainer = ({
16
16
  switch (role) {
17
17
  case 'card--popover':
18
18
  return <PopoverCardContainer icon={icon}>{children}</PopoverCardContainer>;
19
- case 'card--intrinsic':
20
- return (
21
- <IntrinsicCardContainer>
22
- <Card.StaticRoot>{children}</Card.StaticRoot>
23
- </IntrinsicCardContainer>
24
- );
19
+
25
20
  case 'card--extrinsic':
26
21
  return (
27
22
  <ExtrinsicCardContainer>
28
23
  <Card.StaticRoot>{children}</Card.StaticRoot>
29
24
  </ExtrinsicCardContainer>
30
25
  );
26
+
27
+ case 'card--intrinsic':
28
+ return (
29
+ <IntrinsicCardContainer>
30
+ <Card.StaticRoot>{children}</Card.StaticRoot>
31
+ </IntrinsicCardContainer>
32
+ );
33
+
31
34
  default:
32
35
  return <Card.StaticRoot>{children}</Card.StaticRoot>;
33
36
  }