@tcn/ui 0.15.0 → 0.17.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 (204) hide show
  1. package/dist/card.css +1 -0
  2. package/dist/column.css +1 -1
  3. package/dist/containers.css +1 -1
  4. package/dist/containers.module-BmICKsOK.js +5 -0
  5. package/dist/containers.module-BmICKsOK.js.map +1 -0
  6. package/dist/form/field/field.js +11 -8
  7. package/dist/form/field/field.js.map +1 -1
  8. package/dist/inputs/color_input/color_picker.js +5 -2
  9. package/dist/inputs/color_input/color_picker.js.map +1 -1
  10. package/dist/inputs/combo_box/combo_box.js +18 -15
  11. package/dist/inputs/combo_box/combo_box.js.map +1 -1
  12. package/dist/inputs/date_picker/date_picker.js +13 -10
  13. package/dist/inputs/date_picker/date_picker.js.map +1 -1
  14. package/dist/inputs/date_picker/date_picker_input.js +20 -17
  15. package/dist/inputs/date_picker/date_picker_input.js.map +1 -1
  16. package/dist/inputs/date_picker/date_picker_year_selector.js +5 -2
  17. package/dist/inputs/date_picker/date_picker_year_selector.js.map +1 -1
  18. package/dist/inputs/mask_input/key_capture_input.js +26 -23
  19. package/dist/inputs/mask_input/key_capture_input.js.map +1 -1
  20. package/dist/inputs/mask_input/mask_input.js +5 -2
  21. package/dist/inputs/mask_input/mask_input.js.map +1 -1
  22. package/dist/inputs/multiselect/multiselect.js +22 -19
  23. package/dist/inputs/multiselect/multiselect.js.map +1 -1
  24. package/dist/inputs/phone_number_input/phone_number_context.js +7 -4
  25. package/dist/inputs/phone_number_input/phone_number_context.js.map +1 -1
  26. package/dist/inputs/select/select.js +5 -2
  27. package/dist/inputs/select/select.js.map +1 -1
  28. package/dist/inputs/slider/slider.js +19 -16
  29. package/dist/inputs/slider/slider.js.map +1 -1
  30. package/dist/inputs/suggestions/suggestion_list.js +5 -2
  31. package/dist/inputs/suggestions/suggestion_list.js.map +1 -1
  32. package/dist/inputs/switch/switch.js +18 -15
  33. package/dist/inputs/switch/switch.js.map +1 -1
  34. package/dist/inputs/unit_input/unit_input.js +15 -12
  35. package/dist/inputs/unit_input/unit_input.js.map +1 -1
  36. package/dist/layouts/containers/columns/column.d.ts +6 -0
  37. package/dist/layouts/containers/columns/column.d.ts.map +1 -0
  38. package/dist/layouts/containers/columns/column.js +20 -0
  39. package/dist/layouts/containers/columns/column.js.map +1 -0
  40. package/dist/layouts/containers/columns/columns.d.ts +11 -0
  41. package/dist/layouts/containers/columns/columns.d.ts.map +1 -0
  42. package/dist/layouts/containers/columns/columns.js +34 -0
  43. package/dist/layouts/containers/columns/columns.js.map +1 -0
  44. package/dist/layouts/containers/rail.d.ts +2 -5
  45. package/dist/layouts/containers/rail.d.ts.map +1 -1
  46. package/dist/layouts/containers/rail.js +17 -55
  47. package/dist/layouts/containers/rail.js.map +1 -1
  48. package/dist/layouts/containers/rows/index.d.ts +3 -0
  49. package/dist/layouts/containers/rows/index.d.ts.map +1 -0
  50. package/dist/layouts/containers/rows/index.js +7 -0
  51. package/dist/layouts/containers/rows/index.js.map +1 -0
  52. package/dist/layouts/containers/rows/row.d.ts +6 -0
  53. package/dist/layouts/containers/rows/row.d.ts.map +1 -0
  54. package/dist/layouts/containers/rows/row.js +20 -0
  55. package/dist/layouts/containers/rows/row.js.map +1 -0
  56. package/dist/layouts/containers/rows/rows.d.ts +11 -0
  57. package/dist/layouts/containers/rows/rows.d.ts.map +1 -0
  58. package/dist/layouts/containers/rows/rows.js +34 -0
  59. package/dist/layouts/containers/rows/rows.js.map +1 -0
  60. package/dist/layouts/containers/scaffold.d.ts +2 -5
  61. package/dist/layouts/containers/scaffold.d.ts.map +1 -1
  62. package/dist/layouts/containers/scaffold.js +17 -55
  63. package/dist/layouts/containers/scaffold.js.map +1 -1
  64. package/dist/layouts/index.d.ts +4 -2
  65. package/dist/layouts/index.d.ts.map +1 -1
  66. package/dist/layouts/index.js +35 -31
  67. package/dist/layouts/index.js.map +1 -1
  68. package/dist/mobile/inputs/date_picker/mobile_date_picker_header.js +5 -2
  69. package/dist/mobile/inputs/date_picker/mobile_date_picker_header.js.map +1 -1
  70. package/dist/mobile/inputs/date_picker/mobile_date_picker_input.js +5 -2
  71. package/dist/mobile/inputs/date_picker/mobile_date_picker_input.js.map +1 -1
  72. package/dist/mobile/inputs/date_picker/mobile_date_picker_year_selector.js +8 -5
  73. package/dist/mobile/inputs/date_picker/mobile_date_picker_year_selector.js.map +1 -1
  74. package/dist/navigation/tabs/state/link/tab_link.js +9 -6
  75. package/dist/navigation/tabs/state/link/tab_link.js.map +1 -1
  76. package/dist/overlay/menu/menu.js +3 -0
  77. package/dist/overlay/menu/menu.js.map +1 -1
  78. package/dist/overlay/popper/context_popper.js +8 -5
  79. package/dist/overlay/popper/context_popper.js.map +1 -1
  80. package/dist/overlay/popper/element_popper.js +9 -6
  81. package/dist/overlay/popper/element_popper.js.map +1 -1
  82. package/dist/overlay/popper/legacy/popper.js +13 -10
  83. package/dist/overlay/popper/legacy/popper.js.map +1 -1
  84. package/dist/overlay/popper/preview_popper.js +10 -7
  85. package/dist/overlay/popper/preview_popper.js.map +1 -1
  86. package/dist/overlay/tethered/tethered.js +11 -8
  87. package/dist/overlay/tethered/tethered.js.map +1 -1
  88. package/dist/resizable.css +1 -0
  89. package/dist/resizable.module-I6iyBAvM.js +5 -0
  90. package/dist/resizable.module-I6iyBAvM.js.map +1 -0
  91. package/dist/resize_handle.css +1 -0
  92. package/dist/row.css +1 -0
  93. package/dist/stacks/box/box.js +12 -9
  94. package/dist/stacks/box/box.js.map +1 -1
  95. package/dist/stacks/box/detect_resize_bounds.d.ts +1 -0
  96. package/dist/stacks/box/detect_resize_bounds.d.ts.map +1 -1
  97. package/dist/stacks/box/detect_resize_bounds.js +22 -20
  98. package/dist/stacks/box/detect_resize_bounds.js.map +1 -1
  99. package/dist/stacks/h_collapsible_box.js +17 -14
  100. package/dist/stacks/h_collapsible_box.js.map +1 -1
  101. package/dist/stacks/v_collapsible_box.js +19 -16
  102. package/dist/stacks/v_collapsible_box.js.map +1 -1
  103. package/dist/surfaces/card/card.d.ts.map +1 -1
  104. package/dist/surfaces/card/card.js +14 -6
  105. package/dist/surfaces/card/card.js.map +1 -1
  106. package/dist/surfaces/pop_confirm/pop_confirm.js +6 -4
  107. package/dist/surfaces/pop_confirm/pop_confirm.js.map +1 -1
  108. package/dist/test-setup.d.ts +2 -0
  109. package/dist/test-setup.d.ts.map +1 -0
  110. package/dist/test-setup.js +10 -0
  111. package/dist/test-setup.js.map +1 -0
  112. package/dist/themes/theme.d.ts.map +1 -1
  113. package/dist/themes/theme.js +17 -22
  114. package/dist/themes/theme.js.map +1 -1
  115. package/dist/themes/themes/ergo/ergo_theme.css +1 -1
  116. package/dist/themes/themes/ergo/ergo_theme.js +225 -27
  117. package/dist/themes/themes/ergo/ergo_theme.js.map +1 -1
  118. package/dist/utils/index.d.ts +1 -0
  119. package/dist/utils/index.d.ts.map +1 -1
  120. package/dist/utils/index.js +39 -26
  121. package/dist/utils/index.js.map +1 -1
  122. package/dist/utils/resize/context.d.ts +4 -0
  123. package/dist/utils/resize/context.d.ts.map +1 -0
  124. package/dist/utils/resize/context.js +10 -0
  125. package/dist/utils/resize/context.js.map +1 -0
  126. package/dist/utils/resize/handle_config.d.ts +32 -0
  127. package/dist/utils/resize/handle_config.d.ts.map +1 -0
  128. package/dist/utils/resize/handle_config.js +85 -0
  129. package/dist/utils/resize/handle_config.js.map +1 -0
  130. package/dist/utils/resize/index.d.ts +10 -0
  131. package/dist/utils/resize/index.d.ts.map +1 -0
  132. package/dist/utils/resize/index.js +16 -0
  133. package/dist/utils/resize/index.js.map +1 -0
  134. package/dist/utils/resize/resizable.d.ts +11 -0
  135. package/dist/utils/resize/resizable.d.ts.map +1 -0
  136. package/dist/utils/resize/resizable.js +52 -0
  137. package/dist/utils/resize/resizable.js.map +1 -0
  138. package/dist/utils/resize/resize_handle.d.ts +7 -0
  139. package/dist/utils/resize/resize_handle.d.ts.map +1 -0
  140. package/dist/utils/resize/resize_handle.js +100 -0
  141. package/dist/utils/resize/resize_handle.js.map +1 -0
  142. package/dist/utils/resize/resize_strategy.d.ts +47 -0
  143. package/dist/utils/resize/resize_strategy.d.ts.map +1 -0
  144. package/dist/utils/resize/resize_strategy.js +108 -0
  145. package/dist/utils/resize/resize_strategy.js.map +1 -0
  146. package/dist/utils/resize/types.d.ts +28 -0
  147. package/dist/utils/resize/types.d.ts.map +1 -0
  148. package/dist/utils/resize/types.js +2 -0
  149. package/dist/utils/resize/types.js.map +1 -0
  150. package/package.json +3 -3
  151. package/src/layouts/__stories__/columns.stories.tsx +77 -0
  152. package/src/layouts/__stories__/composed.stories.tsx +77 -8
  153. package/src/layouts/__stories__/rail.stories.tsx +4 -4
  154. package/src/layouts/__stories__/rows.stories.tsx +77 -0
  155. package/src/layouts/__stories__/utils.tsx +2 -84
  156. package/src/layouts/containers/columns/column.module.css +15 -0
  157. package/src/layouts/containers/columns/column.tsx +22 -0
  158. package/src/layouts/containers/columns/columns.tsx +42 -0
  159. package/src/layouts/containers/containers.module.css +27 -29
  160. package/src/layouts/containers/rail.tsx +9 -51
  161. package/src/layouts/containers/rows/index.ts +2 -0
  162. package/src/layouts/containers/rows/row.module.css +15 -0
  163. package/src/layouts/containers/rows/row.tsx +22 -0
  164. package/src/layouts/containers/rows/rows.tsx +42 -0
  165. package/src/layouts/containers/scaffold.tsx +9 -49
  166. package/src/layouts/index.ts +4 -2
  167. package/src/stacks/box/detect_resize_bounds.ts +5 -1
  168. package/src/surfaces/card/card.module.css +5 -0
  169. package/src/surfaces/card/card.stories.tsx +66 -8
  170. package/src/surfaces/card/card.tsx +6 -2
  171. package/src/surfaces/page/page.stories.tsx +109 -25
  172. package/src/surfaces/panel/__stories__/panel.stories.tsx +139 -1
  173. package/src/test-setup.ts +11 -0
  174. package/src/themes/theme.tsx +6 -16
  175. package/src/themes/themes/ergo/ergo_theme.css +223 -25
  176. package/src/utils/index.ts +2 -0
  177. package/src/utils/resize/__stories__/resizable.stories.tsx +214 -0
  178. package/src/utils/resize/__stories__/resizable_stories.module.css +47 -0
  179. package/src/utils/resize/__tests__/handle_config.test.ts +269 -0
  180. package/src/utils/resize/__tests__/resize_strategy.test.ts +163 -0
  181. package/src/utils/resize/context.ts +9 -0
  182. package/src/utils/resize/handle_config.ts +142 -0
  183. package/src/utils/resize/index.ts +37 -0
  184. package/src/utils/resize/resizable.module.css +5 -0
  185. package/src/utils/resize/resizable.tsx +97 -0
  186. package/src/utils/resize/resize_handle.module.css +146 -0
  187. package/src/utils/resize/resize_handle.tsx +165 -0
  188. package/src/utils/resize/resize_strategy.ts +190 -0
  189. package/src/utils/resize/types.ts +64 -0
  190. package/dist/containers.module-DlGySre0.js +0 -5
  191. package/dist/containers.module-DlGySre0.js.map +0 -1
  192. package/dist/layouts/column/column.d.ts +0 -10
  193. package/dist/layouts/column/column.d.ts.map +0 -1
  194. package/dist/layouts/column/column.js +0 -52
  195. package/dist/layouts/column/column.js.map +0 -1
  196. package/dist/layouts/containers/side/side.d.ts +0 -6
  197. package/dist/layouts/containers/side/side.d.ts.map +0 -1
  198. package/dist/layouts/containers/side/side.js +0 -22
  199. package/dist/layouts/containers/side/side.js.map +0 -1
  200. package/dist/side.css +0 -1
  201. package/src/layouts/column/column.module.css +0 -35
  202. package/src/layouts/column/column.tsx +0 -57
  203. package/src/layouts/containers/side/side.module.css +0 -7
  204. package/src/layouts/containers/side/side.tsx +0 -25
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
3
3
  import { LayoutStoryDecorator } from './utils/layout_theme_provider.js';
