contain-css-svelte 1.4.3 → 1.6.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 (57) 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/GroupedRadioItem.svelte +551 -0
  7. package/dist/controls/GroupedRadioItem.svelte.d.ts +36 -0
  8. package/dist/controls/GroupedToggle.svelte +147 -0
  9. package/dist/controls/GroupedToggle.svelte.d.ts +9 -0
  10. package/dist/controls/GroupedToggleItem.svelte +452 -0
  11. package/dist/controls/GroupedToggleItem.svelte.d.ts +31 -0
  12. package/dist/controls/Input.svelte +32 -0
  13. package/dist/controls/RadioButton.svelte +36 -1
  14. package/dist/controls/Select.svelte +80 -2
  15. package/dist/controls/Slider.svelte +32 -0
  16. package/dist/controls/TabItem.svelte +36 -0
  17. package/dist/controls/Toggle.svelte +32 -0
  18. package/dist/dropdowns/DropdownMenu.svelte +53 -1
  19. package/dist/index.d.ts +4 -0
  20. package/dist/index.js +4 -0
  21. package/dist/layout/Accordion.svelte +32 -0
  22. package/dist/layout/Bar.svelte +50 -0
  23. package/dist/layout/ColumnContainer.svelte +32 -0
  24. package/dist/layout/Columns.svelte +32 -0
  25. package/dist/layout/Container.svelte +48 -2
  26. package/dist/layout/DataList.svelte +33 -1
  27. package/dist/layout/DataList.svelte.d.ts +7 -0
  28. package/dist/layout/DataListItem.svelte +56 -2
  29. package/dist/layout/Fieldset.svelte +32 -0
  30. package/dist/layout/Form.svelte +32 -0
  31. package/dist/layout/FormItem.svelte +46 -0
  32. package/dist/layout/GridLayout.svelte +59 -0
  33. package/dist/layout/Hero.svelte +42 -0
  34. package/dist/layout/Inline.svelte +37 -1
  35. package/dist/layout/MenuList.svelte +32 -0
  36. package/dist/layout/Page.svelte +137 -10
  37. package/dist/layout/Page.svelte.d.ts +17 -0
  38. package/dist/layout/RowContainer.svelte +32 -0
  39. package/dist/layout/Sidebar.svelte +104 -56
  40. package/dist/layout/SidebarContainer.svelte +32 -0
  41. package/dist/layout/SplitPane.svelte +32 -0
  42. package/dist/layout/Stack.svelte +32 -0
  43. package/dist/layout/TabBar.svelte +127 -8
  44. package/dist/layout/TabBar.svelte.d.ts +16 -0
  45. package/dist/layout/Table.svelte +60 -9
  46. package/dist/layout/Tile.svelte +89 -6
  47. package/dist/misc/CodeInner.svelte +32 -0
  48. package/dist/misc/Progress.svelte +32 -0
  49. package/dist/misc/Tag.svelte +32 -0
  50. package/dist/overlays/Dialog.svelte +32 -0
  51. package/dist/overlays/Tooltip.svelte +32 -0
  52. package/dist/sass/_responsive.scss +43 -0
  53. package/dist/typography/TextLayout.svelte +47 -0
  54. package/dist/vars/defaults.css +4 -1
  55. package/dist/vars/layout.css +4 -1
  56. package/dist/vars/responsive-typography.css +4 -1
  57. package/package.json +1 -1
@@ -86,6 +86,38 @@ const el = $derived(elementProps(restProps, "input", INPUT_VARS));
86
86
  we deliberately avoid everywhere else.
87
87
 
88
88
  One definition, used by both, so they cannot drift again. */
