@dxos/react-ui 0.8.4-main.69d29f4 → 0.8.4-main.6fa680abb7
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/lib/browser/{chunk-CEKVHJ27.mjs → chunk-2FKSMWNY.mjs} +117 -117
- package/dist/lib/browser/chunk-2FKSMWNY.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +2804 -1957
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +56 -32
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node-esm/{chunk-2NHEX4AD.mjs → chunk-ZNBLTSHI.mjs} +117 -117
- package/dist/lib/node-esm/chunk-ZNBLTSHI.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +2804 -1957
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +56 -32
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
- package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
- package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
- package/dist/types/src/components/Button/Button.d.ts.map +1 -1
- package/dist/types/src/components/Card/Card.d.ts +107 -0
- package/dist/types/src/components/Card/Card.d.ts.map +1 -0
- package/dist/types/src/components/Card/Card.stories.d.ts +21 -0
- package/dist/types/src/components/Card/Card.stories.d.ts.map +1 -0
- package/dist/types/src/components/Card/index.d.ts +2 -0
- package/dist/types/src/components/Card/index.d.ts.map +1 -0
- package/dist/types/src/components/Dialog/AlertDialog.d.ts +12 -3
- package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -1
- package/dist/types/src/components/Dialog/AlertDialog.stories.d.ts.map +1 -1
- package/dist/types/src/components/Dialog/Dialog.d.ts +11 -4
- package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
- package/dist/types/src/components/Dialog/Dialog.stories.d.ts +3 -6
- package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
- package/dist/types/src/components/ErrorFallback/ErrorFallback.d.ts +11 -0
- package/dist/types/src/components/ErrorFallback/ErrorFallback.d.ts.map +1 -0
- package/dist/types/src/components/ErrorFallback/ErrorFallback.stories.d.ts +7 -0
- package/dist/types/src/components/ErrorFallback/ErrorFallback.stories.d.ts.map +1 -0
- package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts +8 -0
- package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts.map +1 -0
- package/dist/types/src/components/ErrorFallback/ThrowError.d.ts +9 -0
- package/dist/types/src/components/ErrorFallback/ThrowError.d.ts.map +1 -0
- package/dist/types/src/components/ErrorFallback/index.d.ts +5 -0
- package/dist/types/src/components/ErrorFallback/index.d.ts.map +1 -0
- package/dist/types/src/components/Image/Image.d.ts +14 -0
- package/dist/types/src/components/Image/Image.d.ts.map +1 -0
- package/dist/types/src/components/Image/Image.stories.d.ts +33 -0
- package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -0
- package/dist/types/src/components/Image/index.d.ts +2 -0
- package/dist/types/src/components/Image/index.d.ts.map +1 -0
- package/dist/types/src/components/Input/Input.d.ts +2 -5
- package/dist/types/src/components/Input/Input.d.ts.map +1 -1
- package/dist/types/src/components/Input/Input.stories.d.ts +7 -7
- package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
- package/dist/types/src/components/List/List.d.ts.map +1 -1
- package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
- package/dist/types/src/components/List/Treegrid.d.ts.map +1 -1
- package/dist/types/src/components/Main/Main.d.ts +9 -10
- package/dist/types/src/components/Main/Main.d.ts.map +1 -1
- package/dist/types/src/components/Main/Main.stories.d.ts +0 -3
- package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
- package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -1
- package/dist/types/src/components/Message/Message.d.ts.map +1 -1
- package/dist/types/src/components/Message/Message.stories.d.ts +2 -3
- package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
- package/dist/types/src/components/Popover/Popover.d.ts +1 -0
- package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
- package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +21 -26
- package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
- package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +41 -9
- package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
- package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
- package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +6 -1
- package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/Select/Select.d.ts.map +1 -1
- package/dist/types/src/components/Skeleton/Skeleton.d.ts +12 -0
- package/dist/types/src/components/Skeleton/Skeleton.d.ts.map +1 -0
- package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts +17 -0
- package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts.map +1 -0
- package/dist/types/src/components/Skeleton/index.d.ts +2 -0
- package/dist/types/src/components/Skeleton/index.d.ts.map +1 -0
- package/dist/types/src/components/Splitter/Splitter.d.ts +32 -0
- package/dist/types/src/components/Splitter/Splitter.d.ts.map +1 -0
- package/dist/types/src/components/Splitter/Splitter.stories.d.ts +7 -0
- package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -0
- package/dist/types/src/components/Splitter/index.d.ts +2 -0
- package/dist/types/src/components/Splitter/index.d.ts.map +1 -0
- package/dist/types/src/components/Status/Status.stories.d.ts +4 -2
- package/dist/types/src/components/Status/Status.stories.d.ts.map +1 -1
- package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
- package/dist/types/src/components/Tag/Tag.stories.d.ts +0 -5
- package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
- package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +1 -0
- package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
- package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts +12 -0
- package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toast/Toast.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +33 -7
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +8 -4
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/exemplars/generics.stories.d.ts +18 -0
- package/dist/types/src/exemplars/generics.stories.d.ts.map +1 -0
- package/dist/types/src/exemplars/slot.stories.d.ts +14 -0
- package/dist/types/src/exemplars/slot.stories.d.ts.map +1 -0
- package/dist/types/src/exemplars/tabster.stories.d.ts +8 -0
- package/dist/types/src/exemplars/tabster.stories.d.ts.map +1 -0
- package/dist/types/src/exemplars/virtualizer.stories.d.ts +11 -0
- package/dist/types/src/exemplars/virtualizer.stories.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
- package/dist/types/src/primitives/Column/Column.d.ts +26 -0
- package/dist/types/src/primitives/Column/Column.d.ts.map +1 -0
- package/dist/types/src/primitives/Column/Column.stories.d.ts +6 -0
- package/dist/types/src/primitives/Column/Column.stories.d.ts.map +1 -0
- package/dist/types/src/primitives/Column/index.d.ts +2 -0
- package/dist/types/src/primitives/Column/index.d.ts.map +1 -0
- package/dist/types/src/primitives/Container/Container.d.ts +8 -0
- package/dist/types/src/primitives/Container/Container.d.ts.map +1 -0
- package/dist/types/src/primitives/Container/Container.stories.d.ts +6 -0
- package/dist/types/src/primitives/Container/Container.stories.d.ts.map +1 -0
- package/dist/types/src/primitives/Container/index.d.ts +2 -0
- package/dist/types/src/primitives/Container/index.d.ts.map +1 -0
- package/dist/types/src/primitives/Flex/Flex.d.ts +13 -0
- package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -0
- package/dist/types/src/primitives/Flex/Flex.stories.d.ts +8 -0
- package/dist/types/src/primitives/Flex/Flex.stories.d.ts.map +1 -0
- package/dist/types/src/primitives/Flex/index.d.ts +2 -0
- package/dist/types/src/primitives/Flex/index.d.ts.map +1 -0
- package/dist/types/src/primitives/Grid/Grid.d.ts +15 -0
- package/dist/types/src/primitives/Grid/Grid.d.ts.map +1 -0
- package/dist/types/src/primitives/Grid/Grid.stories.d.ts +8 -0
- package/dist/types/src/primitives/Grid/Grid.stories.d.ts.map +1 -0
- package/dist/types/src/primitives/Grid/index.d.ts +2 -0
- package/dist/types/src/primitives/Grid/index.d.ts.map +1 -0
- package/dist/types/src/primitives/Panel/Panel.d.ts +26 -0
- package/dist/types/src/primitives/Panel/Panel.d.ts.map +1 -0
- package/dist/types/src/primitives/Panel/Panel.stories.d.ts +6 -0
- package/dist/types/src/primitives/Panel/Panel.stories.d.ts.map +1 -0
- package/dist/types/src/primitives/Panel/index.d.ts +2 -0
- package/dist/types/src/primitives/Panel/index.d.ts.map +1 -0
- package/dist/types/src/primitives/index.d.ts +6 -0
- package/dist/types/src/primitives/index.d.ts.map +1 -0
- package/dist/types/src/testing/Loading.d.ts +9 -0
- package/dist/types/src/testing/Loading.d.ts.map +1 -0
- package/dist/types/src/testing/decorators/withLayout.d.ts +1 -1
- package/dist/types/src/testing/decorators/withLayout.d.ts.map +1 -1
- package/dist/types/src/testing/decorators/withLayoutVariants.d.ts.map +1 -1
- package/dist/types/src/testing/decorators/withTheme.d.ts +3 -2
- package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +11 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +25 -21
- package/src/components/Avatars/Avatar.stories.tsx +5 -6
- package/src/components/Avatars/Avatar.tsx +5 -12
- package/src/components/Avatars/AvatarGroup.stories.tsx +2 -2
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +3 -3
- package/src/components/Breadcrumb/Breadcrumb.tsx +11 -37
- package/src/components/Button/Button.stories.tsx +3 -3
- package/src/components/Button/Button.tsx +6 -12
- package/src/components/Button/IconButton.stories.tsx +4 -4
- package/src/components/Button/IconButton.tsx +1 -1
- package/src/components/Button/Toggle.stories.tsx +2 -2
- package/src/components/Button/ToggleGroup.stories.tsx +2 -2
- package/src/components/Card/Card.stories.tsx +151 -0
- package/src/components/Card/Card.tsx +347 -0
- package/src/components/Card/index.ts +5 -0
- package/src/components/Clipboard/CopyButton.tsx +3 -3
- package/src/components/Dialog/AlertDialog.stories.tsx +15 -15
- package/src/components/Dialog/AlertDialog.tsx +116 -16
- package/src/components/Dialog/Dialog.stories.tsx +40 -15
- package/src/components/Dialog/Dialog.tsx +75 -45
- package/src/components/ErrorFallback/ErrorFallback.stories.tsx +50 -0
- package/src/components/ErrorFallback/ErrorFallback.tsx +70 -0
- package/src/components/ErrorFallback/ErrorStack.tsx +80 -0
- package/src/components/ErrorFallback/ThrowError.tsx +37 -0
- package/src/components/ErrorFallback/index.ts +9 -0
- package/src/components/Icon/Icon.stories.tsx +2 -2
- package/src/components/Icon/Icon.tsx +1 -1
- package/src/components/Image/Image.stories.tsx +86 -0
- package/src/components/Image/Image.tsx +223 -0
- package/src/components/Image/index.ts +5 -0
- package/src/components/Input/Input.stories.tsx +20 -39
- package/src/components/Input/Input.tsx +20 -65
- package/src/components/Link/Link.stories.tsx +2 -2
- package/src/components/Link/Link.tsx +2 -2
- package/src/components/List/List.stories.tsx +15 -22
- package/src/components/List/List.tsx +11 -16
- package/src/components/List/ListDropIndicator.tsx +7 -7
- package/src/components/List/Tree.stories.tsx +4 -4
- package/src/components/List/TreeDropIndicator.tsx +6 -6
- package/src/components/List/Treegrid.stories.tsx +3 -3
- package/src/components/List/Treegrid.tsx +10 -15
- package/src/components/Main/Main.stories.tsx +41 -23
- package/src/components/Main/Main.tsx +138 -81
- package/src/components/Menu/ContextMenu.stories.tsx +2 -2
- package/src/components/Menu/ContextMenu.tsx +9 -33
- package/src/components/Menu/DropdownMenu.stories.tsx +2 -2
- package/src/components/Menu/DropdownMenu.tsx +10 -10
- package/src/components/Message/Message.stories.tsx +25 -10
- package/src/components/Message/Message.tsx +17 -29
- package/src/components/Popover/Popover.stories.tsx +4 -4
- package/src/components/Popover/Popover.tsx +23 -20
- package/src/components/ScrollArea/ScrollArea.stories.tsx +152 -76
- package/src/components/ScrollArea/ScrollArea.tsx +72 -116
- package/src/components/ScrollArea/index.ts +1 -1
- package/src/components/ScrollContainer/ScrollContainer.stories.tsx +41 -22
- package/src/components/ScrollContainer/ScrollContainer.tsx +18 -13
- package/src/components/Select/Select.stories.tsx +2 -2
- package/src/components/Select/Select.tsx +11 -27
- package/src/components/Separator/Separator.tsx +1 -1
- package/src/components/Skeleton/Skeleton.stories.tsx +52 -0
- package/src/components/Skeleton/Skeleton.tsx +26 -0
- package/src/components/Skeleton/index.ts +5 -0
- package/src/components/Splitter/Splitter.stories.tsx +83 -0
- package/src/components/Splitter/Splitter.tsx +126 -0
- package/src/components/Splitter/index.ts +5 -0
- package/src/components/Status/Status.stories.tsx +21 -17
- package/src/components/Status/Status.tsx +2 -2
- package/src/components/Tag/Tag.stories.tsx +4 -9
- package/src/components/Tag/Tag.tsx +2 -7
- package/src/components/ThemeProvider/ThemeProvider.stories.tsx +32 -0
- package/src/components/ThemeProvider/ThemeProvider.tsx +4 -3
- package/src/components/Toast/Toast.stories.tsx +2 -2
- package/src/components/Toast/Toast.tsx +10 -14
- package/src/components/Toolbar/Toolbar.stories.tsx +2 -2
- package/src/components/Toolbar/Toolbar.tsx +174 -12
- package/src/components/Tooltip/Tooltip.stories.tsx +15 -13
- package/src/components/Tooltip/Tooltip.tsx +3 -2
- package/src/components/index.ts +9 -5
- package/src/exemplars/generics.stories.tsx +49 -0
- package/src/exemplars/slot.stories.tsx +107 -0
- package/src/exemplars/tabster.stories.tsx +127 -0
- package/src/exemplars/virtualizer.stories.tsx +137 -0
- package/src/index.ts +1 -0
- package/src/playground/Controls.stories.tsx +3 -10
- package/src/playground/Custom.stories.tsx +10 -10
- package/src/playground/Typography.stories.tsx +3 -3
- package/src/primitives/Column/Column.stories.tsx +78 -0
- package/src/primitives/Column/Column.tsx +134 -0
- package/src/primitives/Column/index.ts +5 -0
- package/src/primitives/Container/Container.stories.tsx +30 -0
- package/src/primitives/Container/Container.tsx +22 -0
- package/src/primitives/Container/index.ts +5 -0
- package/src/primitives/Flex/Flex.stories.tsx +58 -0
- package/src/primitives/Flex/Flex.tsx +29 -0
- package/src/primitives/Flex/index.ts +5 -0
- package/src/primitives/Grid/Grid.stories.tsx +57 -0
- package/src/primitives/Grid/Grid.tsx +35 -0
- package/src/primitives/Grid/index.ts +5 -0
- package/src/primitives/Panel/Panel.stories.tsx +67 -0
- package/src/primitives/Panel/Panel.tsx +119 -0
- package/src/primitives/Panel/index.ts +5 -0
- package/src/primitives/index.ts +9 -0
- package/src/testing/Loading.tsx +26 -0
- package/src/testing/decorators/withLayout.tsx +21 -7
- package/src/testing/decorators/withLayoutVariants.tsx +18 -21
- package/src/testing/decorators/withTheme.tsx +19 -17
- package/src/testing/index.ts +2 -0
- package/src/translations.ts +19 -0
- package/dist/lib/browser/chunk-CEKVHJ27.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2NHEX4AD.mjs.map +0 -7
- package/dist/types/src/components/AnchoredOverflow/AnchoredOverflow.d.ts +0 -15
- package/dist/types/src/components/AnchoredOverflow/AnchoredOverflow.d.ts.map +0 -1
- package/dist/types/src/components/AnchoredOverflow/index.d.ts +0 -2
- package/dist/types/src/components/AnchoredOverflow/index.d.ts.map +0 -1
- package/src/components/AnchoredOverflow/AnchoredOverflow.tsx +0 -59
- package/src/components/AnchoredOverflow/index.ts +0 -5
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta } from '@storybook/react-vite';
|
|
6
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
7
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
8
|
+
|
|
9
|
+
import { faker } from '@dxos/random';
|
|
10
|
+
import { Panel, ScrollArea, Toolbar } from '@dxos/react-ui';
|
|
11
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
12
|
+
|
|
13
|
+
faker.seed(999);
|
|
14
|
+
|
|
15
|
+
type TestItem = {
|
|
16
|
+
name: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const meta: Meta = {
|
|
20
|
+
title: 'ui/react-ui-core/exemplars/virtualizer',
|
|
21
|
+
decorators: [withLayout({ layout: 'column' }), withTheme()],
|
|
22
|
+
parameters: {
|
|
23
|
+
layout: 'fullscreen',
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default meta;
|
|
28
|
+
|
|
29
|
+
const NUM_ITEMS = 500;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* https://tanstack.com/virtual/latest/docs/introduction
|
|
33
|
+
*/
|
|
34
|
+
export const Default = {
|
|
35
|
+
render: () => {
|
|
36
|
+
const [index, setIndex] = useState(0);
|
|
37
|
+
const items = useMemo<TestItem[]>(
|
|
38
|
+
() =>
|
|
39
|
+
Array.from({ length: NUM_ITEMS }, () => ({
|
|
40
|
+
name: faker.lorem.paragraph(),
|
|
41
|
+
})),
|
|
42
|
+
[],
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const parentRef = useRef(null);
|
|
46
|
+
const [viewport, setViewport] = useState<HTMLElement | null>(null);
|
|
47
|
+
const virtualizer = useVirtualizer({
|
|
48
|
+
getScrollElement: () => viewport,
|
|
49
|
+
estimateSize: () => 40,
|
|
50
|
+
count: items.length,
|
|
51
|
+
gap: 8,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
virtualizer.scrollToIndex(index, { align: 'start' });
|
|
56
|
+
}, [virtualizer, index]);
|
|
57
|
+
|
|
58
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<Panel.Root>
|
|
62
|
+
<Panel.Toolbar asChild>
|
|
63
|
+
<ScrollToolbar items={items} index={index} setIndex={setIndex} />
|
|
64
|
+
</Panel.Toolbar>
|
|
65
|
+
<Panel.Content asChild>
|
|
66
|
+
<ScrollArea.Root orientation='vertical' margin>
|
|
67
|
+
<ScrollArea.Viewport classNames='p-2' ref={setViewport}>
|
|
68
|
+
<div
|
|
69
|
+
role='none'
|
|
70
|
+
style={{
|
|
71
|
+
position: 'relative',
|
|
72
|
+
height: virtualizer.getTotalSize(),
|
|
73
|
+
width: '100%',
|
|
74
|
+
}}
|
|
75
|
+
ref={parentRef}
|
|
76
|
+
>
|
|
77
|
+
{virtualItems.map((virtualItem) => (
|
|
78
|
+
<div
|
|
79
|
+
key={virtualItem.key}
|
|
80
|
+
role='list'
|
|
81
|
+
className='grid grid-cols-[3rem_1fr] overflow-hidden border border-separator rounded-xs'
|
|
82
|
+
style={{
|
|
83
|
+
position: 'absolute',
|
|
84
|
+
top: 0,
|
|
85
|
+
left: 0,
|
|
86
|
+
width: '100%',
|
|
87
|
+
transform: `translateY(${virtualItem.start}px)`,
|
|
88
|
+
}}
|
|
89
|
+
data-index={virtualItem.index}
|
|
90
|
+
ref={virtualizer.measureElement}
|
|
91
|
+
>
|
|
92
|
+
<div className='p-1'>{virtualItem.index + 1}</div>
|
|
93
|
+
<div className='p-1'>{items[virtualItem.index].name}</div>
|
|
94
|
+
</div>
|
|
95
|
+
))}
|
|
96
|
+
</div>
|
|
97
|
+
</ScrollArea.Viewport>
|
|
98
|
+
</ScrollArea.Root>
|
|
99
|
+
</Panel.Content>
|
|
100
|
+
</Panel.Root>
|
|
101
|
+
);
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const ScrollToolbar = ({
|
|
106
|
+
items,
|
|
107
|
+
index,
|
|
108
|
+
setIndex,
|
|
109
|
+
}: {
|
|
110
|
+
items: any[];
|
|
111
|
+
index: number;
|
|
112
|
+
setIndex: (index: number) => void;
|
|
113
|
+
}) => {
|
|
114
|
+
return (
|
|
115
|
+
<Toolbar.Root classNames='grid grid-cols-3'>
|
|
116
|
+
<div />
|
|
117
|
+
<div className='flex justify-center gap-1'>
|
|
118
|
+
<Toolbar.IconButton icon='ph--arrow-line-left--regular' iconOnly label='start' onClick={() => setIndex(0)} />
|
|
119
|
+
<Toolbar.IconButton
|
|
120
|
+
icon='ph--arrows-out-line-horizontal--regular'
|
|
121
|
+
iconOnly
|
|
122
|
+
label='random'
|
|
123
|
+
onClick={() => setIndex(Math.floor(Math.random() * items.length))}
|
|
124
|
+
/>
|
|
125
|
+
<Toolbar.IconButton
|
|
126
|
+
icon='ph--arrow-line-right--regular'
|
|
127
|
+
iconOnly
|
|
128
|
+
label='end'
|
|
129
|
+
onClick={() => setIndex(items.length - 1)}
|
|
130
|
+
/>
|
|
131
|
+
</div>
|
|
132
|
+
<div className='p-1 text-right'>
|
|
133
|
+
{index + 1}/{items.length}
|
|
134
|
+
</div>
|
|
135
|
+
</Toolbar.Root>
|
|
136
|
+
);
|
|
137
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -6,8 +6,7 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import React, { useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { Icon, Input, Select, Toggle, Toolbar } from '../components';
|
|
9
|
-
import { withTheme } from '../testing';
|
|
10
|
-
import { withLayoutVariants } from '../testing';
|
|
9
|
+
import { withLayoutVariants, withTheme } from '../testing';
|
|
11
10
|
|
|
12
11
|
const DefaultStory = () => {
|
|
13
12
|
const [checked, setChecked] = useState<boolean>(false);
|
|
@@ -32,9 +31,6 @@ const DefaultStory = () => {
|
|
|
32
31
|
</Select.Content>
|
|
33
32
|
</Select.Portal>
|
|
34
33
|
</Select.Root>
|
|
35
|
-
{/* TODO(burdon): Highlight is cyan. */}
|
|
36
|
-
{/* TODO(burdon): Show vertical divider by default. */}
|
|
37
|
-
{/* TODO(burdon): Icon sizes should adapt to density. */}
|
|
38
34
|
<Toolbar.ToggleGroup type='multiple'>
|
|
39
35
|
<Toolbar.ToggleGroupItem value='a'>
|
|
40
36
|
<Icon icon='ph--text-b--regular' />
|
|
@@ -46,7 +42,6 @@ const DefaultStory = () => {
|
|
|
46
42
|
<Icon icon='ph--text-underline--regular' />
|
|
47
43
|
</Toolbar.ToggleGroupItem>
|
|
48
44
|
</Toolbar.ToggleGroup>
|
|
49
|
-
{/* TODO(burdon): Highlight isn't shown. */}
|
|
50
45
|
<Toolbar.ToggleGroup type='single' defaultValue='a'>
|
|
51
46
|
<Toolbar.ToggleGroupItem value='a'>
|
|
52
47
|
<Icon icon='ph--file-ts--regular' />
|
|
@@ -60,11 +55,9 @@ const DefaultStory = () => {
|
|
|
60
55
|
<Icon icon='ph--bug--regular' />
|
|
61
56
|
</Toggle>
|
|
62
57
|
</Toolbar.Button>
|
|
63
|
-
{/* TODO(burdon): Should not be 'is-full' by default. */}
|
|
64
58
|
<Input.Root>
|
|
65
59
|
<Input.TextInput placeholder='Enter text...' />
|
|
66
60
|
</Input.Root>
|
|
67
|
-
{/* TODO(burdon): Checkbox collapsed. */}
|
|
68
61
|
<Input.Root>
|
|
69
62
|
<Input.Checkbox checked={checked} onCheckedChange={(value) => setChecked(!!value)} />
|
|
70
63
|
<Input.Label>Checkbox</Input.Label>
|
|
@@ -82,9 +75,9 @@ const DefaultStory = () => {
|
|
|
82
75
|
};
|
|
83
76
|
|
|
84
77
|
const meta = {
|
|
85
|
-
title: 'ui/react-ui-core/
|
|
78
|
+
title: 'ui/react-ui-core/playground/Controls',
|
|
86
79
|
render: DefaultStory,
|
|
87
|
-
decorators: [withTheme, withLayoutVariants()],
|
|
80
|
+
decorators: [withTheme(), withLayoutVariants()],
|
|
88
81
|
} satisfies Meta<typeof Icon>;
|
|
89
82
|
|
|
90
83
|
export default meta;
|
|
@@ -30,7 +30,7 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
|
|
|
30
30
|
iconOnly
|
|
31
31
|
size={7}
|
|
32
32
|
density='coarse'
|
|
33
|
-
classNames='
|
|
33
|
+
classNames='px-1.5'
|
|
34
34
|
/>
|
|
35
35
|
</div>
|
|
36
36
|
</div>
|
|
@@ -43,7 +43,7 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
|
|
|
43
43
|
</Button>
|
|
44
44
|
</div>
|
|
45
45
|
<div className='flex justify-center'>
|
|
46
|
-
<IconButton {...args} label='Test' icon='ph--atom--regular' density='fine' classNames='
|
|
46
|
+
<IconButton {...args} label='Test' icon='ph--atom--regular' density='fine' classNames='px-2' />
|
|
47
47
|
</div>
|
|
48
48
|
<div className='flex justify-center'>
|
|
49
49
|
<IconButton
|
|
@@ -52,7 +52,7 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
|
|
|
52
52
|
icon='ph--atom--regular'
|
|
53
53
|
iconOnly
|
|
54
54
|
density='fine'
|
|
55
|
-
classNames='
|
|
55
|
+
classNames='py-1 px-1.5'
|
|
56
56
|
/>
|
|
57
57
|
</div>
|
|
58
58
|
</div>
|
|
@@ -60,7 +60,7 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
|
|
|
60
60
|
{/* Small */}
|
|
61
61
|
<div className='grid grid-cols-3 gap-4'>
|
|
62
62
|
<div className='flex justify-center'>
|
|
63
|
-
<Button {...args} density='fine' classNames={'!h-[24px] !text-[14px] p-0
|
|
63
|
+
<Button {...args} density='fine' classNames={'!h-[24px] !text-[14px] p-0 px-1.5 min-h-0'}>
|
|
64
64
|
{children}
|
|
65
65
|
</Button>
|
|
66
66
|
</div>
|
|
@@ -71,7 +71,7 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
|
|
|
71
71
|
icon='ph--atom--regular'
|
|
72
72
|
density='fine'
|
|
73
73
|
size={4}
|
|
74
|
-
classNames={'!h-[24px] !text-[14px] p-1 min-
|
|
74
|
+
classNames={'!h-[24px] !text-[14px] p-1 min-h-0 gap-0.5'}
|
|
75
75
|
/>
|
|
76
76
|
</div>
|
|
77
77
|
<div className='flex justify-center'>
|
|
@@ -82,21 +82,21 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
|
|
|
82
82
|
iconOnly
|
|
83
83
|
density='fine'
|
|
84
84
|
size={4}
|
|
85
|
-
classNames={'!h-[24px] !text-[14px] p-1 min-
|
|
85
|
+
classNames={'!h-[24px] !text-[14px] p-1 min-h-0'}
|
|
86
86
|
/>
|
|
87
87
|
</div>
|
|
88
88
|
</div>
|
|
89
89
|
|
|
90
90
|
{/* TODO(burdon): Full variant with max width. */}
|
|
91
91
|
<div className='flex justify-center'>
|
|
92
|
-
<Button classNames='
|
|
92
|
+
<Button classNames='w-full max-w-[15rem] rounded-sm' variant='default'>
|
|
93
93
|
Test
|
|
94
94
|
</Button>
|
|
95
95
|
</div>
|
|
96
96
|
<div className='flex justify-center'>
|
|
97
97
|
{/* TODO(burdon): Option to have button on RHS. Default size for icon should be 5 for this (medium) density. */}
|
|
98
98
|
<IconButton
|
|
99
|
-
classNames='
|
|
99
|
+
classNames='w-full max-w-[15rem] rounded-sm'
|
|
100
100
|
variant='primary'
|
|
101
101
|
icon='ph--arrows-clockwise--regular'
|
|
102
102
|
label='Test'
|
|
@@ -108,10 +108,10 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
|
|
|
108
108
|
};
|
|
109
109
|
|
|
110
110
|
const meta = {
|
|
111
|
-
title: 'ui/react-ui-core/
|
|
111
|
+
title: 'ui/react-ui-core/playground/Custom',
|
|
112
112
|
component: Button,
|
|
113
113
|
render: DefaultStory,
|
|
114
|
-
decorators: [withTheme],
|
|
114
|
+
decorators: [withTheme()],
|
|
115
115
|
parameters: {
|
|
116
116
|
layout: 'centered',
|
|
117
117
|
},
|
|
@@ -9,7 +9,7 @@ import { withTheme } from '../testing';
|
|
|
9
9
|
|
|
10
10
|
const DefaultStory = () => {
|
|
11
11
|
return (
|
|
12
|
-
<div className='
|
|
12
|
+
<div className='mx-auto p-8 max-w-[60rem] space-b-4'>
|
|
13
13
|
<h1 className='text-4xl font-medium'>
|
|
14
14
|
Việc <span className='italic'>thừa</span> nhận{' '}
|
|
15
15
|
<span className='font-mono bg-neutral-500/10'>
|
|
@@ -43,9 +43,9 @@ const DefaultStory = () => {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
const meta = {
|
|
46
|
-
title: 'ui/react-ui-core/
|
|
46
|
+
title: 'ui/react-ui-core/playground/Typography',
|
|
47
47
|
render: DefaultStory,
|
|
48
|
-
decorators: [withTheme],
|
|
48
|
+
decorators: [withTheme()],
|
|
49
49
|
} satisfies Meta<typeof DefaultStory>;
|
|
50
50
|
|
|
51
51
|
export default meta;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { Input, ScrollArea } from '../../components';
|
|
9
|
+
import { withLayout, withTheme } from '../../testing';
|
|
10
|
+
import { Flex } from '../Flex';
|
|
11
|
+
|
|
12
|
+
import { Column } from './Column';
|
|
13
|
+
|
|
14
|
+
const List = () => {
|
|
15
|
+
return (
|
|
16
|
+
<ScrollArea.Root margin role='list'>
|
|
17
|
+
<ScrollArea.Viewport>
|
|
18
|
+
{Array.from({ length: 100 }).map((_, i) => (
|
|
19
|
+
<div key={i} role='listitem' className='p-1 hover:bg-hover-surface'>
|
|
20
|
+
Item {i}
|
|
21
|
+
</div>
|
|
22
|
+
))}
|
|
23
|
+
</ScrollArea.Viewport>
|
|
24
|
+
</ScrollArea.Root>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const DefaultStory = () => {
|
|
29
|
+
return (
|
|
30
|
+
<Column.Root className='h-full overflow-hidden' gutter='md'>
|
|
31
|
+
<Column.Segment asChild>
|
|
32
|
+
<h1 className='p-1 bg-blue-500 text-black'>Header</h1>
|
|
33
|
+
</Column.Segment>
|
|
34
|
+
|
|
35
|
+
<Column.Row>
|
|
36
|
+
<div className='p-1 bg-blue-500'>A</div>
|
|
37
|
+
<div className='p-1 bg-red-500'>B</div>
|
|
38
|
+
<div className='p-1 bg-blue-500'>C</div>
|
|
39
|
+
</Column.Row>
|
|
40
|
+
|
|
41
|
+
<Column.Segment asChild>
|
|
42
|
+
<div className='py-2'>
|
|
43
|
+
<Input.Root>
|
|
44
|
+
<Input.TextInput placeholder='Search' />
|
|
45
|
+
</Input.Root>
|
|
46
|
+
</div>
|
|
47
|
+
</Column.Segment>
|
|
48
|
+
|
|
49
|
+
<List />
|
|
50
|
+
|
|
51
|
+
<Column.Segment asChild>
|
|
52
|
+
<Flex column>
|
|
53
|
+
<h1 className='p-1 bg-red-500 text-black'>Section with overflow</h1>
|
|
54
|
+
<pre className='p-1 text-xs text-subdued overflow-auto'>{new Error().stack}</pre>
|
|
55
|
+
</Flex>
|
|
56
|
+
</Column.Segment>
|
|
57
|
+
|
|
58
|
+
<Column.Segment asChild>
|
|
59
|
+
<div className='p-1 bg-green-500 text-black'>Footer</div>
|
|
60
|
+
</Column.Segment>
|
|
61
|
+
</Column.Root>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const meta: Meta = {
|
|
66
|
+
title: 'ui/react-ui-core/primitives/Column',
|
|
67
|
+
render: DefaultStory,
|
|
68
|
+
decorators: [withTheme(), withLayout({ layout: 'column', classNames: 'w-[25rem]' })],
|
|
69
|
+
parameters: {
|
|
70
|
+
layout: 'fullscreen',
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default meta;
|
|
75
|
+
|
|
76
|
+
type Story = StoryObj<typeof meta>;
|
|
77
|
+
|
|
78
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Primitive } from '@radix-ui/react-primitive';
|
|
6
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
7
|
+
import React, { type CSSProperties, forwardRef } from 'react';
|
|
8
|
+
|
|
9
|
+
import { composableProps } from '@dxos/ui-theme';
|
|
10
|
+
import { type SlottableProps } from '@dxos/ui-types';
|
|
11
|
+
|
|
12
|
+
import { useThemeContext } from '../../hooks';
|
|
13
|
+
|
|
14
|
+
//
|
|
15
|
+
// Root
|
|
16
|
+
//
|
|
17
|
+
|
|
18
|
+
const COLUMN_ROOT_NAME = 'Column.Root';
|
|
19
|
+
|
|
20
|
+
type GutterSize = 'sm' | 'md' | 'lg' | 'rail';
|
|
21
|
+
|
|
22
|
+
const gutterSizes: Record<GutterSize, string> = {
|
|
23
|
+
sm: 'var(--dx-gutter-sm)',
|
|
24
|
+
md: 'var(--dx-gutter-md)',
|
|
25
|
+
lg: 'var(--dx-gutter-lg)',
|
|
26
|
+
rail: 'var(--dx-rail-item)',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type ColumnRootProps = SlottableProps<HTMLDivElement, { gutter?: GutterSize }>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a vertical channel with left/right gutter columns.
|
|
33
|
+
* The `--gutter` CSS variable is set for nested components (Dialog, ScrollArea, Form.Viewport, etc.).
|
|
34
|
+
* Use `gutter='rail'` for icon-slot row layouts (Card); `gutter='md'` for whitespace layouts (Dialog).
|
|
35
|
+
* Direct children must use Column.Row (spans all 3 cols) or Column.Segment (center col only).
|
|
36
|
+
*
|
|
37
|
+
* NOTE: The theme applies a `dx-column` marker class to this element.
|
|
38
|
+
* ScrollArea.Root detects this via `[.dx-column_&]:col-span-full` to span all 3 grid columns,
|
|
39
|
+
* ensuring scroll content extends under the gutters rather than being confined to the center column.
|
|
40
|
+
* The `--gutter` CSS variable is also consumed by ScrollArea's `margin` option to align scrollbar spacing.
|
|
41
|
+
*/
|
|
42
|
+
const Root = forwardRef<HTMLDivElement, ColumnRootProps>(
|
|
43
|
+
({ children, asChild, role, gutter = 'md', ...props }, forwardedRef) => {
|
|
44
|
+
const { className, ...rest } = composableProps(props);
|
|
45
|
+
const Comp = asChild ? Slot : Primitive.div;
|
|
46
|
+
const { tx } = useThemeContext();
|
|
47
|
+
const gutterSize = gutterSizes[gutter];
|
|
48
|
+
return (
|
|
49
|
+
<Comp
|
|
50
|
+
{...rest}
|
|
51
|
+
role={role ?? 'none'}
|
|
52
|
+
style={
|
|
53
|
+
{
|
|
54
|
+
'--gutter': gutterSize,
|
|
55
|
+
gridTemplateColumns: [gutterSize, 'minmax(0,1fr)', gutterSize].join(' '),
|
|
56
|
+
} as CSSProperties
|
|
57
|
+
}
|
|
58
|
+
className={tx('column.root', { gutter }, className)}
|
|
59
|
+
ref={forwardedRef}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
</Comp>
|
|
63
|
+
);
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
Root.displayName = COLUMN_ROOT_NAME;
|
|
68
|
+
|
|
69
|
+
//
|
|
70
|
+
// Row
|
|
71
|
+
//
|
|
72
|
+
|
|
73
|
+
const COLUMN_ROW_NAME = 'Column.Row';
|
|
74
|
+
|
|
75
|
+
type ColumnRowProps = SlottableProps<HTMLDivElement>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Spans all 3 columns of the parent Column.Root and uses CSS subgrid to inherit their sizing.
|
|
79
|
+
* Children map to: [col-1: icon/slot] [col-2: content] [col-3: icon/action].
|
|
80
|
+
* Must be a direct child of Column.Root.
|
|
81
|
+
*/
|
|
82
|
+
const Row = forwardRef<HTMLDivElement, ColumnRowProps>(({ children, asChild, role, ...props }, forwardedRef) => {
|
|
83
|
+
const { className, ...rest } = composableProps(props);
|
|
84
|
+
const Comp = asChild ? Slot : Primitive.div;
|
|
85
|
+
const { tx } = useThemeContext();
|
|
86
|
+
return (
|
|
87
|
+
<Comp {...rest} role={role ?? 'none'} className={tx('column.row', {}, className)} ref={forwardedRef}>
|
|
88
|
+
{children}
|
|
89
|
+
</Comp>
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
Row.displayName = COLUMN_ROW_NAME;
|
|
94
|
+
|
|
95
|
+
//
|
|
96
|
+
// Segment
|
|
97
|
+
//
|
|
98
|
+
|
|
99
|
+
const COLUMN_SEGMENT_NAME = 'Column.Segment';
|
|
100
|
+
|
|
101
|
+
type ColumnSegmentProps = SlottableProps<HTMLDivElement>;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Occupies only the center column (col-2) of the parent Column.Root grid.
|
|
105
|
+
* Use `asChild` to merge grid positioning onto the child element, eliminating the wrapper div.
|
|
106
|
+
* NOTE: Must not use overflow-hidden here since it will clip input focus rings.
|
|
107
|
+
*/
|
|
108
|
+
const Segment = forwardRef<HTMLDivElement, ColumnSegmentProps>(
|
|
109
|
+
({ children, asChild, role, ...props }, forwardedRef) => {
|
|
110
|
+
const { className, ...rest } = composableProps(props);
|
|
111
|
+
const Comp = asChild ? Slot : Primitive.div;
|
|
112
|
+
const { tx } = useThemeContext();
|
|
113
|
+
// With asChild, merge col-start-2 directly onto the child — no contents wrapper needed.
|
|
114
|
+
return (
|
|
115
|
+
<Comp {...rest} role={role ?? 'none'} className={tx('column.segment', {}, className)} ref={forwardedRef}>
|
|
116
|
+
{asChild ? children : <div className='contents'>{children}</div>}
|
|
117
|
+
</Comp>
|
|
118
|
+
);
|
|
119
|
+
},
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
Segment.displayName = COLUMN_SEGMENT_NAME;
|
|
123
|
+
|
|
124
|
+
//
|
|
125
|
+
// Column
|
|
126
|
+
//
|
|
127
|
+
|
|
128
|
+
export const Column = {
|
|
129
|
+
Root,
|
|
130
|
+
Row,
|
|
131
|
+
Segment,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export type { ColumnRootProps, ColumnRowProps, ColumnSegmentProps };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { withLayout, withTheme } from '../../testing';
|
|
9
|
+
|
|
10
|
+
import { Container } from './Container';
|
|
11
|
+
|
|
12
|
+
const DefaultStory = () => (
|
|
13
|
+
<Container asChild>
|
|
14
|
+
<div className='grid place-items-center border border-red-500'>Hello</div>
|
|
15
|
+
</Container>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const meta: Meta = {
|
|
19
|
+
title: 'ui/react-ui-core/primitives/Container',
|
|
20
|
+
component: Container,
|
|
21
|
+
render: DefaultStory,
|
|
22
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
23
|
+
parameters: { layout: 'fullscreen' },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
|
|
28
|
+
type Story = StoryObj<typeof meta>;
|
|
29
|
+
|
|
30
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { forwardRef } from 'react';
|
|
6
|
+
|
|
7
|
+
import { composableProps, mx } from '@dxos/ui-theme';
|
|
8
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
9
|
+
import { SlottableProps } from '@dxos/ui-types';
|
|
10
|
+
import { Primitive } from '@radix-ui/react-primitive';
|
|
11
|
+
|
|
12
|
+
export type ContainerProps = SlottableProps<HTMLDivElement>;
|
|
13
|
+
|
|
14
|
+
export const Container = forwardRef<HTMLDivElement, ContainerProps>(({ children, asChild, ...props }, forwardedRef) => {
|
|
15
|
+
const { className, ...rest } = composableProps<HTMLDivElement>(props, { role: 'none' });
|
|
16
|
+
const Comp = asChild ? Slot : Primitive.div;
|
|
17
|
+
return (
|
|
18
|
+
<Comp {...rest} className={mx('dx-container', className)} ref={forwardedRef}>
|
|
19
|
+
{children}
|
|
20
|
+
</Comp>
|
|
21
|
+
);
|
|
22
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { type ChromaticPalette } from '@dxos/ui-types';
|
|
9
|
+
|
|
10
|
+
import { withLayout, withTheme } from '../../testing';
|
|
11
|
+
|
|
12
|
+
import { Flex } from './Flex';
|
|
13
|
+
|
|
14
|
+
const Cell = ({ label, hue }: { label: string; hue: ChromaticPalette }) => (
|
|
15
|
+
<div data-hue={hue} className='flex w-full dx-panel p-2 text-sm font-mono border rounded-sm'>
|
|
16
|
+
{label}
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const RowStory = () => (
|
|
21
|
+
<Flex classNames='gap-2 p-2'>
|
|
22
|
+
<Cell label='A' hue='red' />
|
|
23
|
+
<Cell label='B' hue='green' />
|
|
24
|
+
<Cell label='C' hue='blue' />
|
|
25
|
+
</Flex>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const ColumnStory = () => (
|
|
29
|
+
<Flex column classNames='gap-2 p-2'>
|
|
30
|
+
<Cell label='A' hue='red' />
|
|
31
|
+
<Cell label='B' hue='green' />
|
|
32
|
+
<Cell label='C' hue='blue' />
|
|
33
|
+
</Flex>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const GrowStory = () => (
|
|
37
|
+
<Flex column grow classNames='gap-2 p-2'>
|
|
38
|
+
<Cell label='Header' hue='yellow' />
|
|
39
|
+
<Flex grow>
|
|
40
|
+
<Cell label='Content (grows)' hue='blue' />
|
|
41
|
+
</Flex>
|
|
42
|
+
<Cell label='Footer' hue='orange' />
|
|
43
|
+
</Flex>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const meta: Meta = {
|
|
47
|
+
title: 'ui/react-ui-core/primitives/Flex',
|
|
48
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
49
|
+
parameters: { layout: 'fullscreen' },
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default meta;
|
|
53
|
+
|
|
54
|
+
type Story = StoryObj<typeof meta>;
|
|
55
|
+
|
|
56
|
+
export const Row: Story = { render: RowStory };
|
|
57
|
+
export const Column: Story = { render: ColumnStory };
|
|
58
|
+
export const Grow: Story = { render: GrowStory };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { forwardRef } from 'react';
|
|
6
|
+
|
|
7
|
+
import { composableProps, mx } from '@dxos/ui-theme';
|
|
8
|
+
import { type ComposableProps } from '@dxos/ui-types';
|
|
9
|
+
|
|
10
|
+
export type FlexProps = ComposableProps<HTMLDivElement> & {
|
|
11
|
+
column?: boolean;
|
|
12
|
+
grow?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const Flex = forwardRef<HTMLDivElement, FlexProps>(
|
|
16
|
+
({ children, role, column, grow, ...props }, forwardedRef) => {
|
|
17
|
+
const { className, ...rest } = composableProps(props);
|
|
18
|
+
return (
|
|
19
|
+
<div
|
|
20
|
+
ref={forwardedRef}
|
|
21
|
+
{...rest}
|
|
22
|
+
role={role ?? 'none'}
|
|
23
|
+
className={mx('flex', column && 'flex-col', grow && 'flex-1 overflow-hidden', className)}
|
|
24
|
+
>
|
|
25
|
+
{children}
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
},
|
|
29
|
+
);
|