4
4
  import { SBLayoutContent } from './utils/content.js';
5
5
  import { Rail } from '../containers/rail.js';
6
- import { Side } from '../containers/side/side.js';
6
+ import { Column } from '../containers/columns/column.js';
7
7
  import { UtilityStrip } from '../containers/utility_strip/utility_strip.js';
8
8
  import { Title } from '../../typography/index.js';
9
9
  import { Scaffold } from '../containers/scaffold.js';
@@ -38,7 +38,7 @@ export const Baseline: Story = {
38
38
  <SBLayoutContent />
39
39
  <SBLayoutContent />
40
40
  </Rail>
41
- <Side width="200px">Side</Side>
41
+ <Column minWidth="200px">Column</Column>
42
42
  </Rail>
43
43
  </LayoutStoryDecorator>
44
44
  ),
@@ -57,7 +57,7 @@ export const HorizontalContent: Story = {
57
57
  <SBLayoutContent />
58
58
  <SBLayoutContent />
59
59
  </Rail>
60
- <Side width="200px">Side</Side>
60
+ <Column minWidth="200px">Column</Column>
61
61
  </Rail>
62
62
  </LayoutStoryDecorator>
63
63
  ),
@@ -76,7 +76,7 @@ export const VerticalContent: Story = {
76
76
  <SBLayoutContent />
77
77
  <SBLayoutContent />
78
78
  </Scaffold>
79
- <Side width="200px">Side</Side>
79
+ <Column minWidth="200px">Column</Column>
80
80
  </Rail>
81
81
  </LayoutStoryDecorator>
82
82
  ),