89
+ /* The "small" size tier: a component whose container is this wide or less
90
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
91
+
92
+ The convention, shared by every component that has a size worth changing
93
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
94
+
95
+ --{component}-{property}-small
96
+
97
+ applies inside a small container. What wins there, in order:
98
+ 1. the `-small` variable, if you set it;
99
+ 2. otherwise the regular variable, if you set it -- a size you chose on
100
+ purpose is not overridden behind your back;
101
+ 3. otherwise the component's own small default, which for most
102
+ properties is simply its regular default.
103
+
104
+ Container queries can't read a custom property, so the breakpoint itself
105
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
106
+ which already switched there. (The Sidebar's rail-to-sheet switch,
107
+ above, is a separate, layout-chrome decision and keeps its own value.) */
108
+ /* Styles for the small tier: the nearest container is narrow, OR the
109
+ viewport is.
110
+
111
+ The container query is the real answer -- a Tile in a 400px pane on a
112
+ desktop is small. But a container query only matches inside an ancestor
113
+ that *is* a container, and a component dropped straight into a page (no
114
+ Page, no Container around it) has none, so on a phone it would never
115
+ find out. The viewport query covers that: a narrow viewport means every
116
+ container in it is narrow too, so the two never disagree in the
117
+ direction that matters.
118
+
119
+ An element never queries itself, so on a component that is its own
120
+ container (Tile, Bar) this asks about the space it was given. */
89
121
  /* Warning: because we define a fallback
90
122
  media query, the media query can override the container
91
123
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -113,6 +113,38 @@ function handleChange() {
113
113
  we deliberately avoid everywhere else.
114
114
 
115
115
  One definition, used by both, so they cannot drift again. */
116
+ /* The "small" size tier: a component whose container is this wide or less
117
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
118
+
119
+ The convention, shared by every component that has a size worth changing
120
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
121
+
122
+ --{component}-{property}-small
123
+
124
+ applies inside a small container. What wins there, in order:
125
+ 1. the `-small` variable, if you set it;
126
+ 2. otherwise the regular variable, if you set it -- a size you chose on
127
+ purpose is not overridden behind your back;
128
+ 3. otherwise the component's own small default, which for most
129
+ properties is simply its regular default.
130
+
131
+ Container queries can't read a custom property, so the breakpoint itself
132
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
133
+ which already switched there. (The Sidebar's rail-to-sheet switch,
134
+ above, is a separate, layout-chrome decision and keeps its own value.) */
135
+ /* Styles for the small tier: the nearest container is narrow, OR the
136
+ viewport is.
137
+
138
+ The container query is the real answer -- a Tile in a 400px pane on a
139
+ desktop is small. But a container query only matches inside an ancestor
140
+ that *is* a container, and a component dropped straight into a page (no
141
+ Page, no Container around it) has none, so on a phone it would never
142
+ find out. The viewport query covers that: a narrow viewport means every
143
+ container in it is narrow too, so the two never disagree in the
144
+ direction that matters.
145
+
146
+ An element never queries itself, so on a component that is its own
147
+ container (Tile, Bar) this asks about the space it was given. */
116
148
  /* Warning: because we define a fallback
117
149
  media query, the media query can override the container
118
150
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -123,6 +155,10 @@ function handleChange() {
123
155
  .label-sizing-box {
124
156
  position: relative;
125
157
  display: inline-block;
158
+ /* An inline-block wraps as a whole first, so short labels in a row just
159
+ flow onto the next line; only a label longer than the whole row wraps
160
+ its own text (the invisible sizer and the real label wrap alike). */
161
+ max-width: 100%;
126
162
  }
127
163
 
