contain-css-svelte 1.4.2 → 1.5.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 (50) hide show
  1. package/dist/Card.svelte +57 -3
  2. package/dist/controls/Button.svelte +32 -0
  3. package/dist/controls/ButtonLink.svelte +32 -0
  4. package/dist/controls/Checkbox.svelte +36 -0
  5. package/dist/controls/CircleButton.svelte +32 -0
  6. package/dist/controls/Input.svelte +32 -0
  7. package/dist/controls/RadioButton.svelte +36 -1
  8. package/dist/controls/Select.svelte +35 -0
  9. package/dist/controls/Slider.svelte +32 -0
  10. package/dist/controls/TabItem.svelte +36 -0
  11. package/dist/controls/Toggle.svelte +32 -0
  12. package/dist/dropdowns/DropdownMenu.svelte +53 -1
  13. package/dist/layout/Accordion.svelte +32 -0
  14. package/dist/layout/Bar.svelte +50 -0
  15. package/dist/layout/ColumnContainer.svelte +32 -0
  16. package/dist/layout/Columns.svelte +32 -0
  17. package/dist/layout/Container.svelte +48 -2
  18. package/dist/layout/DataList.svelte +33 -1
  19. package/dist/layout/DataList.svelte.d.ts +7 -0
  20. package/dist/layout/DataListItem.svelte +56 -2
  21. package/dist/layout/Fieldset.svelte +32 -0
  22. package/dist/layout/Form.svelte +32 -0
  23. package/dist/layout/FormItem.svelte +46 -0
  24. package/dist/layout/GridLayout.svelte +59 -0
  25. package/dist/layout/Hero.svelte +42 -0
  26. package/dist/layout/Inline.svelte +37 -1
  27. package/dist/layout/MenuList.svelte +32 -0
  28. package/dist/layout/Page.svelte +137 -10
  29. package/dist/layout/Page.svelte.d.ts +17 -0
  30. package/dist/layout/RowContainer.svelte +32 -0
  31. package/dist/layout/Sidebar.svelte +104 -56
  32. package/dist/layout/SidebarContainer.svelte +32 -0
  33. package/dist/layout/SplitPane.svelte +32 -0
  34. package/dist/layout/Stack.svelte +32 -0
  35. package/dist/layout/TabBar.svelte +127 -8
  36. package/dist/layout/TabBar.svelte.d.ts +16 -0
  37. package/dist/layout/Table.svelte +60 -9
  38. package/dist/layout/Tile.svelte +89 -6
  39. package/dist/misc/CodeInner.svelte +32 -0
  40. package/dist/misc/Progress.svelte +32 -0
  41. package/dist/misc/Tag.svelte +32 -0
  42. package/dist/overlays/Dialog.svelte +32 -0
  43. package/dist/overlays/Tooltip.svelte +32 -0
  44. package/dist/sass/_responsive.scss +43 -0
  45. package/dist/typography/TextLayout.svelte +47 -0
  46. package/dist/vars/colors.css +21 -5
  47. package/dist/vars/defaults.css +25 -6
  48. package/dist/vars/layout.css +4 -1
  49. package/dist/vars/responsive-typography.css +4 -1
  50. package/package.json +1 -1