@@ -0,0 +1,77 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { LayoutStoryDecorator } from './utils/layout_theme_provider.js';
4
+ import { Row } from '../containers/rows/row.js';
5
+ import { Rows } from '../containers/rows/rows.js';
6
+ import { Detail, Section } from '../section/index.js';
7
+
8
+ const meta: Meta = {
9
+ title: 'Layouts/Rows',
10
+ component: () => <></>,
11
+ tags: ['autodocs'],
12
+ parameters: {
13
+ docs: {
14
+ description: {
15
+ component:
16
+ 'Vertical container for fixed-height Row components. Theme controls row separation via the `.tcn-rows` context selector.',
17
+ },
18
+ },
19
+ },
20
+ };
21
+
22
+ export default meta;
23
+
24
+ type Story = StoryObj;
25
+
26
+ /**
27
+ * Simple example of two rows stacked vertically.
28
+ */
29
+ /**
30
+ * rowsMinHeight sets a default minHeight on all child Rows.
31
+ * An explicit minHeight prop on a Row overrides it.
32
+ */
33
+ export const RowsMinHeight: Story = {
34
+ render: () => (
35
+ <LayoutStoryDecorator>
36
+ <Rows rowsMinHeight="80px">
37
+ <Row>
38
+ <Section>
39
+ <Detail>default (80px)</Detail>
40
+ </Section>
41
+ </Row>
42
+ <Row>
43
+ <Section>
44
+ <Detail>default (80px)</Detail>
45
+ </Section>
46
+ </Row>
47
+ <Row minHeight="160px">
48
+ <Section>
49
+ <Detail>override (160px)</Detail>
50
+ </Section>
51
+ </Row>
52
+ </Rows>
53
+ </LayoutStoryDecorator>
54
+ ),
55
+ };
56
+
57
+ /**
58
+ * Simple example of two rows stacked vertically.
59
+ */
60
+ export const Baseline: Story = {
61
+ render: () => (
62
+ <LayoutStoryDecorator>
63
+ <Rows>
64
+ <Row minHeight="120px">
65
+ <Section>
66
+ <Detail>120px row</Detail>
67
+ </Section>
68
+ </Row>
69
+ <Row minHeight="120px">
70
+ <Section>
71
+ <Detail>120px row</Detail>
72
+ </Section>
73
+ </Row>
74
+ </Rows>
75
+ </LayoutStoryDecorator>
76
+ ),
77
+ };
@@ -2,15 +2,9 @@ import type { PropsWithChildren } from 'react';
2
2
  import clsx from 'clsx';