128
164
  .label-sizing-box .radio-item {
@@ -176,7 +212,6 @@ label.radio-item {
176
212
  box-sizing: border-box;
177
213
  user-select: none;
178
214
  gap: var(--radio-button-space, var(--toggle-space, var(--space-md)));
179
- white-space: nowrap;
180
215
  cursor: var(--radio-button-cursor, var(--clickable-cursor, var(--cursor, pointer)));
181
216
  }
182
217
 
@@ -18,6 +18,9 @@ let observer;
18
18
  let resizeObserver;
19
19
  let targetWidth = $state("");
20
20
  let optionButtons = $state([]);
21
+ // The subset of optionButtons the resize observer is currently watching, so
22
+ // the $effect below can tell "nothing changed" from "rewire".
23
+ let observedButtons = [];
21
24
  onMount(() => {
22
25
  tick().then(() => updateOptions());
23
26
  /*
@@ -40,14 +43,37 @@ onMount(() => {
40
43
  attributeFilter: ["data-html", "value", "label", "selected"],
41
44
  });
42
45
  }
43
- // Observe size changes in option buttons
44
46
  resizeObserver = new ResizeObserver(() => updateTargetWidth());
45
- optionButtons.forEach((button) => resizeObserver.observe(button));
46
47
  return () => {
47
48
  observer.disconnect();
48
49
  resizeObserver.disconnect();
49
50
  };
50
51
  });
52
+ /*
53
+ optionButtons is populated by `bind:this` inside the {#each options}
54
+ block below, so it only ever reflects the CURRENT option list once Svelte
55
+ has reconciled the DOM -- which happens asynchronously relative to the
56
+ updateOptions() call that rebuilt `options`. Re-deriving the observed set
57
+ here, every time that binding changes, is what keeps the ResizeObserver
58
+ in sync in both directions: a button added once the list grows longer
59
+ gets observed, and one removed when the list shrinks is dropped instead
60
+ of lingering as a stale (and eventually null) target.
61
+
62
+ Guarded by reference comparison so an unrelated re-render that leaves the
63
+ same buttons in place doesn't thrash disconnect()/observe() every time.
64
+ */
65
+ $effect(() => {
66
+ if (!resizeObserver)
67
+ return;
68
+ const current = optionButtons.filter((button) => Boolean(button));
69
+ const unchanged = current.length === observedButtons.length &&
70
+ current.every((button, i) => button === observedButtons[i]);
71
+ if (unchanged)
72
+ return;
73
+ resizeObserver.disconnect();
74
+ current.forEach((button) => resizeObserver.observe(button));
75
+ observedButtons = current;
76
+ });
51
77
  let options = $state([]);
52
78
  let activeOption = $state(null);
53
79
  let updateQueued = false;
@@ -73,12 +99,29 @@ function updateOptions() {
73
99
  html: richHtml.trim(),
74
100
  });
75
101
  }
102
+ /*
103
+ optionButtons is bound by index from the {#each options} block below,
104
+ so when the option list shrinks, the array's tail is left holding
105
+ targets for <li>s that no longer render. (Svelte nulls each removed
106
+ binding's own slot as it tears the element down, but that happens once
107
+ the DOM catches up with this reassignment, not synchronously here --
108
+ so truncate now rather than leave the old length around in the
109
+ meantime.) Trimming it here, before the {#each} re-renders, keeps it
110
+ from ever describing more options than currently exist.
111
+ */
112
+ if (optionButtons.length > options.length) {
113
+ optionButtons.length = options.length;
114
+ }
76
115
  activeOption = options[selectElement.selectedIndex];
77
116
  updateTargetWidth();
78
117
  }
