contain-css-svelte 1.3.0 → 1.4.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.
- package/dist/Card.svelte +204 -288
- package/dist/controls/Button.svelte +27 -1
- package/dist/controls/ButtonLink.svelte +27 -1
- package/dist/controls/Checkbox.svelte +26 -0
- package/dist/controls/CircleButton.svelte +27 -1
- package/dist/controls/Input.svelte +27 -1
- package/dist/controls/RadioButton.svelte +26 -0
- package/dist/controls/Select.svelte +26 -0
- package/dist/controls/Slider.svelte +27 -1
- package/dist/controls/TabItem.svelte +27 -1
- package/dist/controls/Toggle.svelte +27 -1
- package/dist/dropdowns/DropdownMenu.svelte +27 -1
- package/dist/layout/Accordion.svelte +27 -1
- package/dist/layout/Bar.svelte +37 -1
- package/dist/layout/ColumnContainer.svelte +27 -1
- package/dist/layout/Columns.svelte +27 -1
- package/dist/layout/Container.svelte +205 -292
- package/dist/layout/DataList.svelte +27 -1
- package/dist/layout/DataListItem.svelte +205 -292
- package/dist/layout/Fieldset.svelte +27 -1
- package/dist/layout/Form.svelte +205 -292
- package/dist/layout/FormItem.svelte +27 -1
- package/dist/layout/GridLayout.svelte +26 -0
- package/dist/layout/Hero.svelte +205 -292
- package/dist/layout/Inline.svelte +33 -1
- package/dist/layout/MenuList.svelte +27 -1
- package/dist/layout/Page.svelte +27 -1
- package/dist/layout/RowContainer.svelte +27 -1
- package/dist/layout/Sidebar.svelte +266 -33
- package/dist/layout/Sidebar.svelte.d.ts +34 -0
- package/dist/layout/SidebarContainer.svelte +27 -1
- package/dist/layout/SplitPane.svelte +27 -1
- package/dist/layout/Stack.svelte +33 -1
- package/dist/layout/TabBar.svelte +27 -1
- package/dist/layout/Table.svelte +238 -294
- package/dist/layout/Tile.svelte +204 -291
- package/dist/misc/CodeInner.svelte +27 -1
- package/dist/misc/Progress.svelte +205 -292
- package/dist/misc/Tag.svelte +27 -1
- package/dist/overlays/Dialog.svelte +205 -292
- package/dist/overlays/Tooltip.svelte +255 -349
- package/dist/sass/_typography.scss +203 -191
- package/dist/typography/TextLayout.svelte +482 -292
- package/dist/vars/defaults.css +258 -0
- package/dist/vars/typography-context.css +271 -0
- package/package.json +1 -1
|
@@ -32,7 +32,33 @@ const el = $derived(elementProps({ justify, align, gap, wrap, ...restProps }, "i
|
|
|
32
32
|
{@render children?.()}
|
|
33
33
|
</div>
|
|
34
34
|
|
|
35
|
-
<style>/*
|
|
35
|
+
<style>/* Per-level heading (h1-h6) box/typography properties, resolved to PRIVATE,
|
|
36
|
+
inheriting custom properties (--_h1-color, --_h2-font-size, etc) rather than
|
|
37
|
+
assigned directly to a matched h1-h6 selector. Nothing in this file matches
|
|
38
|
+
an actual heading element anymore -- see typography-context.css (vars/), which
|
|
39
|
+
is the single, global, :where()-scoped rule that actually reads these vars
|
|
40
|
+
and applies them to real elements. That split is what lets a component
|
|
41
|
+
nested arbitrarily deep (through <article>, <Tile>, whatever) still get the
|
|
42
|
+
nearest ancestor's heading styling: these are ordinary inherited custom
|
|
43
|
+
properties, so DOM proximity decides which component's values apply, not
|
|
44
|
+
selector specificity or stylesheet order. See AGENTS-INTERNAL.md. */
|
|
45
|
+
/* All six heading levels' context vars in one call -- what every
|
|
46
|
+
"typography container" component (Container, Card, Tile, TextLayout, ...)
|
|
47
|
+
includes on itself once, alongside the shared --_heading-* vars below. */
|
|
48
|
+
/* Shared prose-measure group: p, blockquote, dl, ul, ol. li/dt/dd don't get
|
|
49
|
+
their own vars -- they're never wider than their ul/ol/dl parent's own
|
|
50
|
+
max-width box, so they're already bounded for free by ordinary block
|
|
51
|
+
layout, not by anything selector-based reaching them individually. */
|
|
52
|
+
/* p specifically also gets the fuller typography-props-bare treatment
|
|
53
|
+
(paragraph-prefixed), which -- same as in the original selector-based
|
|
54
|
+
version -- is declared/consumed AFTER the shared prose vars above, so it
|
|
55
|
+
wins for whichever properties both groups set. */
|
|
56
|
+
/* The first paragraph in a typography context (p:first-of-type, or a p right
|
|
57
|
+
after a heading) gets its own, slightly different treatment -- larger lede
|
|
58
|
+
text, no top margin. Structural matching (:first-of-type, `h1 + p`) still
|
|
59
|
+
has to happen where the real element is, in the global consumer rule; only
|
|
60
|
+
the VALUES move to context vars here. */
|
|
61
|
+
/* Logical, not top/bottom/left/right: margin-block/margin-inline already take
|
|
36
62
|
one value (both sides equal) or two (start end), so there is no separate
|
|
37
63
|
"which side" prop to remember and no 4-value shorthand order to get wrong.
|
|
38
64
|
Defaults to 0 on purpose -- unlike padding-props above, a margin that
|
|
@@ -72,6 +98,12 @@ const el = $derived(elementProps({ justify, align, gap, wrap, ...restProps }, "i
|
|
|
72
98
|
border-bottom: var(--inline-border-bottom, var(--border-bottom, var(--inline-border, var(--border, none))));
|
|
73
99
|
border-left: var(--inline-border-left, var(--border-left, var(--inline-border, var(--border, none))));
|
|
74
100
|
border-radius: var(--inline-border-radius, var(--border-radius, none));
|
|
101
|
+
/* A layout helper, not a surface: padding comes only from
|
|
102
|
+
--inline-padding (or the `padding` prop), never from the theme's
|
|
103
|
+
--padding. box-props falls back to --padding, which is inherited, so
|
|
104
|
+
without this every Inline picked up the page's padding -- or
|
|
105
|
+
whatever padding an enclosing Card set. */
|
|
106
|
+
--_padding: var(--inline-padding, 0);
|
|
75
107
|
--_margin-block: var(--inline-margin-block, var(--margin-block, 0));
|
|
76
108
|
--_margin-inline: var(--inline-margin-inline, var(--margin-inline, 0));
|
|
77
109
|
margin-block: var(--_margin-block);
|
|
@@ -26,7 +26,33 @@ const el = $derived(elementProps(restProps, "menu", [
|
|
|
26
26
|
{@render children?.()}
|
|
27
27
|
</ul>
|
|
28
28
|
|
|
29
|
-
<style>/*
|
|
29
|
+
<style>/* Per-level heading (h1-h6) box/typography properties, resolved to PRIVATE,
|
|
30
|
+
inheriting custom properties (--_h1-color, --_h2-font-size, etc) rather than
|
|
31
|
+
assigned directly to a matched h1-h6 selector. Nothing in this file matches
|
|
32
|
+
an actual heading element anymore -- see typography-context.css (vars/), which
|
|
33
|
+
is the single, global, :where()-scoped rule that actually reads these vars
|
|
34
|
+
and applies them to real elements. That split is what lets a component
|
|
35
|
+
nested arbitrarily deep (through <article>, <Tile>, whatever) still get the
|
|
36
|
+
nearest ancestor's heading styling: these are ordinary inherited custom
|
|
37
|
+
properties, so DOM proximity decides which component's values apply, not
|
|
38
|
+
selector specificity or stylesheet order. See AGENTS-INTERNAL.md. */
|
|
39
|
+
/* All six heading levels' context vars in one call -- what every
|
|
40
|
+
"typography container" component (Container, Card, Tile, TextLayout, ...)
|
|
41
|
+
includes on itself once, alongside the shared --_heading-* vars below. */
|
|
42
|
+
/* Shared prose-measure group: p, blockquote, dl, ul, ol. li/dt/dd don't get
|
|
43
|
+
their own vars -- they're never wider than their ul/ol/dl parent's own
|
|
44
|
+
max-width box, so they're already bounded for free by ordinary block
|
|
45
|
+
layout, not by anything selector-based reaching them individually. */
|
|
46
|
+
/* p specifically also gets the fuller typography-props-bare treatment
|
|
47
|
+
(paragraph-prefixed), which -- same as in the original selector-based
|
|
48
|
+
version -- is declared/consumed AFTER the shared prose vars above, so it
|
|
49
|
+
wins for whichever properties both groups set. */
|
|
50
|
+
/* The first paragraph in a typography context (p:first-of-type, or a p right
|
|
51
|
+
after a heading) gets its own, slightly different treatment -- larger lede
|
|
52
|
+
text, no top margin. Structural matching (:first-of-type, `h1 + p`) still
|
|
53
|
+
has to happen where the real element is, in the global consumer rule; only
|
|
54
|
+
the VALUES move to context vars here. */
|
|
55
|
+
/* Logical, not top/bottom/left/right: margin-block/margin-inline already take
|
|
30
56
|
one value (both sides equal) or two (start end), so there is no separate
|
|
31
57
|
"which side" prop to remember and no 4-value shorthand order to get wrong.
|
|
32
58
|
Defaults to 0 on purpose -- unlike padding-props above, a margin that
|
package/dist/layout/Page.svelte
CHANGED
|
@@ -89,7 +89,33 @@ onMount(() => {
|
|
|
89
89
|
</footer>
|
|
90
90
|
</section>
|
|
91
91
|
|
|
92
|
-
<style>/*
|
|
92
|
+
<style>/* Per-level heading (h1-h6) box/typography properties, resolved to PRIVATE,
|
|
93
|
+
inheriting custom properties (--_h1-color, --_h2-font-size, etc) rather than
|
|
94
|
+
assigned directly to a matched h1-h6 selector. Nothing in this file matches
|
|
95
|
+
an actual heading element anymore -- see typography-context.css (vars/), which
|
|
96
|
+
is the single, global, :where()-scoped rule that actually reads these vars
|
|
97
|
+
and applies them to real elements. That split is what lets a component
|
|
98
|
+
nested arbitrarily deep (through <article>, <Tile>, whatever) still get the
|
|
99
|
+
nearest ancestor's heading styling: these are ordinary inherited custom
|
|
100
|
+
properties, so DOM proximity decides which component's values apply, not
|
|
101
|
+
selector specificity or stylesheet order. See AGENTS-INTERNAL.md. */
|
|
102
|
+
/* All six heading levels' context vars in one call -- what every
|
|
103
|
+
"typography container" component (Container, Card, Tile, TextLayout, ...)
|
|
104
|
+
includes on itself once, alongside the shared --_heading-* vars below. */
|
|
105
|
+
/* Shared prose-measure group: p, blockquote, dl, ul, ol. li/dt/dd don't get
|
|
106
|
+
their own vars -- they're never wider than their ul/ol/dl parent's own
|
|
107
|
+
max-width box, so they're already bounded for free by ordinary block
|
|
108
|
+
layout, not by anything selector-based reaching them individually. */
|
|
109
|
+
/* p specifically also gets the fuller typography-props-bare treatment
|
|
110
|
+
(paragraph-prefixed), which -- same as in the original selector-based
|
|
111
|
+
version -- is declared/consumed AFTER the shared prose vars above, so it
|
|
112
|
+
wins for whichever properties both groups set. */
|
|
113
|
+
/* The first paragraph in a typography context (p:first-of-type, or a p right
|
|
114
|
+
after a heading) gets its own, slightly different treatment -- larger lede
|
|
115
|
+
text, no top margin. Structural matching (:first-of-type, `h1 + p`) still
|
|
116
|
+
has to happen where the real element is, in the global consumer rule; only
|
|
117
|
+
the VALUES move to context vars here. */
|
|
118
|
+
/* Logical, not top/bottom/left/right: margin-block/margin-inline already take
|
|
93
119
|
one value (both sides equal) or two (start end), so there is no separate
|
|
94
120
|
"which side" prop to remember and no 4-value shorthand order to get wrong.
|
|
95
121
|
Defaults to 0 on purpose -- unlike padding-props above, a margin that
|
|
@@ -21,7 +21,33 @@ const el = $derived(elementProps(restProps, "row-container", ROW_CONTAINER_VARS)
|
|
|
21
21
|
{@render children?.()}
|
|
22
22
|
</section>
|
|
23
23
|
|
|
24
|
-
<style>/*
|
|
24
|
+
<style>/* Per-level heading (h1-h6) box/typography properties, resolved to PRIVATE,
|
|
25
|
+
inheriting custom properties (--_h1-color, --_h2-font-size, etc) rather than
|
|
26
|
+
assigned directly to a matched h1-h6 selector. Nothing in this file matches
|
|
27
|
+
an actual heading element anymore -- see typography-context.css (vars/), which
|
|
28
|
+
is the single, global, :where()-scoped rule that actually reads these vars
|
|
29
|
+
and applies them to real elements. That split is what lets a component
|
|
30
|
+
nested arbitrarily deep (through <article>, <Tile>, whatever) still get the
|
|
31
|
+
nearest ancestor's heading styling: these are ordinary inherited custom
|
|
32
|
+
properties, so DOM proximity decides which component's values apply, not
|
|
33
|
+
selector specificity or stylesheet order. See AGENTS-INTERNAL.md. */
|
|
34
|
+
/* All six heading levels' context vars in one call -- what every
|
|
35
|
+
"typography container" component (Container, Card, Tile, TextLayout, ...)
|
|
36
|
+
includes on itself once, alongside the shared --_heading-* vars below. */
|
|
37
|
+
/* Shared prose-measure group: p, blockquote, dl, ul, ol. li/dt/dd don't get
|
|
38
|
+
their own vars -- they're never wider than their ul/ol/dl parent's own
|
|
39
|
+
max-width box, so they're already bounded for free by ordinary block
|
|
40
|
+
layout, not by anything selector-based reaching them individually. */
|
|
41
|
+
/* p specifically also gets the fuller typography-props-bare treatment
|
|
42
|
+
(paragraph-prefixed), which -- same as in the original selector-based
|
|
43
|
+
version -- is declared/consumed AFTER the shared prose vars above, so it
|
|
44
|
+
wins for whichever properties both groups set. */
|
|
45
|
+
/* The first paragraph in a typography context (p:first-of-type, or a p right
|
|
46
|
+
after a heading) gets its own, slightly different treatment -- larger lede
|
|
47
|
+
text, no top margin. Structural matching (:first-of-type, `h1 + p`) still
|
|
48
|
+
has to happen where the real element is, in the global consumer rule; only
|
|
49
|
+
the VALUES move to context vars here. */
|
|
50
|
+
/* Logical, not top/bottom/left/right: margin-block/margin-inline already take
|
|
25
51
|
one value (both sides equal) or two (start end), so there is no separate
|
|
26
52
|
"which side" prop to remember and no 4-value shorthand order to get wrong.
|
|
27
53
|
Defaults to 0 on purpose -- unlike padding-props above, a margin that
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">import { elementProps } from "../util";
|
|
2
2
|
import { COLOR_VARS, TYPOGRAPHY_VARS, } from "../styleProps";
|
|
3
|
-
let { left, right, children, overlay = false, open = $bindable(undefined), expandLabel = "Expand sidebar", collapseLabel = "Collapse sidebar", class: className, ...restProps } = $props();
|
|
3
|
+
let { left, right, children, overlay = false, sticky = false, sheetButton = "tab", open = $bindable(undefined), expandLabel = "Expand sidebar", collapseLabel = "Collapse sidebar", class: className, ...restProps } = $props();
|
|
4
4
|
/* The shorthands sidebar'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. */
|
|
@@ -28,6 +28,8 @@ const expandedHamburger = $derived(open ?? false);
|
|
|
28
28
|
class:right
|
|
29
29
|
class:left
|
|
30
30
|
class:overlay
|
|
31
|
+
class:sticky
|
|
32
|
+
class:button-sheet-toggle={sheetButton === "button"}
|
|
31
33
|
class:expandedHamburger
|
|
32
34
|
class:expandedBar
|
|
33
35
|
{...el}
|
|
@@ -57,6 +59,32 @@ const expandedHamburger = $derived(open ?? false);
|
|
|
57
59
|
</aside>
|
|
58
60
|
|
|
59
61
|
<style>@charset "UTF-8";
|
|
62
|
+
/* Per-level heading (h1-h6) box/typography properties, resolved to PRIVATE,
|
|
63
|
+
inheriting custom properties (--_h1-color, --_h2-font-size, etc) rather than
|
|
64
|
+
assigned directly to a matched h1-h6 selector. Nothing in this file matches
|
|
65
|
+
an actual heading element anymore -- see typography-context.css (vars/), which
|
|
66
|
+
is the single, global, :where()-scoped rule that actually reads these vars
|
|
67
|
+
and applies them to real elements. That split is what lets a component
|
|
68
|
+
nested arbitrarily deep (through <article>, <Tile>, whatever) still get the
|
|
69
|
+
nearest ancestor's heading styling: these are ordinary inherited custom
|
|
70
|
+
properties, so DOM proximity decides which component's values apply, not
|
|
71
|
+
selector specificity or stylesheet order. See AGENTS-INTERNAL.md. */
|
|
72
|
+
/* All six heading levels' context vars in one call -- what every
|
|
73
|
+
"typography container" component (Container, Card, Tile, TextLayout, ...)
|
|
74
|
+
includes on itself once, alongside the shared --_heading-* vars below. */
|
|
75
|
+
/* Shared prose-measure group: p, blockquote, dl, ul, ol. li/dt/dd don't get
|
|
76
|
+
their own vars -- they're never wider than their ul/ol/dl parent's own
|
|
77
|
+
max-width box, so they're already bounded for free by ordinary block
|
|
78
|
+
layout, not by anything selector-based reaching them individually. */
|
|
79
|
+
/* p specifically also gets the fuller typography-props-bare treatment
|
|
80
|
+
(paragraph-prefixed), which -- same as in the original selector-based
|
|
81
|
+
version -- is declared/consumed AFTER the shared prose vars above, so it
|
|
82
|
+
wins for whichever properties both groups set. */
|
|
83
|
+
/* The first paragraph in a typography context (p:first-of-type, or a p right
|
|
84
|
+
after a heading) gets its own, slightly different treatment -- larger lede
|
|
85
|
+
text, no top margin. Structural matching (:first-of-type, `h1 + p`) still
|
|
86
|
+
has to happen where the real element is, in the global consumer rule; only
|
|
87
|
+
the VALUES move to context vars here. */
|
|
60
88
|
/* Logical, not top/bottom/left/right: margin-block/margin-inline already take
|
|
61
89
|
one value (both sides equal) or two (start end), so there is no separate
|
|
62
90
|
"which side" prop to remember and no 4-value shorthand order to get wrong.
|
|
@@ -85,6 +113,9 @@ const expandedHamburger = $derived(open ?? false);
|
|
|
85
113
|
*/
|
|
86
114
|
/* Convenience groupings */
|
|
87
115
|
aside {
|
|
116
|
+
/* Set only by `sheetButton="button"` (below); cleared here so it never
|
|
117
|
+
leaks in from an enclosing sidebar. */
|
|
118
|
+
--_sidebar-sheet-edge-override: initial;
|
|
88
119
|
--link-bg: var(--sidebar-link-bg, var(--surface-link-bg, inherit));
|
|
89
120
|
--link-fg: var(--sidebar-link-fg, var(--surface-link-fg, inherit));
|
|
90
121
|
--_bg-mix-color: var(--sidebar-bg-mix-color, var(--surface-bg-mix-color, var(--bg-mix-color, transparent)));
|
|
@@ -383,6 +414,26 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
383
414
|
var(--sidebar-icon-height, 1rem),
|
|
384
415
|
var(--icon-size, 32px)
|
|
385
416
|
);
|
|
417
|
+
/* The sheet button's corners. Its "edge" corners are the pair on the
|
|
418
|
+
side it attaches to -- the page edge while shut, the panel's inner edge
|
|
419
|
+
while open -- and default to 0, which is what makes it read as a tab
|
|
420
|
+
fastened to that edge. `sheetButton="button"` rounds them like the
|
|
421
|
+
other two, for a sheet that does not sit against an edge. */
|
|
422
|
+
--_sidebar-sheet-button-radius: var(--circle-button-radius, var(--mini-button-radius, var(--button-radius, var(--radius, 50%))));
|
|
423
|
+
--_sidebar-sheet-expand-edge-radius: var(
|
|
424
|
+
--sidebar-sheet-expand-edge-radius,
|
|
425
|
+
var(
|
|
426
|
+
--_sidebar-sheet-edge-override,
|
|
427
|
+
var(--sidebar-sheet-edge-radius, 0)
|
|
428
|
+
)
|
|
429
|
+
);
|
|
430
|
+
--_sidebar-sheet-collapse-edge-radius: var(
|
|
431
|
+
--sidebar-sheet-collapse-edge-radius,
|
|
432
|
+
var(
|
|
433
|
+
--_sidebar-sheet-edge-override,
|
|
434
|
+
var(--sidebar-sheet-edge-radius, 0)
|
|
435
|
+
)
|
|
436
|
+
);
|
|
386
437
|
position: relative;
|
|
387
438
|
overflow: visible;
|
|
388
439
|
background: transparent;
|
|
@@ -408,7 +459,9 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
408
459
|
top: 0;
|
|
409
460
|
left: 0;
|
|
410
461
|
width: var(--sidebar-width);
|
|
411
|
-
z-index
|
|
462
|
+
/* Above a sticky Table head (z-index 2), which a sheet beside a long table
|
|
463
|
+
otherwise slides under. */
|
|
464
|
+
z-index: var(--sidebar-overlay-z-index, 3);
|
|
412
465
|
transform: translateX(-100%);
|
|
413
466
|
opacity: 0;
|
|
414
467
|
background: transparent;
|
|
@@ -536,16 +589,16 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
536
589
|
aside.overlay > button {
|
|
537
590
|
transition: left var(--sidebar-transition);
|
|
538
591
|
transform: translateX(0);
|
|
539
|
-
z-index: 3;
|
|
592
|
+
z-index: calc(var(--sidebar-overlay-z-index, 3) + 1);
|
|
540
593
|
position: absolute;
|
|
541
594
|
opacity: 1;
|
|
542
595
|
pointer-events: all;
|
|
543
596
|
display: block;
|
|
544
597
|
top: var(--padding);
|
|
545
598
|
left: 0;
|
|
546
|
-
border-radius: var(--
|
|
547
|
-
border-top-left-radius:
|
|
548
|
-
border-bottom-left-radius:
|
|
599
|
+
border-radius: var(--_sidebar-sheet-button-radius);
|
|
600
|
+
border-top-left-radius: var(--_sidebar-sheet-expand-edge-radius);
|
|
601
|
+
border-bottom-left-radius: var(--_sidebar-sheet-expand-edge-radius);
|
|
549
602
|
border: var(--circle-button-border, var(--mini-button-border));
|
|
550
603
|
width: var(--_sidebar-expander-width);
|
|
551
604
|
height: var(--_sidebar-expander-height);
|
|
@@ -674,9 +727,9 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
674
727
|
Either the button pops out of the panel or it sits inside it; this
|
|
675
728
|
sits inside it, and the inset is then exactly button + one gutter. */
|
|
676
729
|
left: calc(var(--sidebar-width) - var(--_sidebar-expander-width));
|
|
677
|
-
border-radius: var(--
|
|
678
|
-
border-top-right-radius:
|
|
679
|
-
border-bottom-right-radius:
|
|
730
|
+
border-radius: var(--_sidebar-sheet-button-radius);
|
|
731
|
+
border-top-right-radius: var(--_sidebar-sheet-collapse-edge-radius);
|
|
732
|
+
border-bottom-right-radius: var(--_sidebar-sheet-collapse-edge-radius);
|
|
680
733
|
}
|
|
681
734
|
aside.overlay {
|
|
682
735
|
/* Everything above anchors the button to the left, which is right for a
|
|
@@ -690,18 +743,95 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
690
743
|
aside.overlay.right > button {
|
|
691
744
|
left: auto;
|
|
692
745
|
right: 0;
|
|
693
|
-
border-
|
|
694
|
-
border-
|
|
695
|
-
border-
|
|
696
|
-
border-bottom-right-radius: 0;
|
|
746
|
+
border-radius: var(--_sidebar-sheet-button-radius);
|
|
747
|
+
border-top-right-radius: var(--_sidebar-sheet-expand-edge-radius);
|
|
748
|
+
border-bottom-right-radius: var(--_sidebar-sheet-expand-edge-radius);
|
|
697
749
|
}
|
|
698
750
|
aside.overlay.right > button.close {
|
|
699
751
|
left: auto;
|
|
700
752
|
right: calc(var(--sidebar-width) - var(--_sidebar-expander-width));
|
|
701
|
-
border-
|
|
702
|
-
border-
|
|
703
|
-
border-
|
|
704
|
-
|
|
753
|
+
border-radius: var(--_sidebar-sheet-button-radius);
|
|
754
|
+
border-top-left-radius: var(--_sidebar-sheet-collapse-edge-radius);
|
|
755
|
+
border-bottom-left-radius: var(--_sidebar-sheet-collapse-edge-radius);
|
|
756
|
+
}
|
|
757
|
+
aside.overlay {
|
|
758
|
+
/* `sticky`: the sheet follows the reader down the page instead of
|
|
759
|
+
stretching to the row.
|
|
760
|
+
|
|
761
|
+
Sticky needs the sheet back *in flow* -- an absolutely positioned box
|
|
762
|
+
cannot stick -- but the aside is only a button's width wide and the
|
|
763
|
+
row's full height, and that height is exactly the range the sheet
|
|
764
|
+
should be free to travel. So the aside becomes a one-cell grid as tall
|
|
765
|
+
as its row, and the sheet and its button share that cell, each sticky
|
|
766
|
+
within it.
|
|
767
|
+
|
|
768
|
+
Horizontal placement moves from `left`/`right` onto margins, because on
|
|
769
|
+
a sticky box `left` and `right` stop being offsets and become sticky
|
|
770
|
+
insets -- they would pin the button against a sideways-scrolling
|
|
771
|
+
ancestor rather than place it. The margins reproduce the absolute
|
|
772
|
+
geometry exactly: the aside is `--gap` plus one button wide, and a
|
|
773
|
+
sheet or button wider than that spills out of its cell on the side
|
|
774
|
+
that faces the content. */
|
|
775
|
+
}
|
|
776
|
+
aside.overlay.sticky {
|
|
777
|
+
--_sidebar-sheet-top: var(--sidebar-sheet-top, var(--padding));
|
|
778
|
+
--_sidebar-aside-width: calc(var(--gap) + var(--_sidebar-expander-width));
|
|
779
|
+
display: grid;
|
|
780
|
+
grid-template-columns: 100%;
|
|
781
|
+
align-content: stretch;
|
|
782
|
+
/* A shut sheet is still in flow now, and would otherwise hold the row
|
|
783
|
+
open to its own height. The aside's width is set explicitly, so
|
|
784
|
+
size containment only ever zeroes out the height it would have
|
|
785
|
+
contributed; the row still stretches it to full height. */
|
|
786
|
+
contain: size;
|
|
787
|
+
}
|
|
788
|
+
aside.overlay.sticky > .content, aside.overlay.sticky > button.expander, aside.overlay.sticky > button.close {
|
|
789
|
+
grid-area: 1/1;
|
|
790
|
+
position: sticky;
|
|
791
|
+
align-self: start;
|
|
792
|
+
justify-self: start;
|
|
793
|
+
left: auto;
|
|
794
|
+
right: auto;
|
|
795
|
+
}
|
|
796
|
+
aside.overlay.sticky > .content {
|
|
797
|
+
top: var(--_sidebar-sheet-top);
|
|
798
|
+
margin-left: 0;
|
|
799
|
+
height: auto;
|
|
800
|
+
/* The reserve is a budget for everything that is not the sheet, rather
|
|
801
|
+
than just the sticky offset: before the sheet sticks -- page scrolled
|
|
802
|
+
to the top -- its top edge is its row's, which may sit well below the
|
|
803
|
+
viewport top, and a sheet sized only from the offset would overflow
|
|
804
|
+
the viewport by exactly that much. Twice the top gives it an even
|
|
805
|
+
margin at both ends once it has stuck. */
|
|
806
|
+
max-height: var(--sidebar-sheet-max-height, calc(100dvh - var(--sidebar-sheet-reserve, calc(2 * var(--_sidebar-sheet-top)))));
|
|
807
|
+
overflow-y: auto;
|
|
808
|
+
/* A column, so a child with `min-height: 0` and its own overflow can
|
|
809
|
+
keep a header or footer in view and scroll only its middle. Children
|
|
810
|
+
that do not opt in keep their size, and the sheet scrolls as a
|
|
811
|
+
whole. */
|
|
812
|
+
display: flex;
|
|
813
|
+
flex-direction: column;
|
|
814
|
+
}
|
|
815
|
+
aside.overlay.sticky.expandedHamburger > .content {
|
|
816
|
+
height: auto;
|
|
817
|
+
}
|
|
818
|
+
aside.overlay.sticky.right > .content {
|
|
819
|
+
margin-left: calc(var(--_sidebar-aside-width) - var(--sidebar-width));
|
|
820
|
+
}
|
|
821
|
+
aside.overlay.sticky > button.expander, aside.overlay.sticky > button.close {
|
|
822
|
+
top: calc(var(--_sidebar-sheet-top) + var(--padding));
|
|
823
|
+
margin-top: var(--padding);
|
|
824
|
+
margin-left: 0;
|
|
825
|
+
transition: margin-left var(--sidebar-transition);
|
|
826
|
+
}
|
|
827
|
+
aside.overlay.sticky > button.close {
|
|
828
|
+
margin-left: calc(var(--sidebar-width) - var(--_sidebar-expander-width));
|
|
829
|
+
}
|
|
830
|
+
aside.overlay.sticky.right > button.expander {
|
|
831
|
+
margin-left: var(--gap);
|
|
832
|
+
}
|
|
833
|
+
aside.overlay.sticky.right > button.close {
|
|
834
|
+
margin-left: calc(var(--_sidebar-aside-width) - var(--sidebar-width));
|
|
705
835
|
}
|
|
706
836
|
.edge-bar {
|
|
707
837
|
--link-bg: var(--grab-bar-link-bg, var(--sidebar-link-bg, var(--surface-link-bg, inherit)));
|
|
@@ -863,6 +993,26 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
863
993
|
var(--sidebar-icon-height, 1rem),
|
|
864
994
|
var(--icon-size, 32px)
|
|
865
995
|
);
|
|
996
|
+
/* The sheet button's corners. Its "edge" corners are the pair on the
|
|
997
|
+
side it attaches to -- the page edge while shut, the panel's inner edge
|
|
998
|
+
while open -- and default to 0, which is what makes it read as a tab
|
|
999
|
+
fastened to that edge. `sheetButton="button"` rounds them like the
|
|
1000
|
+
other two, for a sheet that does not sit against an edge. */
|
|
1001
|
+
--_sidebar-sheet-button-radius: var(--circle-button-radius, var(--mini-button-radius, var(--button-radius, var(--radius, 50%))));
|
|
1002
|
+
--_sidebar-sheet-expand-edge-radius: var(
|
|
1003
|
+
--sidebar-sheet-expand-edge-radius,
|
|
1004
|
+
var(
|
|
1005
|
+
--_sidebar-sheet-edge-override,
|
|
1006
|
+
var(--sidebar-sheet-edge-radius, 0)
|
|
1007
|
+
)
|
|
1008
|
+
);
|
|
1009
|
+
--_sidebar-sheet-collapse-edge-radius: var(
|
|
1010
|
+
--sidebar-sheet-collapse-edge-radius,
|
|
1011
|
+
var(
|
|
1012
|
+
--_sidebar-sheet-edge-override,
|
|
1013
|
+
var(--sidebar-sheet-edge-radius, 0)
|
|
1014
|
+
)
|
|
1015
|
+
);
|
|
866
1016
|
position: relative;
|
|
867
1017
|
overflow: visible;
|
|
868
1018
|
background: transparent;
|
|
@@ -888,7 +1038,9 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
888
1038
|
top: 0;
|
|
889
1039
|
left: 0;
|
|
890
1040
|
width: var(--sidebar-width);
|
|
891
|
-
z-index
|
|
1041
|
+
/* Above a sticky Table head (z-index 2), which a sheet beside a long table
|
|
1042
|
+
otherwise slides under. */
|
|
1043
|
+
z-index: var(--sidebar-overlay-z-index, 3);
|
|
892
1044
|
transform: translateX(-100%);
|
|
893
1045
|
opacity: 0;
|
|
894
1046
|
background: transparent;
|
|
@@ -1016,16 +1168,16 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
1016
1168
|
aside > button {
|
|
1017
1169
|
transition: left var(--sidebar-transition);
|
|
1018
1170
|
transform: translateX(0);
|
|
1019
|
-
z-index: 3;
|
|
1171
|
+
z-index: calc(var(--sidebar-overlay-z-index, 3) + 1);
|
|
1020
1172
|
position: absolute;
|
|
1021
1173
|
opacity: 1;
|
|
1022
1174
|
pointer-events: all;
|
|
1023
1175
|
display: block;
|
|
1024
1176
|
top: var(--padding);
|
|
1025
1177
|
left: 0;
|
|
1026
|
-
border-radius: var(--
|
|
1027
|
-
border-top-left-radius:
|
|
1028
|
-
border-bottom-left-radius:
|
|
1178
|
+
border-radius: var(--_sidebar-sheet-button-radius);
|
|
1179
|
+
border-top-left-radius: var(--_sidebar-sheet-expand-edge-radius);
|
|
1180
|
+
border-bottom-left-radius: var(--_sidebar-sheet-expand-edge-radius);
|
|
1029
1181
|
border: var(--circle-button-border, var(--mini-button-border));
|
|
1030
1182
|
width: var(--_sidebar-expander-width);
|
|
1031
1183
|
height: var(--_sidebar-expander-height);
|
|
@@ -1154,9 +1306,9 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
1154
1306
|
Either the button pops out of the panel or it sits inside it; this
|
|
1155
1307
|
sits inside it, and the inset is then exactly button + one gutter. */
|
|
1156
1308
|
left: calc(var(--sidebar-width) - var(--_sidebar-expander-width));
|
|
1157
|
-
border-radius: var(--
|
|
1158
|
-
border-top-right-radius:
|
|
1159
|
-
border-bottom-right-radius:
|
|
1309
|
+
border-radius: var(--_sidebar-sheet-button-radius);
|
|
1310
|
+
border-top-right-radius: var(--_sidebar-sheet-collapse-edge-radius);
|
|
1311
|
+
border-bottom-right-radius: var(--_sidebar-sheet-collapse-edge-radius);
|
|
1160
1312
|
}
|
|
1161
1313
|
aside {
|
|
1162
1314
|
/* Everything above anchors the button to the left, which is right for a
|
|
@@ -1170,20 +1322,101 @@ aside .content:hover::-webkit-scrollbar-thumb:hover {
|
|
|
1170
1322
|
aside.right > button {
|
|
1171
1323
|
left: auto;
|
|
1172
1324
|
right: 0;
|
|
1173
|
-
border-
|
|
1174
|
-
border-
|
|
1175
|
-
border-
|
|
1176
|
-
border-bottom-right-radius: 0;
|
|
1325
|
+
border-radius: var(--_sidebar-sheet-button-radius);
|
|
1326
|
+
border-top-right-radius: var(--_sidebar-sheet-expand-edge-radius);
|
|
1327
|
+
border-bottom-right-radius: var(--_sidebar-sheet-expand-edge-radius);
|
|
1177
1328
|
}
|
|
1178
1329
|
aside.right > button.close {
|
|
1179
1330
|
left: auto;
|
|
1180
1331
|
right: calc(var(--sidebar-width) - var(--_sidebar-expander-width));
|
|
1181
|
-
border-
|
|
1182
|
-
border-
|
|
1183
|
-
border-
|
|
1184
|
-
|
|
1332
|
+
border-radius: var(--_sidebar-sheet-button-radius);
|
|
1333
|
+
border-top-left-radius: var(--_sidebar-sheet-collapse-edge-radius);
|
|
1334
|
+
border-bottom-left-radius: var(--_sidebar-sheet-collapse-edge-radius);
|
|
1335
|
+
}
|
|
1336
|
+
aside {
|
|
1337
|
+
/* `sticky`: the sheet follows the reader down the page instead of
|
|
1338
|
+
stretching to the row.
|
|
1339
|
+
|
|
1340
|
+
Sticky needs the sheet back *in flow* -- an absolutely positioned box
|
|
1341
|
+
cannot stick -- but the aside is only a button's width wide and the
|
|
1342
|
+
row's full height, and that height is exactly the range the sheet
|
|
1343
|
+
should be free to travel. So the aside becomes a one-cell grid as tall
|
|
1344
|
+
as its row, and the sheet and its button share that cell, each sticky
|
|
1345
|
+
within it.
|
|
1346
|
+
|
|
1347
|
+
Horizontal placement moves from `left`/`right` onto margins, because on
|
|
1348
|
+
a sticky box `left` and `right` stop being offsets and become sticky
|
|
1349
|
+
insets -- they would pin the button against a sideways-scrolling
|
|
1350
|
+
ancestor rather than place it. The margins reproduce the absolute
|
|
1351
|
+
geometry exactly: the aside is `--gap` plus one button wide, and a
|
|
1352
|
+
sheet or button wider than that spills out of its cell on the side
|
|
1353
|
+
that faces the content. */
|
|
1354
|
+
}
|
|
1355
|
+
aside.sticky {
|
|
1356
|
+
--_sidebar-sheet-top: var(--sidebar-sheet-top, var(--padding));
|
|
1357
|
+
--_sidebar-aside-width: calc(var(--gap) + var(--_sidebar-expander-width));
|
|
1358
|
+
display: grid;
|
|
1359
|
+
grid-template-columns: 100%;
|
|
1360
|
+
align-content: stretch;
|
|
1361
|
+
/* A shut sheet is still in flow now, and would otherwise hold the row
|
|
1362
|
+
open to its own height. The aside's width is set explicitly, so
|
|
1363
|
+
size containment only ever zeroes out the height it would have
|
|
1364
|
+
contributed; the row still stretches it to full height. */
|
|
1365
|
+
contain: size;
|
|
1366
|
+
}
|
|
1367
|
+
aside.sticky > .content, aside.sticky > button.expander, aside.sticky > button.close {
|
|
1368
|
+
grid-area: 1/1;
|
|
1369
|
+
position: sticky;
|
|
1370
|
+
align-self: start;
|
|
1371
|
+
justify-self: start;
|
|
1372
|
+
left: auto;
|
|
1373
|
+
right: auto;
|
|
1374
|
+
}
|
|
1375
|
+
aside.sticky > .content {
|
|
1376
|
+
top: var(--_sidebar-sheet-top);
|
|
1377
|
+
margin-left: 0;
|
|
1378
|
+
height: auto;
|
|
1379
|
+
/* The reserve is a budget for everything that is not the sheet, rather
|
|
1380
|
+
than just the sticky offset: before the sheet sticks -- page scrolled
|
|
1381
|
+
to the top -- its top edge is its row's, which may sit well below the
|
|
1382
|
+
viewport top, and a sheet sized only from the offset would overflow
|
|
1383
|
+
the viewport by exactly that much. Twice the top gives it an even
|
|
1384
|
+
margin at both ends once it has stuck. */
|
|
1385
|
+
max-height: var(--sidebar-sheet-max-height, calc(100dvh - var(--sidebar-sheet-reserve, calc(2 * var(--_sidebar-sheet-top)))));
|
|
1386
|
+
overflow-y: auto;
|
|
1387
|
+
/* A column, so a child with `min-height: 0` and its own overflow can
|
|
1388
|
+
keep a header or footer in view and scroll only its middle. Children
|
|
1389
|
+
that do not opt in keep their size, and the sheet scrolls as a
|
|
1390
|
+
whole. */
|
|
1391
|
+
display: flex;
|
|
1392
|
+
flex-direction: column;
|
|
1393
|
+
}
|
|
1394
|
+
aside.sticky.expandedHamburger > .content {
|
|
1395
|
+
height: auto;
|
|
1396
|
+
}
|
|
1397
|
+
aside.sticky.right > .content {
|
|
1398
|
+
margin-left: calc(var(--_sidebar-aside-width) - var(--sidebar-width));
|
|
1185
1399
|
}
|
|
1400
|
+
aside.sticky > button.expander, aside.sticky > button.close {
|
|
1401
|
+
top: calc(var(--_sidebar-sheet-top) + var(--padding));
|
|
1402
|
+
margin-top: var(--padding);
|
|
1403
|
+
margin-left: 0;
|
|
1404
|
+
transition: margin-left var(--sidebar-transition);
|
|
1405
|
+
}
|
|
1406
|
+
aside.sticky > button.close {
|
|
1407
|
+
margin-left: calc(var(--sidebar-width) - var(--_sidebar-expander-width));
|
|
1408
|
+
}
|
|
1409
|
+
aside.sticky.right > button.expander {
|
|
1410
|
+
margin-left: var(--gap);
|
|
1411
|
+
}
|
|
1412
|
+
aside.sticky.right > button.close {
|
|
1413
|
+
margin-left: calc(var(--_sidebar-aside-width) - var(--sidebar-width));
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
aside.button-sheet-toggle {
|
|
1417
|
+
--_sidebar-sheet-edge-override: var(--_sidebar-sheet-button-radius);
|
|
1186
1418
|
}
|
|
1419
|
+
|
|
1187
1420
|
button::after {
|
|
1188
1421
|
color: var(--sidebar-icon-fg, var(--fg, currentColor));
|
|
1189
1422
|
background-position: center;
|
|
@@ -18,6 +18,40 @@ declare const Sidebar: import("svelte").Component<ContainProps<HTMLAttributes<HT
|
|
|
18
18
|
* top of the content is worse.
|
|
19
19
|
*/
|
|
20
20
|
overlay?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Pin the sheet to the viewport while the page scrolls past it, instead
|
|
23
|
+
* of stretching it to the height of whatever it sits beside.
|
|
24
|
+
*
|
|
25
|
+
* Without it, an open sheet is as tall as its row -- right beside a
|
|
26
|
+
* short card, wrong beside a fifty-row table, where the top of the
|
|
27
|
+
* panel scrolls away and anything at its foot ends up off the bottom of
|
|
28
|
+
* the page. With it, the sheet (and its button) stick at
|
|
29
|
+
* `--sidebar-sheet-top` and stop growing at `--sidebar-sheet-max-height`,
|
|
30
|
+
* scrolling their own content past that.
|
|
31
|
+
*
|
|
32
|
+
* Applies wherever the sheet does: any `overlay` sidebar, and any
|
|
33
|
+
* sidebar in the compact layout. The wide rail is unaffected. Like any
|
|
34
|
+
* `position: sticky`, it needs every ancestor up to the scrolling one to
|
|
35
|
+
* leave `overflow` alone.
|
|
36
|
+
*/
|
|
37
|
+
sticky?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The shape of the sheet's toggle button (the sheet is what any
|
|
40
|
+
* `overlay` sidebar, and any sidebar in the compact layout, uses).
|
|
41
|
+
*
|
|
42
|
+
* - `"tab"` (default): the corners on the side it attaches to are
|
|
43
|
+
* square, so it reads as fastened to that edge -- the page edge while
|
|
44
|
+
* shut, the panel's edge while open. Right against a page edge.
|
|
45
|
+
* - `"button"`: rounded all round like any other button, for a sheet
|
|
46
|
+
* that does not sit against an edge -- beside a table, inside page
|
|
47
|
+
* padding -- where a half-flat tab looks broken.
|
|
48
|
+
*
|
|
49
|
+
* Per-state control, if you need it, is by variable:
|
|
50
|
+
* `--sidebar-sheet-expand-edge-radius` (the shut button) and
|
|
51
|
+
* `--sidebar-sheet-collapse-edge-radius` (the open one), both falling
|
|
52
|
+
* back to `--sidebar-sheet-edge-radius`.
|
|
53
|
+
*/
|
|
54
|
+
sheetButton?: "tab" | "button";
|
|
21
55
|
/**
|
|
22
56
|
* Whether the sidebar is showing its panel. Bindable, so a caller can
|
|
23
57
|
* drive the sidebar from a button of their own:
|
|
@@ -18,7 +18,33 @@ const el = $derived(elementProps(restProps, "sidebar-container", [
|
|
|
18
18
|
{@render children?.()}
|
|
19
19
|
</div>
|
|
20
20
|
|
|
21
|
-
<style>/*
|
|
21
|
+
<style>/* Per-level heading (h1-h6) box/typography properties, resolved to PRIVATE,
|
|
22
|
+
inheriting custom properties (--_h1-color, --_h2-font-size, etc) rather than
|
|
23
|
+
assigned directly to a matched h1-h6 selector. Nothing in this file matches
|
|
24
|
+
an actual heading element anymore -- see typography-context.css (vars/), which
|
|
25
|
+
is the single, global, :where()-scoped rule that actually reads these vars
|
|
26
|
+
and applies them to real elements. That split is what lets a component
|
|
27
|
+
nested arbitrarily deep (through <article>, <Tile>, whatever) still get the
|
|
28
|
+
nearest ancestor's heading styling: these are ordinary inherited custom
|
|
29
|
+
properties, so DOM proximity decides which component's values apply, not
|
|
30
|
+
selector specificity or stylesheet order. See AGENTS-INTERNAL.md. */
|
|
31
|
+
/* All six heading levels' context vars in one call -- what every
|
|
32
|
+
"typography container" component (Container, Card, Tile, TextLayout, ...)
|
|
33
|
+
includes on itself once, alongside the shared --_heading-* vars below. */
|
|
34
|
+
/* Shared prose-measure group: p, blockquote, dl, ul, ol. li/dt/dd don't get
|
|
35
|
+
their own vars -- they're never wider than their ul/ol/dl parent's own
|
|
36
|
+
max-width box, so they're already bounded for free by ordinary block
|
|
37
|
+
layout, not by anything selector-based reaching them individually. */
|
|
38
|
+
/* p specifically also gets the fuller typography-props-bare treatment
|
|
39
|
+
(paragraph-prefixed), which -- same as in the original selector-based
|
|
40
|
+
version -- is declared/consumed AFTER the shared prose vars above, so it
|
|
41
|
+
wins for whichever properties both groups set. */
|
|
42
|
+
/* The first paragraph in a typography context (p:first-of-type, or a p right
|
|
43
|
+
after a heading) gets its own, slightly different treatment -- larger lede
|
|
44
|
+
text, no top margin. Structural matching (:first-of-type, `h1 + p`) still
|
|
45
|
+
has to happen where the real element is, in the global consumer rule; only
|
|
46
|
+
the VALUES move to context vars here. */
|
|
47
|
+
/* Logical, not top/bottom/left/right: margin-block/margin-inline already take
|
|
22
48
|
one value (both sides equal) or two (start end), so there is no separate
|
|
23
49
|
"which side" prop to remember and no 4-value shorthand order to get wrong.
|
|
24
50
|
Defaults to 0 on purpose -- unlike padding-props above, a margin that
|