3
3
 
4
4
  import { Scaffold, type ScaffoldProps } from '../containers/scaffold.js';
5
- import { Header } from '../header/header.js';
6
- import { Footer } from '../footer/footer.js';
7
- import { UtilityBar } from '../utility_bar/utility_bar.js';
8
5
 
9
6
  import { Rail, type RailProps } from '../containers/rail.js';
10
- import { Side } from '../containers/side/side.js';
11
- import { Box, Spacer } from '../../stacks/index.js';
12
- import { UtilityStrip } from '../containers/utility_strip/utility_strip.js';
13
- import { SearchIcon } from '@tcn/icons/search_icon.js';
7
+ import { Box } from '../../stacks/index.js';
14
8
 
15
9
  import styles from './composed_stories.module.css';
16
10
 
@@ -22,10 +16,6 @@ const FloatingLabel = ({ children }: { children: React.ReactNode }) => {
22
16
  );
23
17
  };
24
18
 
25
- const VerticalLabel = ({ children }: { children: React.ReactNode }) => {
26
- return <span className={styles.verticalLabel}>{children}</span>;
27
- };
28
-
29
19
  export const SBContent: React.FC<
30
20
  PropsWithChildren<{ className?: string; minHeight?: string; minWidth?: string }>
31
21
  > = ({ className, children, minHeight = '200px', minWidth = '200px' }) => {
@@ -42,43 +32,14 @@ export const SBContent: React.FC<
42
32
  );