79
118
  function updateTargetWidth() {
80
119
  let maxWidth = 0;
81
120
  for (let button of optionButtons) {
121
+ // A stale or not-yet-bound slot (see updateOptions() above) -- skip it
122
+ // rather than crash on a null bind:this target.
123
+ if (!button)
124
+ continue;
82
125
  if (button.offsetWidth > maxWidth) {
83
126
  maxWidth = button.offsetWidth;
84
127
  }
@@ -212,6 +255,38 @@ $effect(() => {
212
255
  we deliberately avoid everywhere else.
213
256
 
214
257
  One definition, used by both, so they cannot drift again. */
258
+ /* The "small" size tier: a component whose container is this wide or less
259
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
260
+
261
+ The convention, shared by every component that has a size worth changing
262
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
263
+
264
+ --{component}-{property}-small
265
+
266
+ applies inside a small container. What wins there, in order:
267
+ 1. the `-small` variable, if you set it;
268
+ 2. otherwise the regular variable, if you set it -- a size you chose on
269
+ purpose is not overridden behind your back;
270
+ 3. otherwise the component's own small default, which for most
271
+ properties is simply its regular default.
272
+
273
+ Container queries can't read a custom property, so the breakpoint itself
274
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
275
+ which already switched there. (The Sidebar's rail-to-sheet switch,
276
+ above, is a separate, layout-chrome decision and keeps its own value.) */
277
+ /* Styles for the small tier: the nearest container is narrow, OR the
278
+ viewport is.
279
+
280
+ The container query is the real answer -- a Tile in a 400px pane on a
281
+ desktop is small. But a container query only matches inside an ancestor
282
+ that *is* a container, and a component dropped straight into a page (no
283
+ Page, no Container around it) has none, so on a phone it would never
284
+ find out. The viewport query covers that: a narrow viewport means every
285
+ container in it is narrow too, so the two never disagree in the
286
+ direction that matters.
287
+
288
+ An element never queries itself, so on a component that is its own
289
+ container (Tile, Bar) this asks about the space it was given. */
215
290
  /* Warning: because we define a fallback
216
291
  media query, the media query can override the container
217
292
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -318,6 +393,9 @@ select,
318
393
  background-color: var(--_background-color);
319
394
  color: var(--_color);
320
395
  width: var(--select-width, var(--target-width, var(--dropdown-menu-width, min(12em, 100vw))));
396
+ /* The measured width fits the longest option; the container may be
397
+ narrower than that. Truncate (below) rather than overflow. */
398
+ max-width: 100%;
321
399
  text-overflow: ellipsis;
322
400
  font-family: var(--select-font-family, var(--input-font-family, var(--ui-font-family, var(--font-family, unset))));
323
401
  text-transform: var(--select-text-transform, var(--input-text-transform, var(--ui-text-transform, var(--text-transform, unset))));
@@ -88,6 +88,38 @@ const el = $derived(elementProps(restProps, "slider", ["bg", "fg", "padding", "w
88
88
  we deliberately avoid everywhere else.
89
89
 
90
90
  One definition, used by both, so they cannot drift again. */
91
+ /* The "small" size tier: a component whose container is this wide or less
92
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
93
+
94
+ The convention, shared by every component that has a size worth changing
95
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
96
+
97
+ --{component}-{property}-small
98
+
99
+ applies inside a small container. What wins there, in order:
100
+ 1. the `-small` variable, if you set it;
101
+ 2. otherwise the regular variable, if you set it -- a size you chose on
102
+ purpose is not overridden behind your back;
103
+ 3. otherwise the component's own small default, which for most
104
+ properties is simply its regular default.
105
+
106
+ Container queries can't read a custom property, so the breakpoint itself
107
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
108
+ which already switched there. (The Sidebar's rail-to-sheet switch,
109
+ above, is a separate, layout-chrome decision and keeps its own value.) */
110
+ /* Styles for the small tier: the nearest container is narrow, OR the
111
+ viewport is.
112
+
113
+ The container query is the real answer -- a Tile in a 400px pane on a
114
+ desktop is small. But a container query only matches inside an ancestor
115
+ that *is* a container, and a component dropped straight into a page (no
116
+ Page, no Container around it) has none, so on a phone it would never
117
+ find out. The viewport query covers that: a narrow viewport means every
118
+ container in it is narrow too, so the two never disagree in the
119
+ direction that matters.
120
+
121
+ An element never queries itself, so on a component that is its own
122
+ container (Tile, Bar) this asks about the space it was given. */
91
123
  /* Warning: because we define a fallback
92
124
  media query, the media query can override the container
93
125
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -100,6 +100,38 @@ const el = $derived(elementProps(restProps, "tab", [
100
100
  we deliberately avoid everywhere else.
101
101
 
102
102
  One definition, used by both, so they cannot drift again. */
103
+ /* The "small" size tier: a component whose container is this wide or less
104
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
105
+
106
+ The convention, shared by every component that has a size worth changing
107
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
108
+
109
+ --{component}-{property}-small
110
+
111
+ applies inside a small container. What wins there, in order:
112
+ 1. the `-small` variable, if you set it;
113
+ 2. otherwise the regular variable, if you set it -- a size you chose on
114
+ purpose is not overridden behind your back;
115
+ 3. otherwise the component's own small default, which for most
116
+ properties is simply its regular default.
117
+
118
+ Container queries can't read a custom property, so the breakpoint itself
119
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
120
+ which already switched there. (The Sidebar's rail-to-sheet switch,
121
+ above, is a separate, layout-chrome decision and keeps its own value.) */
122
+ /* Styles for the small tier: the nearest container is narrow, OR the
123
+ viewport is.
124
+
125
+ The container query is the real answer -- a Tile in a 400px pane on a
126
+ desktop is small. But a container query only matches inside an ancestor
127
+ that *is* a container, and a component dropped straight into a page (no
128
+ Page, no Container around it) has none, so on a phone it would never
129
+ find out. The viewport query covers that: a narrow viewport means every
130
+ container in it is narrow too, so the two never disagree in the
131
+ direction that matters.
132
+
133
+ An element never queries itself, so on a component that is its own
134
+ container (Tile, Bar) this asks about the space it was given. */
103
135
  /* Warning: because we define a fallback
104
136
  media query, the media query can override the container
105
137
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -238,6 +270,10 @@ const el = $derived(elementProps(restProps, "tab", [
238
270
  .tab > :global(div > button) {
239
271
  border-radius: var(--tab-border-radius, var(--border-radius) var(--border-radius) 0 0);
240
272
  margin: 0;
273
+ /* In a TabBar that scrolls, a tab keeps its label on one line and its
274
+ full width; squeezing the labels is what made them wrap. */
275
+ flex-shrink: 0;
276
+ white-space: nowrap;
241
277
  }
242
278
 
243
279
  .tab.active > :global(button),
@@ -117,6 +117,38 @@ const effectiveOnLabel = $derived(onLabel || children);
117
117
  we deliberately avoid everywhere else.
118
118
 
119
119
  One definition, used by both, so they cannot drift again. */
120
+ /* The "small" size tier: a component whose container is this wide or less
121
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
122
+
123
+ The convention, shared by every component that has a size worth changing
124
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
125
+
126
+ --{component}-{property}-small
127
+
128
+ applies inside a small container. What wins there, in order:
129
+ 1. the `-small` variable, if you set it;
130
+ 2. otherwise the regular variable, if you set it -- a size you chose on
131
+ purpose is not overridden behind your back;
132
+ 3. otherwise the component's own small default, which for most
133
+ properties is simply its regular default.
134
+
135
+ Container queries can't read a custom property, so the breakpoint itself
136
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
137
+ which already switched there. (The Sidebar's rail-to-sheet switch,
138
+ above, is a separate, layout-chrome decision and keeps its own value.) */
139
+ /* Styles for the small tier: the nearest container is narrow, OR the
140
+ viewport is.
141
+
142
+ The container query is the real answer -- a Tile in a 400px pane on a
143
+ desktop is small. But a container query only matches inside an ancestor
144
+ that *is* a container, and a component dropped straight into a page (no
145
+ Page, no Container around it) has none, so on a phone it would never
146
+ find out. The viewport query covers that: a narrow viewport means every
147
+ container in it is narrow too, so the two never disagree in the
148
+ direction that matters.
149
+
150
+ An element never queries itself, so on a component that is its own
151
+ container (Tile, Bar) this asks about the space it was given. */
120
152
  /* Warning: because we define a fallback
121
153
  media query, the media query can override the container
122
154
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -255,7 +255,9 @@ let popoverDiv = $state();
255
255
  aria-expanded={isOpen ? "true" : "false"}
256
256
  aria-controls={id}
257
257
  >
258
- {#if label}{@render label()}{:else}Menu{/if}
258
+ <span class="trigger-label"
259
+ >{#if label}{@render label()}{:else}Menu{/if}</span
260
+ >
259
261
  </button>
260
262
  <div
261
263
  {id}
@@ -358,6 +360,38 @@ let popoverDiv = $state();
358
360
  we deliberately avoid everywhere else.
359
361
 
360
362
  One definition, used by both, so they cannot drift again. */
363
+ /* The "small" size tier: a component whose container is this wide or less
364
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
365
+
366
+ The convention, shared by every component that has a size worth changing
367
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
368
+
369
+ --{component}-{property}-small
370
+
371
+ applies inside a small container. What wins there, in order:
372
+ 1. the `-small` variable, if you set it;
373
+ 2. otherwise the regular variable, if you set it -- a size you chose on
374
+ purpose is not overridden behind your back;
375
+ 3. otherwise the component's own small default, which for most
376
+ properties is simply its regular default.
377
+
378
+ Container queries can't read a custom property, so the breakpoint itself
379
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
380
+ which already switched there. (The Sidebar's rail-to-sheet switch,
381
+ above, is a separate, layout-chrome decision and keeps its own value.) */
382
+ /* Styles for the small tier: the nearest container is narrow, OR the
383
+ viewport is.
384
+
385
+ The container query is the real answer -- a Tile in a 400px pane on a
386
+ desktop is small. But a container query only matches inside an ancestor
387
+ that *is* a container, and a component dropped straight into a page (no
388
+ Page, no Container around it) has none, so on a phone it would never
389
+ find out. The viewport query covers that: a narrow viewport means every
390
+ container in it is narrow too, so the two never disagree in the
391
+ direction that matters.
392
+
393
+ An element never queries itself, so on a component that is its own
394
+ container (Tile, Bar) this asks about the space it was given. */
361
395
  /* Warning: because we define a fallback
362
396
  media query, the media query can override the container
363
397
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -497,6 +531,20 @@ button:focus-visible {
497
531
 
498
532
  button {
499
533
  position: relative;
534
+ /* In a crowded row (a toolbar, a phone-width header) the trigger gives
535
+ way before its neighbours do: never wider than the space it was given,
536
+ its label on one line and truncated with an ellipsis (below). */
537
+ max-width: 100%;
538
+ }
539
+
540
+ /* The clipping lives on this inner span, not the button: overflow other
541
+ than visible moves an inline-level box's baseline to its bottom edge,
542
+ which would drop the trigger out of line with text beside it. */
543
+ .trigger-label {
544
+ display: block;
545
+ white-space: nowrap;
546
+ overflow: hidden;
547
+ text-overflow: ellipsis;
500
548
  }
501
549
 
502
550
  .dropdown-content :global(.menu) {
@@ -993,6 +1041,10 @@ button {
993
1041
 
994
1042
  nav {
995
1043
  position: relative;
1044
+ /* Lets a flex/grid parent shrink the menu below its label's width, so the
1045
+ trigger's ellipsis can kick in instead of the row overflowing. */
1046
+ min-width: 0;
1047
+ max-width: 100%;
996
1048
  }
997
1049
 
998
1050
  [popover] {
package/dist/index.d.ts CHANGED
@@ -4,6 +4,9 @@ import Button from "./controls/Button.svelte";
4
4
  import ButtonLink from "./controls/ButtonLink.svelte";
5
5
  import Checkbox from "./controls/Checkbox.svelte";
6
6
  import CircleButton from "./controls/CircleButton.svelte";
7
+ import GroupedToggle from "./controls/GroupedToggle.svelte";
8
+ import GroupedToggleItem from "./controls/GroupedToggleItem.svelte";
9
+ import GroupedRadioItem from "./controls/GroupedRadioItem.svelte";
7
10
  import Input from "./controls/Input.svelte";
8
11
  import MiniButton from "./controls/MiniButton.svelte";
9
12
  import RadioButton from "./controls/RadioButton.svelte";
@@ -51,6 +54,7 @@ export type { BaseStyleProps, MarginStyleProps, ContainerStyleProps, BarStylePro
51
54
  export { Tag };
52
55
  export { Hero };
53
56
  export { TabItem };
57
+ export { GroupedToggle, GroupedToggleItem, GroupedRadioItem };
54
58
  export { Button, ButtonLink, CircleButton, Checkbox, Input, Slider, Toggle, RadioButton, MiniButton, Select, Option, };
55
59
  export { Bar, ColumnContainer, Container, GridLayout, GridRow, Inline, MenuList, Page, ResponsiveText, RowContainer, Stack, TabBar, };
56
60
  export { TextLayout, Code, Accordion };
package/dist/index.js CHANGED
@@ -5,6 +5,9 @@ import Button from "./controls/Button.svelte";
5
5
  import ButtonLink from "./controls/ButtonLink.svelte";
6
6
  import Checkbox from "./controls/Checkbox.svelte";
7
7
  import CircleButton from "./controls/CircleButton.svelte";
8
+ import GroupedToggle from "./controls/GroupedToggle.svelte";
9
+ import GroupedToggleItem from "./controls/GroupedToggleItem.svelte";
10
+ import GroupedRadioItem from "./controls/GroupedRadioItem.svelte";
8
11
  import Input from "./controls/Input.svelte";
9
12
  import MiniButton from "./controls/MiniButton.svelte";
10
13
  import RadioButton from "./controls/RadioButton.svelte";
@@ -51,6 +54,7 @@ import Text from "./typography/Text.svelte";
51
54
  export { Tag };
52
55
  export { Hero };
53
56
  export { TabItem };
57
+ export { GroupedToggle, GroupedToggleItem, GroupedRadioItem };
54
58
  export { Button, ButtonLink, CircleButton, Checkbox, Input, Slider, Toggle, RadioButton, MiniButton, Select, Option, };
55
59
  export { Bar, ColumnContainer, Container, GridLayout, GridRow, Inline, MenuList, Page, ResponsiveText, RowContainer, Stack, TabBar, };
56
60
  export { TextLayout, Code, Accordion };
@@ -124,6 +124,38 @@ function onAccordionClicked(e) {
124
124
  we deliberately avoid everywhere else.
125
125
 
126
126
  One definition, used by both, so they cannot drift again. */
127
+ /* The "small" size tier: a component whose container is this wide or less
128
+ is on a phone, or in a pane about that narrow, and sizes itself for it.
129
+
130
+ The convention, shared by every component that has a size worth changing
131
+ there (Card started it; Tile, GridLayout, Bar and Container follow):
132
+
133
+ --{component}-{property}-small
134
+
135
+ applies inside a small container. What wins there, in order:
136
+ 1. the `-small` variable, if you set it;
137
+ 2. otherwise the regular variable, if you set it -- a size you chose on
138
+ purpose is not overridden behind your back;
139
+ 3. otherwise the component's own small default, which for most
140
+ properties is simply its regular default.
141
+
142
+ Container queries can't read a custom property, so the breakpoint itself
143
+ is fixed here rather than themeable. 600px matches Card and SplitPane,
144
+ which already switched there. (The Sidebar's rail-to-sheet switch,
145
+ above, is a separate, layout-chrome decision and keeps its own value.) */
146
+ /* Styles for the small tier: the nearest container is narrow, OR the
147
+ viewport is.
148
+
149
+ The container query is the real answer -- a Tile in a 400px pane on a
150
+ desktop is small. But a container query only matches inside an ancestor
151
+ that *is* a container, and a component dropped straight into a page (no
152
+ Page, no Container around it) has none, so on a phone it would never
153
+ find out. The viewport query covers that: a narrow viewport means every
154
+ container in it is narrow too, so the two never disagree in the
155
+ direction that matters.
156
+
157
+ An element never queries itself, so on a component that is its own
158
+ container (Tile, Bar) this asks about the space it was given. */
127
159
  /* Warning: because we define a fallback
128
160
  media query, the media query can override the container
129
161
  if we stack a bunch of these in a row and aren't thoughtful about the order.
@@ -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.