@@ -119,6 +119,38 @@ const el = $derived(elementProps({ ...restProps, marginTop, marginBottom }, "bar
119
119
  we deliberately avoid everywhere else.
120
120
 
121
121
  One definition, used by both, so they cannot drift again. */
122
+ /* The "small" size tier: a component whose container is this wide or less
123
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
124
+
125
+ The convention, shared by every component that has a size worth changing
126
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
127
+
128
+ --{component}-{property}-small
129
+
130
+ applies inside a small container. What wins there, in order:
131
+ 1. the `-small` variable, if you set it;
132
+ 2. otherwise the regular variable, if you set it -- a size you chose on
133
+ purpose is not overridden behind your back;
134
+ 3. otherwise the component's own small default, which for most
135
+ properties is simply its regular default.
136
+
137
+ Container queries can't read a custom property, so the breakpoint itself
138
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
139
+ which already switched there. (The Sidebar's rail-to-sheet switch,
140
+ above, is a separate, layout-chrome decision and keeps its own value.) */
141
+ /* Styles for the small tier: the nearest container is narrow, OR the
142
+ viewport is.
143
+
144
+ The container query is the real answer -- a Tile in a 400px pane on a
145
+ desktop is small. But a container query only matches inside an ancestor
146
+ that *is* a container, and a component dropped straight into a page (no
147
+ Page, no Container around it) has none, so on a phone it would never
148
+ find out. The viewport query covers that: a narrow viewport means every
149
+ container in it is narrow too, so the two never disagree in the
150
+ direction that matters.
151
+
152
+ An element never queries itself, so on a component that is its own
153
+ container (Tile, Bar) this asks about the space it was given. */
122
154
  /* Warning: because we define a fallback
123
155
  media query, the media query can override the container
124
156
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -256,6 +288,24 @@ const el = $derived(elementProps({ ...restProps, marginTop, marginBottom }, "bar
256
288
  --_heading-margin-inline: var-with-fallbacks(--heading-margin-inline, bar, 0);
257
289
  }
258
290
 
291
+ /* Small tier (see $small-max): --bar-padding-small, --bar-gap-small and
292
+ --bar-min-height-small, each falling back to the regular value. A bar
293
+ that should be slimmer on a phone says so once, here, instead of every
294
+ consumer writing its own query. */
295
+ @media (max-width: 600px) {
296
+ .bar {
297
+ padding: var(--bar-padding-small, var(--bar-padding, var(--padding, 8px)));
298
+ gap: var(--bar-gap-small, var(--bar-gap, var(--gap, 8px)));
299
+ min-height: var(--bar-min-height-small, var(--bar-min-height, var(--bar-height, 3em)));
300
+ }
301
+ }
302
+ @container (max-width: 600px) {
303
+ .bar {
304
+ padding: var(--bar-padding-small, var(--bar-padding, var(--padding, 8px)));
305
+ gap: var(--bar-gap-small, var(--bar-gap, var(--gap, 8px)));
306
+ min-height: var(--bar-min-height-small, var(--bar-min-height, var(--bar-height, 3em)));
307
+ }
308
+ }
259
309
  .bar :global(h1),
260
310
  .bar :global(h2),
261
311
  .bar :global(h3),
@@ -92,6 +92,38 @@ const el = $derived(elementProps(restProps, "column-container", COLUMN_CONTAINER
92
92
  we deliberately avoid everywhere else.
93
93
 
94
94
  One definition, used by both, so they cannot drift again. */
95
+ /* The "small" size tier: a component whose container is this wide or less
96
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
97
+
98
+ The convention, shared by every component that has a size worth changing
99
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
100
+
101
+ --{component}-{property}-small
102
+
103
+ applies inside a small container. What wins there, in order:
104
+ 1. the `-small` variable, if you set it;
105
+ 2. otherwise the regular variable, if you set it -- a size you chose on
106
+ purpose is not overridden behind your back;
107
+ 3. otherwise the component's own small default, which for most
108
+ properties is simply its regular default.
109
+
110
+ Container queries can't read a custom property, so the breakpoint itself
111
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
112
+ which already switched there. (The Sidebar's rail-to-sheet switch,
113
+ above, is a separate, layout-chrome decision and keeps its own value.) */
114
+ /* Styles for the small tier: the nearest container is narrow, OR the
115
+ viewport is.
116
+
117
+ The container query is the real answer -- a Tile in a 400px pane on a
118
+ desktop is small. But a container query only matches inside an ancestor
119
+ that *is* a container, and a component dropped straight into a page (no
120
+ Page, no Container around it) has none, so on a phone it would never
121
+ find out. The viewport query covers that: a narrow viewport means every
122
+ container in it is narrow too, so the two never disagree in the
123
+ direction that matters.
124
+
125
+ An element never queries itself, so on a component that is its own
126
+ container (Tile, Bar) this asks about the space it was given. */
95
127
  /* Warning: because we define a fallback
96
128
  media query, the media query can override the container
97
129
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -78,6 +78,38 @@ const el = $derived(elementProps(restProps, "columns", ["gap"]));
78
78
  we deliberately avoid everywhere else.
79
79
 
80
80
  One definition, used by both, so they cannot drift again. */
81
+ /* The "small" size tier: a component whose container is this wide or less
82
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
83
+
84
+ The convention, shared by every component that has a size worth changing
85
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
86
+
87
+ --{component}-{property}-small
88
+
89
+ applies inside a small container. What wins there, in order:
90
+ 1. the `-small` variable, if you set it;
91
+ 2. otherwise the regular variable, if you set it -- a size you chose on
92
+ purpose is not overridden behind your back;
93
+ 3. otherwise the component's own small default, which for most
94
+ properties is simply its regular default.
95
+
96
+ Container queries can't read a custom property, so the breakpoint itself
97
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
98
+ which already switched there. (The Sidebar's rail-to-sheet switch,
99
+ above, is a separate, layout-chrome decision and keeps its own value.) */
100
+ /* Styles for the small tier: the nearest container is narrow, OR the
101
+ viewport is.
102
+
103
+ The container query is the real answer -- a Tile in a 400px pane on a
104
+ desktop is small. But a container query only matches inside an ancestor
105
+ that *is* a container, and a component dropped straight into a page (no
106
+ Page, no Container around it) has none, so on a phone it would never
107
+ find out. The viewport query covers that: a narrow viewport means every
108
+ container in it is narrow too, so the two never disagree in the
109
+ direction that matters.
110
+
111
+ An element never queries itself, so on a component that is its own
112
+ container (Tile, Bar) this asks about the space it was given. */
81
113
  /* Warning: because we define a fallback
82
114
  media query, the media query can override the container
83
115
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -96,6 +96,38 @@ const el = $derived(elementProps(restProps, "container", [
96
96
  we deliberately avoid everywhere else.
97
97
 
98
98
  One definition, used by both, so they cannot drift again. */
99
+ /* The "small" size tier: a component whose container is this wide or less
100
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
101
+
102
+ The convention, shared by every component that has a size worth changing
103
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
104
+
105
+ --{component}-{property}-small
106
+
107
+ applies inside a small container. What wins there, in order:
108
+ 1. the `-small` variable, if you set it;
109
+ 2. otherwise the regular variable, if you set it -- a size you chose on
110
+ purpose is not overridden behind your back;
111
+ 3. otherwise the component's own small default, which for most
112
+ properties is simply its regular default.
113
+
114
+ Container queries can't read a custom property, so the breakpoint itself
115
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
116
+ which already switched there. (The Sidebar's rail-to-sheet switch,
117
+ above, is a separate, layout-chrome decision and keeps its own value.) */
118
+ /* Styles for the small tier: the nearest container is narrow, OR the
119
+ viewport is.
120
+
121
+ The container query is the real answer -- a Tile in a 400px pane on a
122
+ desktop is small. But a container query only matches inside an ancestor
123
+ that *is* a container, and a component dropped straight into a page (no
124
+ Page, no Container around it) has none, so on a phone it would never
125
+ find out. The viewport query covers that: a narrow viewport means every
126
+ container in it is narrow too, so the two never disagree in the
127
+ direction that matters.
128
+
129
+ An element never queries itself, so on a component that is its own
130
+ container (Tile, Bar) this asks about the space it was given. */
99
131
  /* Warning: because we define a fallback
100
132
  media query, the media query can override the container
101
133
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -417,9 +449,11 @@ section {
417
449
  of fighting a single shared value for both. */
418
450
  margin-inline: var(--container-margin-inline, var(--surface-margin-inline, var(--block-margin-inline, var(--margin-inline, auto))));
419
451
  margin-block: var(--container-margin-block, var(--surface-margin-block, var(--block-margin-block, var(--margin-block, var(--gap)))));
420
- /* Why is this suddenly causing a scroll? */
421
452
  container-type: inline-size;
422
- overflow-x: hidden;
453
+ /* Scroll, never clip: content wider than the container (a table, a
454
+ wide grid, a long unbroken string) must stay reachable on a narrow
455
+ screen. `hidden` here made it unreachable on phones. */
456
+ overflow-x: auto;
423
457
  height: var(--container-height, 100%);
424
458
  overflow-y: auto;
425
459
  overflow-y: auto;
@@ -460,6 +494,18 @@ section {
460
494
  width: var(--container-width, 100%);
461
495
  }
462
496
 
497
+ /* Small tier (see $small-max): --container-padding-small, falling back to
498
+ the regular padding. */
499
+ @media (max-width: 600px) {
500
+ section {
501
+ padding: var(--container-padding-small, var(--container-padding, var(--surface-padding, var(--block-padding, var(--padding, 8px)))));
502
+ }
503
+ }
504
+ @container (max-width: 600px) {
505
+ section {
506
+ padding: var(--container-padding-small, var(--container-padding, var(--surface-padding, var(--block-padding, var(--padding, 8px)))));
507
+ }
508
+ }
463
509
  .border {
464
510
  border: var(--container-border, var(--surface-border, var(--border, var(--border-width) var(--border-style) var(--border-color))));
465
511
  }</style>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">import { elementProps } from "../util";
2
2
  import { COLOR_VARS, PADDING_VARS, RADIUS_VARS, TYPOGRAPHY_VARS, } from "../styleProps";
3
- let { children, stackable = false, class: className, ...restProps } = $props();
3
+ let { children, stackable = true, class: className, ...restProps } = $props();
4
4
  /* The shorthands data-list's own CSS backs, one group per mixin it
5
5
  includes. The Props type is derived from this same array, so what the
6
6
  component accepts and what it emits cannot drift apart. */
@@ -115,6 +115,38 @@ const el = $derived(elementProps(restProps, "data-list", [
115
115
  we deliberately avoid everywhere else.
116
116
 
117
117
  One definition, used by both, so they cannot drift again. */
118
+ /* The "small" size tier: a component whose container is this wide or less
119
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
120
+
121
+ The convention, shared by every component that has a size worth changing
122
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
123
+
124
+ --{component}-{property}-small
125
+
126
+ applies inside a small container. What wins there, in order:
127
+ 1. the `-small` variable, if you set it;
128
+ 2. otherwise the regular variable, if you set it -- a size you chose on
129
+ purpose is not overridden behind your back;
130
+ 3. otherwise the component's own small default, which for most
131
+ properties is simply its regular default.
132
+
133
+ Container queries can't read a custom property, so the breakpoint itself
134
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
135
+ which already switched there. (The Sidebar's rail-to-sheet switch,
136
+ above, is a separate, layout-chrome decision and keeps its own value.) */
137
+ /* Styles for the small tier: the nearest container is narrow, OR the
138
+ viewport is.
139
+
140
+ The container query is the real answer -- a Tile in a 400px pane on a
141
+ desktop is small. But a container query only matches inside an ancestor
142
+ that *is* a container, and a component dropped straight into a page (no
143
+ Page, no Container around it) has none, so on a phone it would never
144
+ find out. The viewport query covers that: a narrow viewport means every
145
+ container in it is narrow too, so the two never disagree in the
146
+ direction that matters.
147
+
148
+ An element never queries itself, so on a component that is its own
149
+ container (Tile, Bar) this asks about the space it was given. */
118
150
  /* Warning: because we define a fallback
119
151
  media query, the media query can override the container
120
152
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -4,6 +4,13 @@ import type { BaseStyleProps, ContainProps } from "../types";
4
4
  import { type StyleProps } from "../styleProps";
5
5
  declare const DataList: import("svelte").Component<ContainProps<HTMLAttributes<HTMLUListElement>, {
6
6
  children?: Snippet;
7
+ /**
8
+ * In the small tier (a container or viewport 600px or narrower), move
9
+ * each row's `end` region -- tags, buttons -- onto its own line under
10
+ * the main content instead of squeezing the main column to a sliver.
11
+ * On by default; pass `stackable={false}` for rows whose end region is
12
+ * small enough to stay beside the content on a phone.
13
+ */
7
14
  stackable?: boolean;
8
15
  }, BaseStyleProps & {
9
16
  marginInline?: string | null;
@@ -193,6 +193,38 @@ function handleKeydown(event) {
193
193
  we deliberately avoid everywhere else.
194
194
 
195
195
  One definition, used by both, so they cannot drift again. */
196
+ /* The "small" size tier: a component whose container is this wide or less
197
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
198
+
199
+ The convention, shared by every component that has a size worth changing
200
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
201
+
202
+ --{component}-{property}-small
203
+
204
+ applies inside a small container. What wins there, in order:
205
+ 1. the `-small` variable, if you set it;
206
+ 2. otherwise the regular variable, if you set it -- a size you chose on
207
+ purpose is not overridden behind your back;
208
+ 3. otherwise the component's own small default, which for most
209
+ properties is simply its regular default.
210
+
211
+ Container queries can't read a custom property, so the breakpoint itself
212
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
213
+ which already switched there. (The Sidebar's rail-to-sheet switch,
214
+ above, is a separate, layout-chrome decision and keeps its own value.) */
215
+ /* Styles for the small tier: the nearest container is narrow, OR the
216
+ viewport is.
217
+
218
+ The container query is the real answer -- a Tile in a 400px pane on a
219
+ desktop is small. But a container query only matches inside an ancestor
220
+ that *is* a container, and a component dropped straight into a page (no
221
+ Page, no Container around it) has none, so on a phone it would never
222
+ find out. The viewport query covers that: a narrow viewport means every
223
+ container in it is narrow too, so the two never disagree in the
224
+ direction that matters.
225
+
226
+ An element never queries itself, so on a component that is its own
227
+ container (Tile, Bar) this asks about the space it was given. */
196
228
  /* Warning: because we define a fallback
197
229
  media query, the media query can override the container
198
230
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -646,9 +678,31 @@ function handleKeydown(event) {
646
678
  border-top-width: 0;
647
679
  }
648
680
 
649
- @container (max-width: 640px) {
681
+ /* The shared small tier ($small-max). Text keeps its size here -- a phone
682
+ is the last place to make it smaller; --data-list-item-font-size-small
683
+ is there for anyone who wants it anyway. */
684
+ @media (max-width: 600px) {
685
+ .data-list-item {
686
+ font-size: var(--data-list-item-font-size-small, var(--_font-size));
687
+ }
688
+ :global(.data-list.stackable) .data-list-item.hasStart.hasEnd {
689
+ grid-template-columns: var(--data-list-item-icon-width, var(--data-list-icon-width, var(--icon-width, var(--data-list-item-icon-size, var(--data-list-icon-size, var(--icon-size, 2.5rem)))))) minmax(0, 1fr);
690
+ grid-template-areas: "start main" "end end";
691
+ }
692
+ :global(.data-list.stackable) .data-list-item.hasStart.hasEnd .end {
693
+ flex-direction: var(--data-list-item-action-compact-flex-direction, var(--data-list-action-compact-flex-direction, var(--action-compact-flex-direction, row)));
694
+ flex-wrap: var(--data-list-item-action-compact-wrap, var(--data-list-action-compact-wrap, var(--action-compact-wrap, wrap)));
695
+ justify-content: var(--data-list-item-action-mobile-justify, var(--data-list-action-mobile-justify, var(--action-mobile-justify, flex-start)));
696
+ padding-inline-start: calc(var(--data-list-item-icon-width, var(--data-list-icon-width, var(--icon-width, var(--data-list-item-icon-size, var(--data-list-icon-size, var(--icon-size, 2.5rem)))))) + var(--data-list-item-gap, var(--data-list-gap, var(--gap, var(--space)))));
697
+ }
698
+ :global(.data-list.stackable) .data-list-item:not(.hasStart).hasEnd {
699
+ grid-template-columns: minmax(0, 1fr);
700
+ grid-template-areas: "main" "end";
701
+ }
702
+ }
703
+ @container (max-width: 600px) {
650
704
  .data-list-item {
651
- font-size: var(--data-list-item-font-size-small, calc(0.9 * var(--_font-size)));
705
+ font-size: var(--data-list-item-font-size-small, var(--_font-size));
652
706
  }
653
707
  :global(.data-list.stackable) .data-list-item.hasStart.hasEnd {
654
708
  grid-template-columns: var(--data-list-item-icon-width, var(--data-list-icon-width, var(--icon-width, var(--data-list-item-icon-size, var(--data-list-icon-size, var(--icon-size, 2.5rem)))))) minmax(0, 1fr);
@@ -125,6 +125,38 @@ const el = $derived(elementProps({
125
125
  we deliberately avoid everywhere else.
126
126
 
127
127
  One definition, used by both, so they cannot drift again. */
128
+ /* The "small" size tier: a component whose container is this wide or less
129
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
130
+
131
+ The convention, shared by every component that has a size worth changing
132
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
133
+
134
+ --{component}-{property}-small
135
+
136
+ applies inside a small container. What wins there, in order:
137
+ 1. the `-small` variable, if you set it;
138
+ 2. otherwise the regular variable, if you set it -- a size you chose on
139
+ purpose is not overridden behind your back;
140
+ 3. otherwise the component's own small default, which for most
141
+ properties is simply its regular default.
142
+
143
+ Container queries can't read a custom property, so the breakpoint itself
144
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
145
+ which already switched there. (The Sidebar's rail-to-sheet switch,
146
+ above, is a separate, layout-chrome decision and keeps its own value.) */
147
+ /* Styles for the small tier: the nearest container is narrow, OR the
148
+ viewport is.
149
+
150
+ The container query is the real answer -- a Tile in a 400px pane on a
151
+ desktop is small. But a container query only matches inside an ancestor
152
+ that *is* a container, and a component dropped straight into a page (no
153
+ Page, no Container around it) has none, so on a phone it would never
154
+ find out. The viewport query covers that: a narrow viewport means every
155
+ container in it is narrow too, so the two never disagree in the
156
+ direction that matters.
157
+
158
+ An element never queries itself, so on a component that is its own
159
+ container (Tile, Bar) this asks about the space it was given. */
128
160
  /* Warning: because we define a fallback
129
161
  media query, the media query can override the container
130
162
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -123,6 +123,38 @@ const el = $derived(elementProps({
123
123
  we deliberately avoid everywhere else.
124
124
 
125
125
  One definition, used by both, so they cannot drift again. */
126
+ /* The "small" size tier: a component whose container is this wide or less
127
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
128
+
129
+ The convention, shared by every component that has a size worth changing
130
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
131
+
132
+ --{component}-{property}-small
133
+
134
+ applies inside a small container. What wins there, in order:
135
+ 1. the `-small` variable, if you set it;
136
+ 2. otherwise the regular variable, if you set it -- a size you chose on
137
+ purpose is not overridden behind your back;
138
+ 3. otherwise the component's own small default, which for most
139
+ properties is simply its regular default.
140
+
141
+ Container queries can't read a custom property, so the breakpoint itself
142
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
143
+ which already switched there. (The Sidebar's rail-to-sheet switch,
144
+ above, is a separate, layout-chrome decision and keeps its own value.) */
145
+ /* Styles for the small tier: the nearest container is narrow, OR the
146
+ viewport is.
147
+
148
+ The container query is the real answer -- a Tile in a 400px pane on a
149
+ desktop is small. But a container query only matches inside an ancestor
150
+ that *is* a container, and a component dropped straight into a page (no
151
+ Page, no Container around it) has none, so on a phone it would never
152
+ find out. The viewport query covers that: a narrow viewport means every
153
+ container in it is narrow too, so the two never disagree in the
154
+ direction that matters.
155
+
156
+ An element never queries itself, so on a component that is its own
157
+ container (Tile, Bar) this asks about the space it was given. */
126
158
  /* Warning: because we define a fallback
127
159
  media query, the media query can override the container
128
160
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -112,6 +112,38 @@ const effectiveLayout = $derived(above ? "above" : below ? "below" : effectiveLa
112
112
  we deliberately avoid everywhere else.
113
113
 
114
114
  One definition, used by both, so they cannot drift again. */
115
+ /* The "small" size tier: a component whose container is this wide or less
116
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
117
+
118
+ The convention, shared by every component that has a size worth changing
119
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
120
+
121
+ --{component}-{property}-small
122
+
123
+ applies inside a small container. What wins there, in order:
124
+ 1. the `-small` variable, if you set it;
125
+ 2. otherwise the regular variable, if you set it -- a size you chose on
126
+ purpose is not overridden behind your back;
127
+ 3. otherwise the component's own small default, which for most
128
+ properties is simply its regular default.
129
+
130
+ Container queries can't read a custom property, so the breakpoint itself
131
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
132
+ which already switched there. (The Sidebar's rail-to-sheet switch,
133
+ above, is a separate, layout-chrome decision and keeps its own value.) */
134
+ /* Styles for the small tier: the nearest container is narrow, OR the
135
+ viewport is.
136
+
137
+ The container query is the real answer -- a Tile in a 400px pane on a
138
+ desktop is small. But a container query only matches inside an ancestor
139
+ that *is* a container, and a component dropped straight into a page (no
140
+ Page, no Container around it) has none, so on a phone it would never
141
+ find out. The viewport query covers that: a narrow viewport means every
142
+ container in it is narrow too, so the two never disagree in the
143
+ direction that matters.
144
+
145
+ An element never queries itself, so on a component that is its own
146
+ container (Tile, Bar) this asks about the space it was given. */
115
147
  /* Warning: because we define a fallback
116
148
  media query, the media query can override the container
117
149
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -206,15 +238,29 @@ label {
206
238
  display: contents;
207
239
  }
208
240
 
241
+ /* Label and input widths are what they'd like, not what they insist on:
242
+ a 12em label above its input in a 15em-wide collapsed item, or a fixed
243
+ input width beside a label in a narrow column, gives way to the item. */
209
244
  .label {
210
245
  box-sizing: border-box;
211
246
  width: var(--form-label-width, 12em);
247
+ max-width: 100%;
212
248
  text-align: var(--form-label-text-align, right);
213
249
  }
214
250
 
215
251
  .input {
216
252
  box-sizing: border-box;
217
253
  width: var(--form-input-fixed-width, var(--form-input-width));
254
+ max-width: 100%;
255
+ min-width: 0;
256
+ }
257
+
258
+ /* A native input's intrinsic width (~20 characters) is a default, not a
259
+ requirement -- in a narrow item it fits the space it has. */
260
+ .input :global(input),
261
+ .input :global(select),
262
+ .input :global(textarea) {
263
+ max-width: 100%;
218
264
  }
219
265
 
220
266
  /* In grid layouts, make the input area stretch fully */
@@ -93,6 +93,38 @@ const el = $derived(elementProps(restProps, "grid-layout", GRID_LAYOUT_VARS));
93
93
  we deliberately avoid everywhere else.
94
94
 
95
95
  One definition, used by both, so they cannot drift again. */
96
+ /* The "small" size tier: a component whose container is this wide or less
97
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
98
+
99
+ The convention, shared by every component that has a size worth changing
100
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
101
+
102
+ --{component}-{property}-small
103
+
104
+ applies inside a small container. What wins there, in order:
105
+ 1. the `-small` variable, if you set it;
106
+ 2. otherwise the regular variable, if you set it -- a size you chose on
107
+ purpose is not overridden behind your back;
108
+ 3. otherwise the component's own small default, which for most
109
+ properties is simply its regular default.
110
+
111
+ Container queries can't read a custom property, so the breakpoint itself
112
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
113
+ which already switched there. (The Sidebar's rail-to-sheet switch,
114
+ above, is a separate, layout-chrome decision and keeps its own value.) */
115
+ /* Styles for the small tier: the nearest container is narrow, OR the
116
+ viewport is.
117
+
118
+ The container query is the real answer -- a Tile in a 400px pane on a
119
+ desktop is small. But a container query only matches inside an ancestor
120
+ that *is* a container, and a component dropped straight into a page (no
121
+ Page, no Container around it) has none, so on a phone it would never
122
+ find out. The viewport query covers that: a narrow viewport means every
123
+ container in it is narrow too, so the two never disagree in the
124
+ direction that matters.
125
+
126
+ An element never queries itself, so on a component that is its own
127
+ container (Tile, Bar) this asks about the space it was given. */
96
128
  /* Warning: because we define a fallback
97
129
  media query, the media query can override the container
98
130
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -224,4 +256,31 @@ const el = $derived(elementProps(restProps, "grid-layout", GRID_LAYOUT_VARS));
224
256
  narrower than the track it was handed -- a `--tile-width` set smaller than
225
257
  the grid's item width, say. */
226
258
  --justify-items: center;
259
+ }
260
+
261
+ /* Small tier (see $small-max). Tile tracks follow the tile's own small
262
+ width -- same precedence, same default -- or a phone gets 160px tiles in
263
+ 192px tracks, one to a row. (Card tracks are already capped at 100% of
264
+ the grid by the `min()` above.) */
265
+ @media (max-width: 600px) {
266
+ .tile-grid {
267
+ --item-width: var(
268
+ --tile-width-small,
269
+ var(--tile-width, calc(var(--space-lg, 8px) * 20))
270
+ );
271
+ }
272
+ .grid-layout {
273
+ gap: var(--grid-layout-gap-small, var(--grid-layout-gap, var(--gap, 8px)));
274
+ }
275
+ }
276
+ @container (max-width: 600px) {
277
+ .tile-grid {
278
+ --item-width: var(
279
+ --tile-width-small,
280
+ var(--tile-width, calc(var(--space-lg, 8px) * 20))
281
+ );
282
+ }
283
+ .grid-layout {
284
+ gap: var(--grid-layout-gap-small, var(--grid-layout-gap, var(--gap, 8px)));
285
+ }
227
286
  }</style>
@@ -97,6 +97,38 @@ const el = $derived(elementProps(restProps, "hero", [
97
97
  we deliberately avoid everywhere else.
98
98
 
99
99
  One definition, used by both, so they cannot drift again. */
100
+ /* The "small" size tier: a component whose container is this wide or less
101
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
102
+
103
+ The convention, shared by every component that has a size worth changing
104
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
105
+
106
+ --{component}-{property}-small
107
+
108
+ applies inside a small container. What wins there, in order:
109
+ 1. the `-small` variable, if you set it;
110
+ 2. otherwise the regular variable, if you set it -- a size you chose on
111
+ purpose is not overridden behind your back;
112
+ 3. otherwise the component's own small default, which for most
113
+ properties is simply its regular default.
114
+
115
+ Container queries can't read a custom property, so the breakpoint itself
116
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
117
+ which already switched there. (The Sidebar's rail-to-sheet switch,
118
+ above, is a separate, layout-chrome decision and keeps its own value.) */
119
+ /* Styles for the small tier: the nearest container is narrow, OR the
120
+ viewport is.
121
+
122
+ The container query is the real answer -- a Tile in a 400px pane on a
123
+ desktop is small. But a container query only matches inside an ancestor
124
+ that *is* a container, and a component dropped straight into a page (no
125
+ Page, no Container around it) has none, so on a phone it would never
126
+ find out. The viewport query covers that: a narrow viewport means every
127
+ container in it is narrow too, so the two never disagree in the
128
+ direction that matters.
129
+
130
+ An element never queries itself, so on a component that is its own
131
+ container (Tile, Bar) this asks about the space it was given. */
100
132
  /* Warning: because we define a fallback
101
133
  media query, the media query can override the container
102
134
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -393,6 +425,16 @@ const el = $derived(elementProps(restProps, "hero", [
393
425
  width: var(--hero-width, 100%);
394
426
  max-width: var(--hero-width, 100%);
395
427
  height: var(--hero-height, 100vh);
428
+ /* Small-viewport units where supported: on a phone, 100vh is the height
429
+ with the browser's toolbars *hidden*, so a full-height hero's content
430
+ sits partly under them on first load. */
431
+ height: var(--hero-height, 100svh);
432
+ /* Without inline padding, centred hero text runs right to the screen's
433
+ edges the moment the viewport is narrower than its longest line. */
434
+ padding-inline: var(--hero-padding-inline, var(--padding, 1rem));
435
+ /* Lets hero content size itself to the hero (cqi units, @container)
436
+ rather than to the viewport. */
437
+ container-type: inline-size;
396
438
  /* font-size: var(--hero-font-size, 2rem); */
397
439
  box-sizing: border-box;
398
440
  }