43
33
  };
44
34
 
45
- const SBActionBox = ({ children }: { children: React.ReactNode }) => {
46
- return <span className={styles.actionBox}>{children}</span>;
47
- };
48
-
49
- const SBActions = () => {
50
- return (
51
- <>
52
- <Spacer />
53
- <SBActionBox>
54
- <SearchIcon />
55
- </SBActionBox>
56
- <SBActionBox>
57
- <SearchIcon />
58
- </SBActionBox>
59
- <SBActionBox>
60
- <SearchIcon />
61
- </SBActionBox>
62
- </>
63
- );
64
- };
65
-
66
35
  interface SBNestedRailProps extends RailProps {
67
36
  depth?: number;
68
- scaffold?: boolean;
69
- side?: boolean;
70
- utilityStrip?: boolean;
71
- label?: boolean;
72
37
  }
73
38
 
74
39
  export const SBNestedRail: React.FC<PropsWithChildren<SBNestedRailProps>> = ({
75
40
  children,
76
41
  className,
77
42
  depth = 1,
78
- scaffold = true,
79
- side = true,
80
- utilityStrip = true,
81
- label = true,
82
43
  height = '100%',
83
44
  ...props
84
45
  }) => {
@@ -89,51 +50,20 @@ export const SBNestedRail: React.FC<PropsWithChildren<SBNestedRailProps>> = ({
89
50
  data-depth={depth}
90
51
  {...props}
91
52
  >
92
- {label && <FloatingLabel>Rail</FloatingLabel>}
93
- {utilityStrip && (
94
- <UtilityStrip className={clsx(styles.utilityStrip, styles.secondary)}>
95
- <VerticalLabel>Utility Strip</VerticalLabel>
96
- <SBActions />
97
- </UtilityStrip>
98
- )}
53
+ <FloatingLabel>Rail</FloatingLabel>
99
54
  {children}
100
- {side && (
101
- <Side className={clsx(styles.side, styles.secondary)} minWidth="200px">
102
- <span>Side/Column/WIP</span>
103
- </Side>
104
- )}
105
- {scaffold && (
106
- <SBNestedScaffold
107
- depth={depth + 1}
108
- utilityBar={false}
109
- footer={false}
110
- minWidth={'fit-content'}
111
- >
112
- <Scaffold>
113
- <SBContent />
114
- <SBContent />
115
- <SBContent />
116
- </Scaffold>
117
- </SBNestedScaffold>
118
- )}
119
55
  </Rail>
120
56
  );
121
57
  };
122
58
 
123
59
  interface SBNestedScaffoldProps extends ScaffoldProps {
124
60
  depth?: number;
125
- header?: boolean;
126
- utilityBar?: boolean;
127
- footer?: boolean;
128
61
  }
129
62
 
130
63
  export const SBNestedScaffold: React.FC<PropsWithChildren<SBNestedScaffoldProps>> = ({
131
64
  children,
132
65
  className,
133
66
  depth = 1,
134
- header = true,
135
- utilityBar = true,
136
- footer = true,
137
67
  height = '100%',
138
68
  ...props
139
69
  }) => {
@@ -145,19 +75,7 @@ export const SBNestedScaffold: React.FC<PropsWithChildren<SBNestedScaffoldProps>
145
75
  {...props}
146
76
  >
147
77
  <FloatingLabel>Scaffold</FloatingLabel>
148
- {header && (
149
- <Header className={clsx(styles.header, styles.secondary)}>Header</Header>
150
- )}
151
- {utilityBar && (
152
- <UtilityBar className={clsx(styles.utilityBar, styles.secondary)}>
153
- Utility Bar
154
- <SBActions />
155
- </UtilityBar>
156
- )}
157
78
  {children}
158
- {footer && (
159
- <Footer className={clsx(styles.footer, styles.secondary)}>Footer</Footer>
160
- )}
161
79
  </Scaffold>
162
80
  );
163
81
  };
