@lostgradient/cinder 0.12.0 → 0.13.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/CHANGELOG.md +12 -0
- package/components.json +9 -6
- package/dist/components/accordion/index.js +14 -11
- package/dist/components/accordion-item/accordion-item.css +20 -7
- package/dist/components/accordion-item/accordion-item.schema.js +5 -1
- package/dist/components/accordion-item/accordion-item.types.d.ts +4 -0
- package/dist/components/accordion-item/accordion-item.variables.js +13 -2
- package/dist/components/accordion-item/index.js +14 -11
- package/dist/components/action-row/action-row.css +20 -9
- package/dist/components/action-row/action-row.schema.js +5 -1
- package/dist/components/action-row/action-row.types.d.ts +43 -0
- package/dist/components/action-row/action-row.variables.js +12 -2
- package/dist/components/chat/chat.svelte.d.ts +1 -0
- package/dist/components/diff-viewer/index.js +201 -101
- package/dist/components/json-schema-editor/index.js +229 -129
- package/dist/components/markdown-editor/index.js +207 -107
- package/dist/components/review-editor/index.js +291 -191
- package/dist/components/schedule-builder/index.js +205 -105
- package/dist/components/segment/index.js +119 -56
- package/dist/components/segment/segment.schema.d.ts +2 -2
- package/dist/components/segment/segment.schema.js +71 -33
- package/dist/components/segment/segment.svelte.d.ts +2 -1
- package/dist/components/segment/segment.types.d.ts +67 -10
- package/dist/components/segmented-control/index.js +193 -93
- package/dist/components/segmented-control/segmented-control-state.svelte.d.ts +4 -4
- package/dist/components/segmented-control/segmented-control.css +26 -6
- package/dist/components/segmented-control/segmented-control.schema.js +3 -3
- package/dist/components/segmented-control/segmented-control.svelte.d.ts +2 -1
- package/dist/components/segmented-control/segmented-control.types.d.ts +4 -4
- package/dist/components/side-navigation/side-navigation.css +2 -1
- package/dist/components/side-navigation/side-navigation.schema.js +9 -6
- package/dist/components/side-navigation/side-navigation.types.d.ts +11 -0
- package/dist/components/side-navigation/side-navigation.variables.js +2 -2
- package/dist/components/sidebar/index.d.ts +1 -0
- package/dist/components/sidebar/index.js +9 -3
- package/dist/components/sidebar/sidebar.constants.d.ts +12 -0
- package/dist/components/stat/stat.css +16 -8
- package/dist/components/stat/stat.schema.js +5 -1
- package/dist/components/stat/stat.types.d.ts +19 -0
- package/dist/components/stat/stat.variables.js +11 -2
- package/dist/components/stat-group/stat-group.css +7 -4
- package/dist/components/stat-group/stat-group.schema.js +5 -1
- package/dist/components/stat-group/stat-group.types.d.ts +27 -0
- package/dist/components/stat-group/stat-group.variables.js +6 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +479 -368
- package/dist/server/components/accordion/index.js +2 -2
- package/dist/server/components/accordion-item/index.js +2 -2
- package/dist/server/components/diff-viewer/index.js +4 -4
- package/dist/server/components/json-schema-editor/index.js +4 -4
- package/dist/server/components/markdown-editor/index.js +3 -3
- package/dist/server/components/review-editor/index.js +4 -4
- package/dist/server/components/schedule-builder/index.js +3 -3
- package/dist/server/components/segment/index.js +2 -2
- package/dist/server/components/segmented-control/index.js +3 -3
- package/dist/server/components/sidebar/index.js +7 -3
- package/dist/server/index.js +19 -13
- package/dist/server/{index.server-cf6pxeyg.js → index.server-0rzd71e0.js} +1 -1
- package/dist/server/{index.server-jgb8yh5k.js → index.server-2m1kenak.js} +1 -1
- package/dist/server/{index.server-jfrssta6.js → index.server-ck3fwrab.js} +1 -1
- package/dist/server/{index.server-sedjxt36.js → index.server-e89qfamd.js} +79 -35
- package/dist/server/{index.server-pag862vz.js → index.server-grgv455a.js} +2 -2
- package/dist/server/{index.server-y83kqayt.js → index.server-h3nzp8g8.js} +1 -1
- package/dist/server/{index.server-2qj6s2mh.js → index.server-j570vb03.js} +7 -3
- package/dist/server/index.server-jwvxxjvc.js +50 -0
- package/dist/server/{index.server-xeqtpv61.js → index.server-mr68brd6.js} +49 -24
- package/dist/server/{index.server-qbkxz7r2.js → index.server-nx9c2ep1.js} +2 -2
- package/dist/server/{index.server-jj76374p.js → index.server-p071e531.js} +1 -1
- package/dist/server/{index.server-5gzyqv78.js → index.server-v3arexq8.js} +2 -2
- package/dist/server/{index.server-85p4ydph.js → index.server-zzd5wpbw.js} +1 -1
- package/package.json +1 -1
- package/src/components/accordion/accordion.examples.json +6 -0
- package/src/components/accordion-item/accordion-item.css +20 -7
- package/src/components/accordion-item/accordion-item.schema.json +4 -0
- package/src/components/accordion-item/accordion-item.schema.ts +4 -0
- package/src/components/accordion-item/accordion-item.svelte +9 -7
- package/src/components/accordion-item/accordion-item.types.ts +4 -0
- package/src/components/accordion-item/accordion-item.variables.json +12 -1
- package/src/components/accordion-item/accordion-item.variables.ts +12 -1
- package/src/components/action-row/action-row.css +20 -9
- package/src/components/action-row/action-row.examples.json +6 -0
- package/src/components/action-row/action-row.schema.json +4 -0
- package/src/components/action-row/action-row.schema.ts +4 -0
- package/src/components/action-row/action-row.types.ts +44 -0
- package/src/components/action-row/action-row.variables.json +11 -1
- package/src/components/action-row/action-row.variables.ts +11 -1
- package/src/components/chat/chat.examples.json +6 -0
- package/src/components/segment/segment.schema.json +34 -7
- package/src/components/segment/segment.schema.ts +5 -47
- package/src/components/segment/segment.svelte +58 -23
- package/src/components/segment/segment.types.ts +81 -11
- package/src/components/segmented-control/segmented-control.css +26 -6
- package/src/components/segmented-control/segmented-control.examples.json +6 -0
- package/src/components/segmented-control/segmented-control.schema.json +2 -2
- package/src/components/segmented-control/segmented-control.schema.ts +2 -2
- package/src/components/segmented-control/segmented-control.svelte +50 -23
- package/src/components/segmented-control/segmented-control.types.ts +4 -7
- package/src/components/side-navigation/side-navigation.css +2 -1
- package/src/components/side-navigation/side-navigation.examples.json +6 -0
- package/src/components/side-navigation/side-navigation.schema.json +8 -5
- package/src/components/side-navigation/side-navigation.schema.ts +8 -5
- package/src/components/side-navigation/side-navigation.types.ts +12 -0
- package/src/components/side-navigation/side-navigation.variables.json +1 -1
- package/src/components/side-navigation/side-navigation.variables.ts +1 -1
- package/src/components/sidebar/index.ts +1 -0
- package/src/components/sidebar/sidebar.constants.ts +13 -0
- package/src/components/sidebar/sidebar.examples.json +6 -0
- package/src/components/sidebar/sidebar.svelte +4 -5
- package/src/components/stat/stat.css +16 -8
- package/src/components/stat/stat.schema.json +4 -0
- package/src/components/stat/stat.schema.ts +4 -0
- package/src/components/stat/stat.types.ts +20 -0
- package/src/components/stat/stat.variables.json +10 -1
- package/src/components/stat/stat.variables.ts +10 -1
- package/src/components/stat-group/stat-group.css +7 -4
- package/src/components/stat-group/stat-group.examples.json +6 -0
- package/src/components/stat-group/stat-group.schema.json +4 -0
- package/src/components/stat-group/stat-group.schema.ts +4 -0
- package/src/components/stat-group/stat-group.types.ts +28 -0
- package/src/components/stat-group/stat-group.variables.json +5 -1
- package/src/components/stat-group/stat-group.variables.ts +5 -1
- package/src/index.ts +5 -1
- package/src/styles/foundation.css +2 -1
- package/dist/server/index.server-hfx487zj.js +0 -42
|
@@ -1,50 +1,8 @@
|
|
|
1
1
|
import type { ComponentSchema } from '../../schema-types';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type:
|
|
6
|
-
|
|
7
|
-
class: {
|
|
8
|
-
type: 'string',
|
|
9
|
-
description: 'Custom class merged with `.cinder-segmented-control-option`.',
|
|
10
|
-
},
|
|
11
|
-
disabled: {
|
|
12
|
-
type: 'boolean',
|
|
13
|
-
description: 'Disable just this segment (independent of the control-level `disabled`).',
|
|
14
|
-
},
|
|
15
|
-
controls: {
|
|
16
|
-
type: 'string',
|
|
17
|
-
description:
|
|
18
|
-
'ID of the panel this segment controls — only meaningful when the parent\n`SegmentedControl` uses `variant="tablist"`.',
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
additionalProperties: false,
|
|
22
|
-
metadata: {
|
|
23
|
-
unsupportedProps: [
|
|
24
|
-
{
|
|
25
|
-
name: 'children',
|
|
26
|
-
reason: 'function-or-snippet',
|
|
27
|
-
required: true,
|
|
28
|
-
description: "The segment's label content.",
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: 'leading',
|
|
32
|
-
reason: 'function-or-snippet',
|
|
33
|
-
description: 'Optional decorative content rendered before the label, inside `aria-hidden`.',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
name: 'trailing',
|
|
37
|
-
reason: 'function-or-snippet',
|
|
38
|
-
description: 'Optional decorative content rendered after the label, inside `aria-hidden`.',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: 'value',
|
|
42
|
-
reason: 'unknown-shape',
|
|
43
|
-
required: true,
|
|
44
|
-
description: 'Value this segment represents. Must be unique within the parent control.',
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
},
|
|
48
|
-
} satisfies ComponentSchema;
|
|
3
|
+
// eslint-disable-next-line no-unsafe-type-assertion -- generated schema parsed from a build-validated JSON string; see generate-component-schema.ts.
|
|
4
|
+
const schema = JSON.parse(
|
|
5
|
+
'{\n "$schema": "https://json-schema.org/draft/2020-12/schema",\n "type": "object",\n "properties": {\n "class": {\n "type": "string",\n "description": "Custom class merged with `.cinder-segmented-control-option`."\n },\n "disabled": {\n "type": "boolean",\n "description": "Disable just this segment (independent of the control-level `disabled`)."\n },\n "href": {\n "type": "string",\n "description": "Render this segment as a real link inside `SegmentedControl variant=\\"navigation\\"`."\n },\n "current": {\n "type": "boolean",\n "description": "Marks this linked segment as the current route/filter."\n },\n "currentToken": {\n "enum": [\n "page",\n "step",\n "location",\n "date",\n "time",\n "true"\n ],\n "description": "`aria-current` token emitted while `current` is true. Defaults to `\\"page\\"`."\n },\n "value": {\n "type": "string",\n "description": "Value this segment represents. Required when `href` is not provided."\n },\n "controls": {\n "type": "string",\n "description": "ID of the panel this segment controls — only meaningful when the parent\\n`SegmentedControl` uses `variant=\\"tablist\\"`."\n }\n },\n "additionalProperties": false,\n "metadata": {\n "unsupportedProps": [\n {\n "name": "children",\n "reason": "function-or-snippet",\n "required": true,\n "description": "The segment\'s label content."\n },\n {\n "name": "leading",\n "reason": "function-or-snippet",\n "description": "Optional decorative content rendered before the label, inside `aria-hidden`."\n },\n {\n "name": "onclick",\n "reason": "function-or-snippet",\n "description": "Optional click handler for the rendered link. Disabled navigation segments\\nprevent default and do not call this handler."\n },\n {\n "name": "trailing",\n "reason": "function-or-snippet",\n "description": "Optional decorative content rendered after the label, inside `aria-hidden`."\n }\n ]\n },\n "allOf": [\n {\n "if": {\n "not": {\n "required": [\n "href"\n ]\n }\n },\n "then": {\n "required": [\n "value"\n ]\n }\n }\n ]\n}',
|
|
6
|
+
) as ComponentSchema;
|
|
49
7
|
|
|
50
|
-
export default schema
|
|
8
|
+
export default schema;
|
|
@@ -6,8 +6,9 @@ export {};
|
|
|
6
6
|
import { untrack } from 'svelte';
|
|
7
7
|
import { classNames } from '../../utilities/class-names.ts';
|
|
8
8
|
import { getSegmentedControlContext } from '../segmented-control/segmented-control-state.svelte.ts';
|
|
9
|
-
let { value, disabled = false, controls, leading, trailing, children, class: customClassName, ...rest } = $props();
|
|
9
|
+
let { value, href, download, target, rel, current = false, currentToken = 'page', disabled = false, controls, leading, trailing, children, class: customClassName, onclick, ...rest } = $props();
|
|
10
10
|
const context = getSegmentedControlContext();
|
|
11
|
+
const buttonValue = $derived(value ?? href ?? '');
|
|
11
12
|
const registerSegment = (node) => {
|
|
12
13
|
// Attachments run inside a tracked effect. Wrap the call to register() in
|
|
13
14
|
// `untrack` so the controller's mutation of its internal state does not
|
|
@@ -18,7 +19,7 @@ const registerSegment = (node) => {
|
|
|
18
19
|
return untrack(() => context.register({
|
|
19
20
|
node,
|
|
20
21
|
get value() {
|
|
21
|
-
return
|
|
22
|
+
return buttonValue;
|
|
22
23
|
},
|
|
23
24
|
get disabled() {
|
|
24
25
|
return disabled || context.controlDisabled;
|
|
@@ -28,34 +29,28 @@ const registerSegment = (node) => {
|
|
|
28
29
|
},
|
|
29
30
|
}));
|
|
30
31
|
};
|
|
31
|
-
const isSelected = $derived(context.isSelected(
|
|
32
|
-
const isFocusable = $derived(context.isFocusable(
|
|
32
|
+
const isSelected = $derived(context.isSelected(buttonValue));
|
|
33
|
+
const isFocusable = $derived(context.isFocusable(buttonValue));
|
|
33
34
|
const effectiveDisabled = $derived(disabled || context.controlDisabled);
|
|
35
|
+
const isNavigationItem = $derived(context.variant === 'navigation');
|
|
36
|
+
const anchorDisabled = $derived(effectiveDisabled || href === undefined);
|
|
37
|
+
const elementAttributes = $derived(rest);
|
|
38
|
+
const anchorTabindex = $derived(anchorDisabled ? -1 : elementAttributes.tabindex);
|
|
34
39
|
const role = $derived(context.selectionMode === 'multiple'
|
|
35
40
|
? undefined
|
|
36
41
|
: context.variant === 'tablist'
|
|
37
42
|
? 'tab'
|
|
38
43
|
: 'radio');
|
|
44
|
+
function handleAnchorClick(event) {
|
|
45
|
+
if (anchorDisabled) {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
onclick?.(event);
|
|
50
|
+
}
|
|
39
51
|
</script>
|
|
40
52
|
|
|
41
|
-
|
|
42
|
-
{...rest}
|
|
43
|
-
type="button"
|
|
44
|
-
{role}
|
|
45
|
-
data-cinder-segment-value={value}
|
|
46
|
-
aria-checked={role === 'radio' ? isSelected : undefined}
|
|
47
|
-
aria-selected={role === 'tab' ? isSelected : undefined}
|
|
48
|
-
aria-pressed={context.selectionMode === 'multiple' ? isSelected : undefined}
|
|
49
|
-
aria-controls={role === 'tab' ? controls : undefined}
|
|
50
|
-
aria-disabled={effectiveDisabled ? 'true' : undefined}
|
|
51
|
-
disabled={context.selectionMode === 'multiple' ? effectiveDisabled : undefined}
|
|
52
|
-
tabindex={isFocusable ? 0 : -1}
|
|
53
|
-
class={classNames('cinder-segmented-control-option', customClassName)}
|
|
54
|
-
data-cinder-selected={isSelected ? '' : undefined}
|
|
55
|
-
data-cinder-pressed={context.selectionMode === 'multiple' && isSelected ? '' : undefined}
|
|
56
|
-
onclick={() => context.toggle(value)}
|
|
57
|
-
{@attach registerSegment}
|
|
58
|
-
>
|
|
53
|
+
{#snippet content()}
|
|
59
54
|
{#if leading}
|
|
60
55
|
<span class="cinder-segmented-control-option-icon" aria-hidden="true">
|
|
61
56
|
{@render leading()}
|
|
@@ -70,4 +65,44 @@ const role = $derived(context.selectionMode === 'multiple'
|
|
|
70
65
|
{@render trailing()}
|
|
71
66
|
</span>
|
|
72
67
|
{/if}
|
|
73
|
-
|
|
68
|
+
{/snippet}
|
|
69
|
+
|
|
70
|
+
{#if isNavigationItem}
|
|
71
|
+
<a
|
|
72
|
+
{...elementAttributes}
|
|
73
|
+
href={anchorDisabled ? undefined : href}
|
|
74
|
+
{download}
|
|
75
|
+
{target}
|
|
76
|
+
{rel}
|
|
77
|
+
data-cinder-segment-value={buttonValue}
|
|
78
|
+
aria-current={current ? currentToken : undefined}
|
|
79
|
+
aria-disabled={anchorDisabled ? 'true' : undefined}
|
|
80
|
+
tabindex={anchorTabindex}
|
|
81
|
+
class={classNames('cinder-segmented-control-option', customClassName)}
|
|
82
|
+
data-cinder-current={current ? '' : undefined}
|
|
83
|
+
onclick={handleAnchorClick}
|
|
84
|
+
>
|
|
85
|
+
{@render content()}
|
|
86
|
+
</a>
|
|
87
|
+
{:else}
|
|
88
|
+
<button
|
|
89
|
+
{...elementAttributes}
|
|
90
|
+
type="button"
|
|
91
|
+
{role}
|
|
92
|
+
data-cinder-segment-value={buttonValue}
|
|
93
|
+
aria-checked={role === 'radio' ? isSelected : undefined}
|
|
94
|
+
aria-selected={role === 'tab' ? isSelected : undefined}
|
|
95
|
+
aria-pressed={context.selectionMode === 'multiple' ? isSelected : undefined}
|
|
96
|
+
aria-controls={role === 'tab' ? controls : undefined}
|
|
97
|
+
aria-disabled={effectiveDisabled ? 'true' : undefined}
|
|
98
|
+
disabled={context.selectionMode === 'multiple' ? effectiveDisabled : undefined}
|
|
99
|
+
tabindex={isFocusable ? 0 : -1}
|
|
100
|
+
class={classNames('cinder-segmented-control-option', customClassName)}
|
|
101
|
+
data-cinder-selected={isSelected ? '' : undefined}
|
|
102
|
+
data-cinder-pressed={context.selectionMode === 'multiple' && isSelected ? '' : undefined}
|
|
103
|
+
onclick={() => context.toggle(buttonValue)}
|
|
104
|
+
{@attach registerSegment}
|
|
105
|
+
>
|
|
106
|
+
{@render content()}
|
|
107
|
+
</button>
|
|
108
|
+
{/if}
|
|
@@ -1,39 +1,109 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
import type {
|
|
2
|
+
import type { HTMLAnchorAttributes, HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
|
|
4
|
+
export type SegmentCurrentToken = 'page' | 'step' | 'location' | 'date' | 'time' | 'true';
|
|
3
5
|
|
|
4
6
|
// Attributes the component owns and computes itself, so a consumer value would
|
|
5
7
|
// be silently overridden. `onfocus` / `onblur` are intentionally NOT here: the
|
|
6
8
|
// component implements no focus handling, so forwarding them through `...rest`
|
|
7
9
|
// lets consumers wire focus-driven behavior (tooltips, analytics) on a segment.
|
|
10
|
+
type SharedProps = {
|
|
11
|
+
/** Custom class merged with `.cinder-segmented-control-option`. */
|
|
12
|
+
class?: string | undefined;
|
|
13
|
+
/** Disable just this segment (independent of the control-level `disabled`). */
|
|
14
|
+
disabled?: boolean | undefined;
|
|
15
|
+
/** Optional decorative content rendered before the label, inside `aria-hidden`. */
|
|
16
|
+
leading?: Snippet | undefined;
|
|
17
|
+
/** Optional decorative content rendered after the label, inside `aria-hidden`. */
|
|
18
|
+
trailing?: Snippet | undefined;
|
|
19
|
+
/** The segment's label content. */
|
|
20
|
+
children: Snippet;
|
|
21
|
+
};
|
|
22
|
+
|
|
8
23
|
type SegmentOwnedAttributes =
|
|
9
24
|
| 'role'
|
|
10
25
|
| 'type'
|
|
11
26
|
| 'disabled'
|
|
12
27
|
| 'tabindex'
|
|
13
28
|
| 'class'
|
|
29
|
+
| 'href'
|
|
30
|
+
| 'download'
|
|
31
|
+
| 'target'
|
|
32
|
+
| 'rel'
|
|
14
33
|
| 'aria-checked'
|
|
15
34
|
| 'aria-selected'
|
|
16
35
|
| 'aria-pressed'
|
|
17
36
|
| 'aria-controls'
|
|
18
37
|
| 'aria-disabled'
|
|
38
|
+
| 'aria-current'
|
|
19
39
|
| 'onclick';
|
|
20
40
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
type SharedElementAttributes = Omit<HTMLAttributes<HTMLElement>, SegmentOwnedAttributes>;
|
|
42
|
+
|
|
43
|
+
type SegmentButtonProps = SharedElementAttributes &
|
|
44
|
+
SharedProps & {
|
|
45
|
+
href?: undefined;
|
|
46
|
+
download?: undefined;
|
|
47
|
+
target?: undefined;
|
|
48
|
+
rel?: undefined;
|
|
49
|
+
current?: undefined;
|
|
50
|
+
currentToken?: undefined;
|
|
51
|
+
onclick?: undefined;
|
|
52
|
+
/** Value this segment represents. Must be unique within the parent control. */
|
|
53
|
+
value: string;
|
|
54
|
+
/**
|
|
55
|
+
* ID of the panel this segment controls — only meaningful when the parent
|
|
56
|
+
* `SegmentedControl` uses `variant="tablist"`.
|
|
57
|
+
*/
|
|
58
|
+
controls?: string | undefined;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
type SegmentAnchorProps = SharedElementAttributes &
|
|
62
|
+
SharedProps & {
|
|
63
|
+
/** Render this segment as a real link inside `SegmentedControl variant="navigation"`. */
|
|
64
|
+
href: string;
|
|
65
|
+
/** Download hint for the rendered link. */
|
|
66
|
+
download?: boolean | string | undefined;
|
|
67
|
+
/** Browsing context for the rendered link. */
|
|
68
|
+
target?: HTMLAnchorAttributes['target'] | undefined;
|
|
69
|
+
/** Relationship metadata for the rendered link. */
|
|
70
|
+
rel?: HTMLAnchorAttributes['rel'] | undefined;
|
|
71
|
+
/** Optional tab index for enabled links. Disabled navigation links force `-1`. */
|
|
72
|
+
tabindex?: HTMLAttributes<HTMLElement>['tabindex'] | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Optional click handler for the rendered link. Disabled navigation segments
|
|
75
|
+
* prevent default and do not call this handler.
|
|
76
|
+
*/
|
|
77
|
+
onclick?: ((event: MouseEvent) => void) | undefined;
|
|
78
|
+
/** Marks this linked segment as the current route/filter. */
|
|
79
|
+
current?: boolean | undefined;
|
|
80
|
+
/** `aria-current` token emitted while `current` is true. Defaults to `"page"`. */
|
|
81
|
+
currentToken?: SegmentCurrentToken | undefined;
|
|
82
|
+
/** Optional value for consumer metadata; navigation segments do not bind selection state. */
|
|
83
|
+
value?: string | undefined;
|
|
84
|
+
/** Panel controls apply only to tab segments, not navigation links. */
|
|
85
|
+
controls?: undefined;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export type SegmentProps = SegmentButtonProps | SegmentAnchorProps;
|
|
89
|
+
|
|
90
|
+
/** Schema generator surface for Segment's cinder-specific, JSON-expressible props. */
|
|
91
|
+
export interface SegmentSchemaProps {
|
|
24
92
|
/** Custom class merged with `.cinder-segmented-control-option`. */
|
|
25
93
|
class?: string | undefined;
|
|
26
94
|
/** Disable just this segment (independent of the control-level `disabled`). */
|
|
27
95
|
disabled?: boolean | undefined;
|
|
96
|
+
/** Render this segment as a real link inside `SegmentedControl variant="navigation"`. */
|
|
97
|
+
href?: string | undefined;
|
|
98
|
+
/** Marks this linked segment as the current route/filter. */
|
|
99
|
+
current?: boolean | undefined;
|
|
100
|
+
/** `aria-current` token emitted while `current` is true. Defaults to `"page"`. */
|
|
101
|
+
currentToken?: SegmentCurrentToken | undefined;
|
|
102
|
+
/** Value this segment represents. Required when `href` is not provided. */
|
|
103
|
+
value?: string | undefined;
|
|
28
104
|
/**
|
|
29
105
|
* ID of the panel this segment controls — only meaningful when the parent
|
|
30
106
|
* `SegmentedControl` uses `variant="tablist"`.
|
|
31
107
|
*/
|
|
32
108
|
controls?: string | undefined;
|
|
33
|
-
|
|
34
|
-
leading?: Snippet | undefined;
|
|
35
|
-
/** Optional decorative content rendered after the label, inside `aria-hidden`. */
|
|
36
|
-
trailing?: Snippet | undefined;
|
|
37
|
-
/** The segment's label content. */
|
|
38
|
-
children: Snippet;
|
|
39
|
-
};
|
|
109
|
+
}
|
|
@@ -98,6 +98,7 @@
|
|
|
98
98
|
cursor: pointer;
|
|
99
99
|
font-weight: var(--cinder-font-medium);
|
|
100
100
|
line-height: 1;
|
|
101
|
+
text-decoration: none;
|
|
101
102
|
transition:
|
|
102
103
|
background-color var(--cinder-duration-fast) var(--cinder-ease-standard),
|
|
103
104
|
color var(--cinder-duration-fast) var(--cinder-ease-standard),
|
|
@@ -117,11 +118,16 @@
|
|
|
117
118
|
|
|
118
119
|
.cinder-segmented-control:not([data-cinder-detached])
|
|
119
120
|
.cinder-segmented-control-option[data-cinder-selected]:not(:first-child)::before,
|
|
121
|
+
.cinder-segmented-control:not([data-cinder-detached])
|
|
122
|
+
.cinder-segmented-control-option[data-cinder-current]:not(:first-child)::before,
|
|
120
123
|
.cinder-segmented-control:not([data-cinder-detached])
|
|
121
124
|
.cinder-segmented-control-option[data-cinder-pressed]:not(:first-child)::before,
|
|
122
125
|
.cinder-segmented-control:not([data-cinder-detached])
|
|
123
126
|
[data-cinder-selected]
|
|
124
127
|
+ .cinder-segmented-control-option::before,
|
|
128
|
+
.cinder-segmented-control:not([data-cinder-detached])
|
|
129
|
+
[data-cinder-current]
|
|
130
|
+
+ .cinder-segmented-control-option::before,
|
|
125
131
|
.cinder-segmented-control:not([data-cinder-detached])
|
|
126
132
|
[data-cinder-pressed]
|
|
127
133
|
+ .cinder-segmented-control-option::before {
|
|
@@ -211,9 +217,9 @@
|
|
|
211
217
|
/* Sticky-hover suppression on touch: wrap hover-only chrome so it doesn't
|
|
212
218
|
* "stick" after tap on touch devices that emulate :hover. */
|
|
213
219
|
@media (hover: hover) {
|
|
214
|
-
.cinder-segmented-control-option:hover:not(:disabled):not([
|
|
215
|
-
[data-cinder-
|
|
216
|
-
) {
|
|
220
|
+
.cinder-segmented-control-option:hover:not(:disabled):not([aria-disabled='true']):not(
|
|
221
|
+
[data-cinder-selected]
|
|
222
|
+
):not([data-cinder-current]):not([data-cinder-pressed]) {
|
|
217
223
|
background: color-mix(in oklch, var(--cinder-accent), transparent 90%);
|
|
218
224
|
color: var(--cinder-text);
|
|
219
225
|
}
|
|
@@ -229,6 +235,9 @@
|
|
|
229
235
|
.cinder-segmented-control-option[data-cinder-selected]:hover:not(:disabled):not(
|
|
230
236
|
[aria-disabled='true']
|
|
231
237
|
),
|
|
238
|
+
.cinder-segmented-control-option[data-cinder-current]:hover:not(:disabled):not(
|
|
239
|
+
[aria-disabled='true']
|
|
240
|
+
),
|
|
232
241
|
.cinder-segmented-control-option[data-cinder-pressed]:hover:not(:disabled):not(
|
|
233
242
|
[aria-disabled='true']
|
|
234
243
|
) {
|
|
@@ -248,7 +257,8 @@
|
|
|
248
257
|
|
|
249
258
|
/* ── Disabled option ────────────────────────────────────────────────────── */
|
|
250
259
|
|
|
251
|
-
.cinder-segmented-control-option:disabled
|
|
260
|
+
.cinder-segmented-control-option:disabled,
|
|
261
|
+
.cinder-segmented-control-option[aria-disabled='true'] {
|
|
252
262
|
cursor: not-allowed;
|
|
253
263
|
/* opacity centralized in foundation.css disabled-visual rule (0.6) */
|
|
254
264
|
}
|
|
@@ -261,6 +271,12 @@
|
|
|
261
271
|
box-shadow: var(--cinder-shadow-sm);
|
|
262
272
|
}
|
|
263
273
|
|
|
274
|
+
.cinder-segmented-control-option[data-cinder-current] {
|
|
275
|
+
background: var(--cinder-accent);
|
|
276
|
+
color: var(--cinder-accent-contrast);
|
|
277
|
+
box-shadow: var(--cinder-shadow-sm);
|
|
278
|
+
}
|
|
279
|
+
|
|
264
280
|
.cinder-segmented-control-option-icon {
|
|
265
281
|
opacity: 0.9;
|
|
266
282
|
}
|
|
@@ -283,7 +299,9 @@
|
|
|
283
299
|
.cinder-segmented-control:not([data-cinder-variant='tablist'])
|
|
284
300
|
.cinder-segmented-control-option[data-cinder-selected]:focus-visible,
|
|
285
301
|
.cinder-segmented-control:not([data-cinder-variant='tablist'])
|
|
286
|
-
.cinder-segmented-control-option[data-cinder-pressed]:focus-visible
|
|
302
|
+
.cinder-segmented-control-option[data-cinder-pressed]:focus-visible,
|
|
303
|
+
.cinder-segmented-control:not([data-cinder-variant='tablist'])
|
|
304
|
+
.cinder-segmented-control-option[data-cinder-current]:focus-visible {
|
|
287
305
|
box-shadow:
|
|
288
306
|
0 0 0 var(--cinder-ring-offset) var(--cinder-ring-offset-color),
|
|
289
307
|
0 0 0 calc(var(--cinder-ring-offset) + var(--cinder-ring-width)) var(--cinder-ring-color);
|
|
@@ -296,7 +314,9 @@
|
|
|
296
314
|
.cinder-segmented-control:not([data-cinder-variant='tablist'])
|
|
297
315
|
.cinder-segmented-control-option[data-cinder-selected]:focus-visible,
|
|
298
316
|
.cinder-segmented-control:not([data-cinder-variant='tablist'])
|
|
299
|
-
.cinder-segmented-control-option[data-cinder-pressed]:focus-visible
|
|
317
|
+
.cinder-segmented-control-option[data-cinder-pressed]:focus-visible,
|
|
318
|
+
.cinder-segmented-control:not([data-cinder-variant='tablist'])
|
|
319
|
+
.cinder-segmented-control-option[data-cinder-current]:focus-visible {
|
|
300
320
|
outline: var(--cinder-ring-width) solid Highlight;
|
|
301
321
|
outline-offset: 1px;
|
|
302
322
|
box-shadow: none;
|
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
"description": "Multiple options can be toggled independently. Pass a SvelteSet to track selection.",
|
|
16
16
|
"code": "<script lang=\"ts\">\n import { SvelteSet } from 'svelte/reactivity';\n import { Segment } from '@lostgradient/cinder/segment';\n import { SegmentedControl } from '@lostgradient/cinder/segmented-control';\n\n let formats = new SvelteSet<string>();\n\n const selected = $derived([...formats].join(', ') || 'none');\n</script>\n\n<div style=\"display: grid; gap: 0.75rem; justify-items: start;\">\n <SegmentedControl\n id=\"playground-format\"\n selectionMode=\"multiple\"\n value={formats}\n label=\"Text formatting\"\n >\n <Segment value=\"bold\">Bold</Segment>\n <Segment value=\"italic\">Italic</Segment>\n <Segment value=\"underline\">Underline</Segment>\n <Segment value=\"strikethrough\">Strike</Segment>\n </SegmentedControl>\n <p style=\"margin: 0; color: var(--cinder-text-muted);\">Active formats: {selected}</p>\n</div>\n"
|
|
17
17
|
},
|
|
18
|
+
{
|
|
19
|
+
"id": "navigation",
|
|
20
|
+
"title": "Navigation route filters",
|
|
21
|
+
"description": "Use the navigation variant with linked segments when each option should update the URL.",
|
|
22
|
+
"code": "<script lang=\"ts\">\n import { Segment } from '@lostgradient/cinder/segment';\n import { SegmentedControl } from '@lostgradient/cinder/segmented-control';\n\n const sources = [\n { label: 'Actual', href: '/costs?source=actual', current: true },\n { label: 'Forecast', href: '/costs?source=forecast' },\n { label: 'Blended', href: '/costs?source=blended' },\n ];\n</script>\n\n<SegmentedControl id=\"cost-source-filter\" label=\"Cost source\" variant=\"navigation\">\n {#each sources as source (source.href)}\n <Segment href={source.href} current={source.current}>{source.label}</Segment>\n {/each}\n</SegmentedControl>\n"
|
|
23
|
+
},
|
|
18
24
|
{
|
|
19
25
|
"id": "sizing",
|
|
20
26
|
"title": "Sizing — size vs. toolbar density",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"description": "Stretch the control to fill available width."
|
|
44
44
|
},
|
|
45
45
|
"variant": {
|
|
46
|
-
"enum": ["radiogroup", "tablist"],
|
|
47
|
-
"description": "ARIA interaction pattern. Use `
|
|
46
|
+
"enum": ["radiogroup", "tablist", "navigation"],
|
|
47
|
+
"description": "ARIA interaction pattern. Use `navigation` for route-backed links."
|
|
48
48
|
},
|
|
49
49
|
"class": {
|
|
50
50
|
"type": "string",
|
|
@@ -48,8 +48,8 @@ const schema = {
|
|
|
48
48
|
description: 'Stretch the control to fill available width.',
|
|
49
49
|
},
|
|
50
50
|
variant: {
|
|
51
|
-
enum: ['radiogroup', 'tablist'],
|
|
52
|
-
description: 'ARIA interaction pattern. Use `
|
|
51
|
+
enum: ['radiogroup', 'tablist', 'navigation'],
|
|
52
|
+
description: 'ARIA interaction pattern. Use `navigation` for route-backed links.',
|
|
53
53
|
},
|
|
54
54
|
class: {
|
|
55
55
|
type: 'string',
|
|
@@ -12,9 +12,11 @@ let resetInputElement = $state(null);
|
|
|
12
12
|
let resetSyncTimeout;
|
|
13
13
|
const initialSingleValue = untrack(() => (typeof value === 'string' ? value : undefined));
|
|
14
14
|
const initialMultipleValues = untrack(() => selectionMode === 'multiple' && value instanceof SvelteSet ? Array.from(value) : undefined);
|
|
15
|
+
const effectiveVariant = $derived(selectionMode === 'multiple' && variant !== 'radiogroup' ? 'radiogroup' : variant);
|
|
16
|
+
const rendersNavigation = $derived(effectiveVariant === 'navigation');
|
|
15
17
|
const controller = new SegmentedControlController({
|
|
16
18
|
selectionMode: () => selectionMode,
|
|
17
|
-
variant: () =>
|
|
19
|
+
variant: () => effectiveVariant,
|
|
18
20
|
orientation: () => orientation,
|
|
19
21
|
controlDisabled: () => disabled,
|
|
20
22
|
disallowEmptySelection: () => disallowEmptySelection,
|
|
@@ -29,7 +31,7 @@ const contextValue = {
|
|
|
29
31
|
return selectionMode;
|
|
30
32
|
},
|
|
31
33
|
get variant() {
|
|
32
|
-
return
|
|
34
|
+
return effectiveVariant;
|
|
33
35
|
},
|
|
34
36
|
get controlDisabled() {
|
|
35
37
|
return disabled;
|
|
@@ -41,7 +43,13 @@ const contextValue = {
|
|
|
41
43
|
};
|
|
42
44
|
setSegmentedControlContext(contextValue);
|
|
43
45
|
// See docs/decisions/segmented-control-tablist-variant.md for why tablist remains a SegmentedControl variant.
|
|
44
|
-
const groupRole = $derived(selectionMode === 'multiple'
|
|
46
|
+
const groupRole = $derived(selectionMode === 'multiple'
|
|
47
|
+
? 'group'
|
|
48
|
+
: variant === 'navigation'
|
|
49
|
+
? undefined
|
|
50
|
+
: variant === 'tablist'
|
|
51
|
+
? 'tablist'
|
|
52
|
+
: 'radiogroup');
|
|
45
53
|
// When density="toolbar" is requested it resolves to the compact `sm` visual
|
|
46
54
|
// size — explicit `size` values are ignored while toolbar density is on so
|
|
47
55
|
// toolbars line up with sibling toolbar controls. `data-cinder-size` reflects
|
|
@@ -94,26 +102,45 @@ $effect(() => {
|
|
|
94
102
|
>
|
|
95
103
|
{label}
|
|
96
104
|
</span>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
105
|
+
{#if rendersNavigation}
|
|
106
|
+
<nav
|
|
107
|
+
{...rest}
|
|
108
|
+
{id}
|
|
109
|
+
role="navigation"
|
|
110
|
+
aria-labelledby={`${id}-label`}
|
|
111
|
+
data-cinder-orientation={orientation}
|
|
112
|
+
data-cinder-size={effectiveSize}
|
|
113
|
+
data-cinder-density={density === 'toolbar' ? 'toolbar' : undefined}
|
|
114
|
+
data-cinder-selection-mode={selectionMode}
|
|
115
|
+
data-cinder-detached={detached ? '' : undefined}
|
|
116
|
+
data-cinder-full-width={fullWidth ? '' : undefined}
|
|
117
|
+
data-cinder-variant={effectiveVariant}
|
|
118
|
+
class={classNames('cinder-segmented-control', customClassName)}
|
|
119
|
+
>
|
|
120
|
+
{@render children()}
|
|
121
|
+
</nav>
|
|
122
|
+
{:else}
|
|
123
|
+
<div
|
|
124
|
+
{...rest}
|
|
125
|
+
{id}
|
|
126
|
+
role={groupRole}
|
|
127
|
+
aria-labelledby={`${id}-label`}
|
|
128
|
+
aria-disabled={disabled ? 'true' : undefined}
|
|
129
|
+
aria-orientation={selectionMode === 'single' ? orientation : undefined}
|
|
130
|
+
data-cinder-orientation={orientation}
|
|
131
|
+
data-cinder-size={effectiveSize}
|
|
132
|
+
data-cinder-density={density === 'toolbar' ? 'toolbar' : undefined}
|
|
133
|
+
data-cinder-selection-mode={selectionMode}
|
|
134
|
+
data-cinder-detached={detached ? '' : undefined}
|
|
135
|
+
data-cinder-full-width={fullWidth ? '' : undefined}
|
|
136
|
+
data-cinder-variant={effectiveVariant}
|
|
137
|
+
class={classNames('cinder-segmented-control', customClassName)}
|
|
138
|
+
onkeydown={(event) => controller.handleKeydown(event)}
|
|
139
|
+
>
|
|
140
|
+
{@render children()}
|
|
141
|
+
</div>
|
|
142
|
+
{/if}
|
|
143
|
+
{#if name && !rendersNavigation}
|
|
117
144
|
<input bind:this={resetInputElement} type="hidden" disabled />
|
|
118
145
|
{#each selectedValues as selectedValue (selectedValue)}
|
|
119
146
|
<input type="hidden" {name} value={selectedValue} {disabled} />
|
|
@@ -14,10 +14,7 @@ type ComponentOwnedAttributes =
|
|
|
14
14
|
| 'onchange'
|
|
15
15
|
| 'onkeydown';
|
|
16
16
|
|
|
17
|
-
type CommonProps<T extends string> = Omit<
|
|
18
|
-
HTMLAttributes<HTMLDivElement>,
|
|
19
|
-
ComponentOwnedAttributes
|
|
20
|
-
> & {
|
|
17
|
+
type CommonProps<T extends string> = Omit<HTMLAttributes<HTMLElement>, ComponentOwnedAttributes> & {
|
|
21
18
|
/** Unique identifier for the control. */
|
|
22
19
|
id: string;
|
|
23
20
|
/** Accessible label for the group. */
|
|
@@ -53,8 +50,8 @@ type CommonProps<T extends string> = Omit<
|
|
|
53
50
|
detached?: boolean | undefined;
|
|
54
51
|
/** Stretch the control to fill available width. */
|
|
55
52
|
fullWidth?: boolean | undefined;
|
|
56
|
-
/** ARIA interaction pattern. Use `
|
|
57
|
-
variant?: 'radiogroup' | 'tablist' | undefined;
|
|
53
|
+
/** ARIA interaction pattern. Use `navigation` for route-backed links. */
|
|
54
|
+
variant?: 'radiogroup' | 'tablist' | 'navigation' | undefined;
|
|
58
55
|
/** Additional class names merged with `.cinder-segmented-control`. */
|
|
59
56
|
class?: string | undefined;
|
|
60
57
|
/** Called when the selected value changes (single mode only). */
|
|
@@ -82,7 +79,7 @@ type MultipleProps<T extends string> = CommonProps<T> & {
|
|
|
82
79
|
value?: SvelteSet<T> | undefined;
|
|
83
80
|
/** Not applicable in multiple mode — present for Svelte destructuring compatibility. */
|
|
84
81
|
disallowEmptySelection?: undefined;
|
|
85
|
-
/** Tablist semantics are only valid for single selection. */
|
|
82
|
+
/** Tablist and navigation semantics are only valid for single selection. */
|
|
86
83
|
variant?: 'radiogroup' | undefined;
|
|
87
84
|
};
|
|
88
85
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* ======================================== */
|
|
14
14
|
|
|
15
15
|
.cinder-side-navigation {
|
|
16
|
+
--cinder-side-navigation-list-gap: var(--cinder-space-1);
|
|
16
17
|
display: block;
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
padding: 0;
|
|
23
24
|
display: flex;
|
|
24
25
|
flex-direction: column;
|
|
25
|
-
gap: var(--cinder-space-1);
|
|
26
|
+
gap: var(--cinder-side-navigation-list-gap, var(--cinder-space-1));
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/* ----------------------------------------
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
"description": "A grouped sidebar nav. Uses the SideNavigation namespace API: SideNavigation.Group wraps a collapsible section and SideNavigation.Item renders each link.",
|
|
10
10
|
"code": "<script lang=\"ts\">\n import { SideNavigation } from '@lostgradient/cinder/side-navigation';\n</script>\n\n<SideNavigation ariaLabel=\"Workspace\">\n <SideNavigation.Item href=\"/dashboard\">Dashboard</SideNavigation.Item>\n <SideNavigation.Group label=\"Projects\">\n <SideNavigation.Item href=\"/projects/phoenix\" active>Phoenix</SideNavigation.Item>\n <SideNavigation.Item href=\"/projects/atlas\">Atlas</SideNavigation.Item>\n <SideNavigation.Item href=\"/projects/beacon\">Beacon</SideNavigation.Item>\n </SideNavigation.Group>\n <SideNavigation.Group label=\"Settings\">\n <SideNavigation.Item href=\"/settings/team\">Team</SideNavigation.Item>\n <SideNavigation.Item href=\"/settings/billing\">Billing</SideNavigation.Item>\n </SideNavigation.Group>\n</SideNavigation>\n"
|
|
11
11
|
},
|
|
12
|
+
{
|
|
13
|
+
"id": "compact-sidebar",
|
|
14
|
+
"title": "Compact sidebar spacing",
|
|
15
|
+
"description": "Dense sidebars can tune the SideNavigation list gap through a public CSS variable.",
|
|
16
|
+
"code": "<script lang=\"ts\">\n import { SideNavigation } from '@lostgradient/cinder/side-navigation';\n</script>\n\n<div style=\"max-inline-size: 18rem;\">\n <SideNavigation ariaLabel=\"Inspector sections\" style=\"--cinder-side-navigation-list-gap: 0;\">\n <SideNavigation.Item href=\"#overview\" active>Overview</SideNavigation.Item>\n <SideNavigation.Item href=\"#timeline\">Timeline</SideNavigation.Item>\n <SideNavigation.Item href=\"#payload\">Payload</SideNavigation.Item>\n <SideNavigation.Group label=\"Artifacts\">\n <SideNavigation.Item href=\"#source\">Source</SideNavigation.Item>\n <SideNavigation.Item href=\"#snapshot\">Snapshot</SideNavigation.Item>\n </SideNavigation.Group>\n </SideNavigation>\n</div>\n"
|
|
17
|
+
},
|
|
12
18
|
{
|
|
13
19
|
"id": "docs-sidebar",
|
|
14
20
|
"title": "Docs sidebar",
|
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
"ariaLabel": {
|
|
6
6
|
"type": "string",
|
|
7
7
|
"description": "Accessible name for the <nav> landmark. Required, non-empty, distinct from other navs on the page."
|
|
8
|
+
},
|
|
9
|
+
"class": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Additional CSS class merged with `.cinder-side-navigation`."
|
|
12
|
+
},
|
|
13
|
+
"style": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Inline style string applied to the `.cinder-side-navigation` root."
|
|
8
16
|
}
|
|
9
17
|
},
|
|
10
18
|
"additionalProperties": false,
|
|
@@ -16,11 +24,6 @@
|
|
|
16
24
|
"reason": "function-or-snippet",
|
|
17
25
|
"required": true,
|
|
18
26
|
"description": "Must be <li> elements containing NavigationItem and/or SideNavigationGroup."
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"name": "class",
|
|
22
|
-
"reason": "unknown-shape",
|
|
23
|
-
"description": "Additional CSS class merged with `.cinder-side-navigation`."
|
|
24
27
|
}
|
|
25
28
|
]
|
|
26
29
|
}
|
|
@@ -9,6 +9,14 @@ const schema = {
|
|
|
9
9
|
description:
|
|
10
10
|
'Accessible name for the <nav> landmark. Required, non-empty, distinct from other navs on the page.',
|
|
11
11
|
},
|
|
12
|
+
class: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'Additional CSS class merged with `.cinder-side-navigation`.',
|
|
15
|
+
},
|
|
16
|
+
style: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
description: 'Inline style string applied to the `.cinder-side-navigation` root.',
|
|
19
|
+
},
|
|
12
20
|
},
|
|
13
21
|
additionalProperties: false,
|
|
14
22
|
required: ['ariaLabel'],
|
|
@@ -20,11 +28,6 @@ const schema = {
|
|
|
20
28
|
required: true,
|
|
21
29
|
description: 'Must be <li> elements containing NavigationItem and/or SideNavigationGroup.',
|
|
22
30
|
},
|
|
23
|
-
{
|
|
24
|
-
name: 'class',
|
|
25
|
-
reason: 'unknown-shape',
|
|
26
|
-
description: 'Additional CSS class merged with `.cinder-side-navigation`.',
|
|
27
|
-
},
|
|
28
31
|
],
|
|
29
32
|
},
|
|
30
33
|
} satisfies ComponentSchema;
|