@@ -0,0 +1,15 @@
1
+ @layer tcn-system {
2
+ :where(.column) {
3
+ height: 100%;
4
+ min-height: 100%;
5
+ width: var(--columns-width, auto);
6
+ min-width: var(--columns-min-width, 0);
7
+ max-width: var(--columns-max-width, none);
8
+ flex-grow: 0;
9
+ }
10
+
11
+ :where(.column[data-width="fill"]) {
12
+ flex-grow: 1;
13
+ width: 0; /* let flex-grow determine width, not content */
14
+ }
15
+ }
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { VStack, type VStackProps } from '../../../stacks/v_stack.js';
4
+ import styles from './column.module.css';
5
+
6
+ export interface ColumnProps extends Omit<VStackProps, 'as'> {}
7
+
8
+ export const Column = React.forwardRef<HTMLElement, ColumnProps>(function Column(
9
+ { children, className, ...props }: ColumnProps,
10
+ ref
11
+ ) {
12
+ return (
13
+ <VStack
14
+ ref={ref}
15
+ as="section"
16
+ className={clsx('tcn-column', styles['column'], className)}
17
+ {...props}
18
+ >
19
+ {children}
20
+ </VStack>
21
+ );
22
+ });
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { Rail, type RailProps } from '../rail.js';
4
+ import { removeUndefinedProperties } from '../../../stacks/utils/remove_undefined_properties.js';
5
+
6
+ export interface ColumnsOwnProps {
7
+ columnsMinWidth?: string | number;
8
+ columnsWidth?: string | number;
9
+ columnsMaxWidth?: string | number;
10
+ }
11
+
12
+ export interface ColumnsProps extends Omit<RailProps, 'as'>, ColumnsOwnProps {}
13
+
14
+ export const Columns = React.forwardRef<HTMLElement, ColumnsProps>(function Columns(
15
+ {
16
+ children,
17
+ className,
18
+ columnsMinWidth,
19
+ columnsWidth,
20
+ columnsMaxWidth,
21
+ style,
22
+ ...props
23
+ }: ColumnsProps,
24
+ ref
25
+ ) {
26
+ const columnVars = removeUndefinedProperties({
27
+ '--columns-min-width': columnsMinWidth,
28
+ '--columns-width': columnsWidth,
29
+ '--columns-max-width': columnsMaxWidth,
30
+ });
31
+
32
+ return (
33
+ <Rail
34
+ ref={ref}
35
+ className={clsx('tcn-columns', className)}
36
+ style={{ ...columnVars, ...style }}
37
+ {...props}
38
+ >
39
+ {children}
40
+ </Rail>
41
+ );
42
+ });
@@ -1,55 +1,53 @@
1
1
  @layer tcn-system {
2
+ /* Outer or standalone scaffold fills its container */
2
3
  :where(.scaffold) {
3
- max-height: 100%;
4
+ height: 100%;
4
5
  width: 100%;
5
- height: auto;
6
+ max-height: 100%;
7
+ overflow: auto;
6
8
  }
7
9
 
10
+ /* Outer or standalone Rail fills its container */
8
11
  :where(.rail) {
9
12
  max-width: 100%;
10
13
  height: 100%;
11
- width: auto;
12
- }
13
-
14
- :where(.container) > :where(.container-stack) {
15
14
  width: 100%;
16
- height: 100%;
15
+ overflow: auto;
17
16
  }
18
17
 
19
- /* Scaffold base layout frame only, no overflow clipping */
20
- :where(.scaffold) > :where(.scaffold-stack) {
21
- overflow-y: auto;
18
+ /* Nested Containers should grow via flex-grow */
19
+ :where(.container) > .container {
20
+ flex-grow: 1;
21
+ /* Important - override the Stack css */
22
+ flex-shrink: unset;
22
23
  }
23
24
 
24
- /* Switching direction - rail fills scaffold width */
25
- :where(.scaffold) > :where(.scaffold-stack) > :where(.rail) {
26
- width: 100%;
25
+ /* Child Scaffolds should use flex-grow to manage height - scroll vertically */
26
+ :where(.container) > .scaffold {
27
+ overflow-y: auto;
28
+ min-height: 0;
27
29
  }
28
30
 
29
- /* Switching direction - scaffold fills rail height */
30
- :where(.rail) > :where(.rail-stack) > :where(.scaffold) {
31
- height: 100%;
31
+ :where(.scaffold) > .scaffold {
32
+ height: auto;
32
33
  }
33
34
 
34
- /* Rail base layout frame only, no overflow clipping */
35
- :where(.rail) > :where(.rail-stack) {
35
+ /* Child Rails should use flex-grow to manage width - scroll horizontally */
36
+ :where(.container) > .rail {
36
37
  overflow-x: auto;
38
+ min-width: 0;
37
39
  }
38
40
 
39
- /* container grows to fill remaining space */
40
- :where(.container-stack) > :where(.container) {
41
- flex-grow: 1;
41
+ :where(.rail) > .rail {
42
+ width: auto;
42
43
  }
43
44
 
44
- /* container nested Scaffold scrolls vertically */
45
- :where(.container-stack) > :where(.scaffold) {
46
- min-height: 0;
47
- overflow-y: auto;
45
+ /* The opposite axis of the flex grow should fill via height or width */
46
+ :where(.rail) > .container {
47
+ height: 100%;
48
48
  }
49
49
 
50
- /* container nested Rail scrolls horizontally */
51
- :where(.container-stack) > :where(.rail) {
52
- min-width: 0;
53
- overflow-x: auto;
50
+ :where(.scaffold) > .container {
51
+ width: 100%;
54
52
  }
55
53
  }
@@ -1,44 +1,20 @@
1
1
  import React from 'react';
2
2
  import { clsx } from 'clsx';
3
- import { Box, type BoxProps } from '../../stacks/box/box.js';
4
- import type { Alignment } from '../../stacks/types/alignment.js';
5
- import { HStack } from '../../stacks/h_stack.js';
6
-
3
+ import { HStack, type HStackProps } from '../../stacks/h_stack.js';
7
4
  import styles from './containers.module.css';
8
5
 
9
- export interface RailProps extends Omit<BoxProps, 'as'> {
10
- vAlign?: Alignment;
11
- hAlign?: Alignment;
12
- }
6
+ export interface RailProps extends Omit<HStackProps, 'as'> {}
13
7
 
14
- // WIP: This component is not fully implemented.
15
8
  export const Rail = React.forwardRef<HTMLElement, RailProps>(function Rail(
16
- {
17
- children,
18
- width,
19
- height,
20
- minWidth,
21
- maxWidth,
22
- minHeight,
23
- maxHeight,
24
- hAlign = 'start',
25
- vAlign = 'start',
26
- className,
27
- ...props
28
- }: RailProps,
9
+ { children, className, vAlign = 'start', hAlign = 'start', ...props }: RailProps,
29
10
  ref
30
11
  ) {
31
12
  return (
32
- <Box
13
+ <HStack
33
14
  ref={ref}
34
- width={width}
35
- height={height}
36
- minWidth={minWidth}
37
- maxWidth={maxWidth}
38
- minHeight={minHeight}
39
- maxHeight={maxHeight}
40
- data-h-alignment={hAlign}
41
- data-v-alignment={vAlign}
15
+ as="section"
16
+ vAlign={vAlign}
17
+ hAlign={hAlign}
42
18
  className={clsx(
43
19
  className,
44
20
  styles['rail'],
@@ -48,25 +24,7 @@ export const Rail = React.forwardRef<HTMLElement, RailProps>(function Rail(
48
24
  )}
49
25
  {...props}
50
26
  >
51
- <HStack
52
- as="section"
53
- minWidth={minWidth}
54
- maxWidth={maxWidth}
55
- minHeight={minHeight}
56
- maxHeight={maxHeight}
57
- hAlign={hAlign}
58
- vAlign={vAlign}
59
- ref={ref}
60
- className={clsx(
61
- styles['rail-stack'],
62
- styles['container-stack'],
63
- 'tcn-container-stack',
64
- 'tcn-rail-stack'
65
- )}
66
- zIndex={0}
67
- >
68
- {children}
69
- </HStack>
70
- </Box>
27
+ {children}
28
+ </HStack>
71
29
  );
72
30
  });
@@ -0,0 +1,2 @@
1
+ export { Row, type RowProps } from './row.js';
2
+ export { Rows, type RowsProps } from './rows.js';
@@ -0,0 +1,15 @@
1
+ @layer tcn-system {
2
+ :where(.row) {
3
+ width: 100%;
4
+ min-width: 0;
5
+ height: var(--rows-height, auto);
6
+ min-height: var(--rows-min-height, 0);
7
+ max-height: var(--rows-max-height, none);
8
+ flex-grow: 0;
9
+ }
10
+
11
+ :where(.row[data-height="fill"]) {
12
+ flex-grow: 1;
13
+ height: 0; /* let flex-grow determine height, not content */
14
+ }
15
+ }
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { HStack, type HStackProps } from '../../../stacks/h_stack.js';
4
+ import styles from './row.module.css';
5
+
6
+ export interface RowProps extends Omit<HStackProps, 'as'> {}
7
+
8
+ export const Row = React.forwardRef<HTMLElement, RowProps>(function Row(
9
+ { children, className, ...props }: RowProps,
10
+ ref
11
+ ) {
12
+ return (
13
+ <HStack
14
+ ref={ref}
15
+ as="section"
16
+ className={clsx('tcn-row', styles['row'], className)}
17
+ {...props}
18
+ >
19
+ {children}
20
+ </HStack>
21
+ );
22
+ });
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { Scaffold, type ScaffoldProps } from '../scaffold.js';
4
+ import { removeUndefinedProperties } from '../../../stacks/utils/remove_undefined_properties.js';
5
+
6
+ export interface RowsOwnProps {
7
+ rowsMinHeight?: string | number;
8
+ rowsHeight?: string | number;
9
+ rowsMaxHeight?: string | number;
10
+ }
11
+
12
+ export interface RowsProps extends Omit<ScaffoldProps, 'as'>, RowsOwnProps {}
13
+
14
+ export const Rows = React.forwardRef<HTMLElement, RowsProps>(function Rows(
15
+ {
16
+ children,
17
+ className,
18
+ rowsMinHeight,
19
+ rowsHeight,
20
+ rowsMaxHeight,
21
+ style,
22
+ ...props
23
+ }: RowsProps,
24
+ ref
25
+ ) {
26
+ const rowVars = removeUndefinedProperties({
27
+ '--rows-min-height': rowsMinHeight,
28
+ '--rows-height': rowsHeight,
29
+ '--rows-max-height': rowsMaxHeight,
30
+ });
31
+
32
+ return (
33
+ <Scaffold
34
+ ref={ref}
35
+ className={clsx('tcn-rows', className)}
36
+ style={{ ...rowVars, ...style }}
37
+ {...props}
38
+ >
39
+ {children}
40
+ </Scaffold>
41
+ );
42
+ });
@@ -1,42 +1,20 @@
1
1
  import React from 'react';
2
2
  import { clsx } from 'clsx';
3
- import { Box, type BoxProps } from '../../stacks/box/box.js';
4
- import type { Alignment } from '../../stacks/types/alignment.js';
5
- import { VStack } from '../../stacks/v_stack.js';
3
+ import { VStack, type VStackProps } from '../../stacks/v_stack.js';
6
4
  import styles from './containers.module.css';
7
5
 
8
- export interface ScaffoldProps extends Omit<BoxProps, 'as'> {
9
- vAlign?: Alignment;
10
- hAlign?: Alignment;
11
- }
6
+ export interface ScaffoldProps extends Omit<VStackProps, 'as'> {}
12
7
 
13
8
  export const Scaffold = React.forwardRef<HTMLElement, ScaffoldProps>(function Scaffold(
14
- {
15
- children,
16
- width,
17
- height,
18
- minWidth,
19
- maxWidth,
20
- minHeight,
21
- maxHeight,
22
- hAlign = 'start',
23
- vAlign = 'start',
24
- className,
25
- ...props
26
- }: ScaffoldProps,
9
+ { children, className, vAlign = 'start', hAlign = 'start', ...props }: ScaffoldProps,
27
10
  ref
28
11
  ) {
29
12
  return (
30
- <Box
13
+ <VStack
31
14
  ref={ref}
32
- width={width}
33
- height={height}
34
- minWidth={minWidth}
35
- maxWidth={maxWidth}
36
- minHeight={minHeight}
37
- maxHeight={maxHeight}
38
- data-h-alignment={hAlign}
39
- data-v-alignment={vAlign}
15
+ as="section"
16
+ vAlign={vAlign}
17
+ hAlign={hAlign}
40
18
  className={clsx(
41
19
  className,
42
20
  styles['scaffold'],
@@ -46,25 +24,7 @@ export const Scaffold = React.forwardRef<HTMLElement, ScaffoldProps>(function Sc
46
24
  )}
47
25
  {...props}
48
26
  >
49
- <VStack
50
- as="section"
51
- minWidth={minWidth}
52
- maxWidth={maxWidth}
53
- minHeight={minHeight}
54
- maxHeight={maxHeight}
55
- hAlign={hAlign}
56
- vAlign={vAlign}
57
- ref={ref}
58
- className={clsx(
59
- styles['scaffold-stack'],
60
- styles['container-stack'],
61
- 'tcn-container-stack',
62
- 'tcn-scaffold-stack'
63
- )}
64
- zIndex={0}
65
- >
66
- {children}
67
- </VStack>
68
- </Box>
27
+ {children}
28
+ </VStack>
69
29
  );
70
30
  });
@@ -1,4 +1,4 @@
1
- export * from './column/column.js';
1
+ export { Column, type ColumnProps } from './containers/columns/column.js';
2
2
  export * from './divider/divider.js';
3
3
  export * from './grid/grid.js';
4
4
  export * from './list/item.js';
@@ -20,7 +20,9 @@ export { Breakpoint, type BreakpointProps } from './responsive/breakpoint.js';
20
20
  export { TTable, THead, TBody, TFoot, TR, TH, TD } from './table/table.js';
21
21
 
22
22
  export { Rail, type RailProps } from './containers/rail.js';
23
- export { Side, type SideProps } from './containers/side/side.js';
23
+ export { Columns, type ColumnsProps } from './containers/columns/columns.js';
24
+ export { Row, type RowProps } from './containers/rows/row.js';
25
+ export { Rows, type RowsProps } from './containers/rows/rows.js';
24
26
  export {
25
27
  UtilityStrip,
26
28
  type UtilityStripProps,