zdp-design-system 0.43.8

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 (110) hide show
  1. package/CHANGELOG.md +449 -0
  2. package/LICENSE +21 -0
  3. package/README.md +568 -0
  4. package/THIRD_PARTY_NOTICES.md +34 -0
  5. package/dist/code.ts +2 -0
  6. package/dist/combobox.ts +9 -0
  7. package/dist/command.ts +1 -0
  8. package/dist/components/Accordion.svelte +97 -0
  9. package/dist/components/Avatar.svelte +90 -0
  10. package/dist/components/Badge.svelte +61 -0
  11. package/dist/components/Breadcrumb.svelte +97 -0
  12. package/dist/components/Button.svelte +163 -0
  13. package/dist/components/Callout.svelte +81 -0
  14. package/dist/components/Card.svelte +151 -0
  15. package/dist/components/CardHeader.svelte +58 -0
  16. package/dist/components/Checkbox.svelte +135 -0
  17. package/dist/components/CodeBlock.svelte +247 -0
  18. package/dist/components/Combobox.svelte +552 -0
  19. package/dist/components/CommandField.svelte +230 -0
  20. package/dist/components/ConfirmAction.svelte +307 -0
  21. package/dist/components/Container.svelte +63 -0
  22. package/dist/components/Dialog.svelte +303 -0
  23. package/dist/components/Disclosure.svelte +176 -0
  24. package/dist/components/Divider.svelte +41 -0
  25. package/dist/components/EmptyState.svelte +79 -0
  26. package/dist/components/ErrorText.svelte +18 -0
  27. package/dist/components/Field.svelte +38 -0
  28. package/dist/components/Grid.svelte +76 -0
  29. package/dist/components/HelpText.svelte +17 -0
  30. package/dist/components/Icon.svelte +45 -0
  31. package/dist/components/IconButton.svelte +162 -0
  32. package/dist/components/IdentityChip.svelte +130 -0
  33. package/dist/components/Inline.svelte +85 -0
  34. package/dist/components/InlineCode.svelte +27 -0
  35. package/dist/components/Input.svelte +109 -0
  36. package/dist/components/Kbd.svelte +63 -0
  37. package/dist/components/KeyValue.svelte +73 -0
  38. package/dist/components/Label.svelte +43 -0
  39. package/dist/components/Link.svelte +70 -0
  40. package/dist/components/LocaleSwitcher.svelte +209 -0
  41. package/dist/components/Menu.svelte +491 -0
  42. package/dist/components/Page.svelte +36 -0
  43. package/dist/components/PageHeader.svelte +93 -0
  44. package/dist/components/Pagination.svelte +297 -0
  45. package/dist/components/Popover.svelte +208 -0
  46. package/dist/components/Progress.svelte +111 -0
  47. package/dist/components/Radio.svelte +132 -0
  48. package/dist/components/Section.svelte +52 -0
  49. package/dist/components/SegmentedControl.svelte +190 -0
  50. package/dist/components/Select.svelte +88 -0
  51. package/dist/components/ShareDock.svelte +304 -0
  52. package/dist/components/Sheet.svelte +332 -0
  53. package/dist/components/ShortcutHint.svelte +52 -0
  54. package/dist/components/Skeleton.svelte +82 -0
  55. package/dist/components/SkipLink.svelte +40 -0
  56. package/dist/components/SortHeader.svelte +138 -0
  57. package/dist/components/Spinner.svelte +82 -0
  58. package/dist/components/Stack.svelte +62 -0
  59. package/dist/components/StatusToast.svelte +133 -0
  60. package/dist/components/Surface.svelte +53 -0
  61. package/dist/components/Switch.svelte +152 -0
  62. package/dist/components/Table.svelte +94 -0
  63. package/dist/components/TableToolbar.svelte +195 -0
  64. package/dist/components/Tabs.svelte +205 -0
  65. package/dist/components/TermSheet.svelte +392 -0
  66. package/dist/components/TermTrigger.svelte +70 -0
  67. package/dist/components/TextScaleControl.svelte +219 -0
  68. package/dist/components/Textarea.svelte +106 -0
  69. package/dist/components/ThemeToggle.svelte +148 -0
  70. package/dist/components/Toast.svelte +180 -0
  71. package/dist/components/Toolbar.svelte +83 -0
  72. package/dist/components/Tooltip.svelte +199 -0
  73. package/dist/components/VisuallyHidden.svelte +18 -0
  74. package/dist/disclosure.ts +11 -0
  75. package/dist/focusable.ts +36 -0
  76. package/dist/identity.ts +5 -0
  77. package/dist/index.d.ts +106 -0
  78. package/dist/index.js +76 -0
  79. package/dist/index.ts +106 -0
  80. package/dist/menu.ts +12 -0
  81. package/dist/modal-layer.ts +108 -0
  82. package/dist/pagination.ts +10 -0
  83. package/dist/preferences.js +14 -0
  84. package/dist/preferences.ts +36 -0
  85. package/dist/progress.ts +4 -0
  86. package/dist/schemas/design-tokens.schema.json +119 -0
  87. package/dist/segmented.ts +8 -0
  88. package/dist/share.d.ts +48 -0
  89. package/dist/share.js +115 -0
  90. package/dist/share.ts +99 -0
  91. package/dist/sheet.ts +3 -0
  92. package/dist/shortcuts.js +125 -0
  93. package/dist/shortcuts.ts +153 -0
  94. package/dist/styles/brand-fonts.css +10 -0
  95. package/dist/styles/components.css +4686 -0
  96. package/dist/styles/expressive-fonts.css +2 -0
  97. package/dist/styles/index.css +2 -0
  98. package/dist/styles/locale-fonts.css +4 -0
  99. package/dist/styles/tokens.css +413 -0
  100. package/dist/table-tools.ts +10 -0
  101. package/dist/term.ts +16 -0
  102. package/dist/theme.ts +2 -0
  103. package/dist/toast.ts +14 -0
  104. package/dist/tokens/zdp.tokens.json +241 -0
  105. package/dist/tokens.js +122 -0
  106. package/dist/tokens.ts +123 -0
  107. package/docs/CONSUMER_CONTRACT.md +482 -0
  108. package/docs/EXTERNAL_UI_ADOPTION.md +141 -0
  109. package/docs/INTERACTIVE_PRIMITIVE_AUDIT.md +127 -0
  110. package/package.json +78 -0
@@ -0,0 +1,132 @@
1
+ <script lang="ts">
2
+ export let id: string | null = null;
3
+ export let name: string | null = null;
4
+ export let value: string | null = null;
5
+ export let checked = false;
6
+ export let describedBy: string | null = null;
7
+ export let invalid = false;
8
+ export let disabled = false;
9
+ export let required = false;
10
+
11
+ function handleChange(event: Event): void {
12
+ checked = (event.currentTarget as HTMLInputElement).checked;
13
+ }
14
+ </script>
15
+
16
+ <label class="zdp-choice zdp-choice--radio" data-invalid={invalid ? 'true' : undefined}>
17
+ <input
18
+ class="zdp-choice__input"
19
+ id={id ?? undefined}
20
+ name={name ?? undefined}
21
+ type="radio"
22
+ value={value ?? undefined}
23
+ {checked}
24
+ aria-describedby={describedBy ?? undefined}
25
+ {disabled}
26
+ {required}
27
+ onchange={handleChange}
28
+ />
29
+ <span class="zdp-choice__mark" aria-hidden="true"></span>
30
+ <span class="zdp-choice__body">
31
+ <span class="zdp-choice__label"><slot /></span>
32
+ <slot name="help" />
33
+ </span>
34
+ </label>
35
+
36
+ <style>
37
+ .zdp-choice {
38
+ align-items: start;
39
+ color: var(--zdp-color-ink-normal);
40
+ cursor: pointer;
41
+ display: grid;
42
+ font-family: var(--zdp-font-family-sans);
43
+ gap: var(--zdp-space-3);
44
+ grid-template-columns: var(--zdp-control-choice-size) minmax(0, 1fr);
45
+ line-height: var(--zdp-type-body-small-line-height);
46
+ min-width: 0;
47
+ -webkit-user-select: none;
48
+ user-select: none;
49
+ }
50
+
51
+ .zdp-choice__input {
52
+ height: 1px;
53
+ margin: 0;
54
+ opacity: 0;
55
+ position: absolute;
56
+ width: 1px;
57
+ }
58
+
59
+ .zdp-choice__mark {
60
+ align-items: center;
61
+ background: var(--zdp-color-surface-panel);
62
+ border: var(--zdp-control-border-width) solid var(--zdp-color-line-strong);
63
+ border-radius: 50%;
64
+ box-sizing: border-box;
65
+ color: var(--zdp-color-ink-strong);
66
+ display: inline-flex;
67
+ height: var(--zdp-control-choice-size);
68
+ justify-content: center;
69
+ margin-top: var(--zdp-control-switch-thumb-offset);
70
+ -webkit-user-select: none;
71
+ user-select: none;
72
+ transition:
73
+ background-color var(--zdp-motion-fast) ease,
74
+ border-color var(--zdp-motion-fast) ease,
75
+ color var(--zdp-motion-fast) ease;
76
+ width: var(--zdp-control-choice-size);
77
+ }
78
+
79
+ .zdp-choice__mark::after {
80
+ background: currentcolor;
81
+ border-radius: 50%;
82
+ content: "";
83
+ display: none;
84
+ height: var(--zdp-control-choice-indicator-size);
85
+ width: var(--zdp-control-choice-indicator-size);
86
+ }
87
+
88
+ .zdp-choice:hover .zdp-choice__input:not(:checked):not(:disabled) + .zdp-choice__mark {
89
+ background: var(--zdp-color-surface-raised);
90
+ border-color: var(--zdp-color-line-strong);
91
+ }
92
+
93
+ .zdp-choice__input:checked + .zdp-choice__mark {
94
+ background: var(--zdp-color-accent-primary);
95
+ border-color: var(--zdp-color-accent-primary-strong);
96
+ }
97
+
98
+ :global([data-zdp-theme="dark"]) .zdp-choice__input:checked + .zdp-choice__mark {
99
+ color: var(--zdp-color-ink-inverse);
100
+ }
101
+
102
+ .zdp-choice__input:checked + .zdp-choice__mark::after {
103
+ display: block;
104
+ }
105
+
106
+ .zdp-choice__input:focus-visible + .zdp-choice__mark {
107
+ border-color: var(--zdp-color-focus-line);
108
+ outline: var(--zdp-control-focus-outline-width) solid var(--zdp-color-focus-surface);
109
+ outline-offset: var(--zdp-control-focus-outline-offset);
110
+ }
111
+
112
+ .zdp-choice[data-invalid="true"] .zdp-choice__mark {
113
+ border-color: var(--zdp-color-accent-danger);
114
+ }
115
+
116
+ .zdp-choice:has(.zdp-choice__input:disabled) {
117
+ cursor: not-allowed;
118
+ opacity: 0.56;
119
+ }
120
+
121
+ .zdp-choice__body {
122
+ display: grid;
123
+ gap: var(--zdp-space-1);
124
+ min-width: 0;
125
+ }
126
+
127
+ .zdp-choice__label {
128
+ color: var(--zdp-color-ink-strong);
129
+ font-size: var(--zdp-type-body-small-size);
130
+ line-height: var(--zdp-type-body-small-line-height);
131
+ }
132
+ </style>
@@ -0,0 +1,52 @@
1
+ <script lang="ts">
2
+ export let as: 'section' | 'div' | 'article' = 'section';
3
+ export let spacing: 'sm' | 'md' | 'lg' | 'xl' = 'lg';
4
+ export let tone: 'plain' | 'panel' | 'raised' = 'plain';
5
+ export let id: string | null = null;
6
+ export let labelledBy: string | null = null;
7
+ </script>
8
+
9
+ <svelte:element
10
+ this={as}
11
+ class={`zdp-section zdp-section--spacing-${spacing} zdp-section--${tone}`}
12
+ {id}
13
+ aria-labelledby={labelledBy ?? undefined}
14
+ >
15
+ <slot />
16
+ </svelte:element>
17
+
18
+ <style>
19
+ .zdp-section {
20
+ min-width: 0;
21
+ }
22
+
23
+ .zdp-section--spacing-sm {
24
+ padding-block: var(--zdp-space-4);
25
+ }
26
+
27
+ .zdp-section--spacing-md {
28
+ padding-block: var(--zdp-space-6);
29
+ }
30
+
31
+ .zdp-section--spacing-lg {
32
+ padding-block: var(--zdp-space-8);
33
+ }
34
+
35
+ .zdp-section--spacing-xl {
36
+ padding-block: var(--zdp-space-12);
37
+ }
38
+
39
+ .zdp-section--plain {
40
+ background: transparent;
41
+ }
42
+
43
+ .zdp-section--panel {
44
+ background: var(--zdp-color-surface-panel);
45
+ border-block: 1px solid var(--zdp-color-line-subtle);
46
+ }
47
+
48
+ .zdp-section--raised {
49
+ background: var(--zdp-color-surface-raised);
50
+ border-block: 1px solid var(--zdp-color-line-subtle);
51
+ }
52
+ </style>
@@ -0,0 +1,190 @@
1
+ <script lang="ts" context="module">
2
+ let nextSegmentedControlInstanceId = 0;
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ import type { ZdpSegmentedControlItem, ZdpSegmentedControlSize } from '../segmented';
7
+
8
+ export let items: readonly ZdpSegmentedControlItem[] = [];
9
+ export let selectedId: string | null = null;
10
+ export let ariaLabel = 'Selection toggle';
11
+ export let idPrefix: string | null = null;
12
+ export let size: ZdpSegmentedControlSize = 'md';
13
+ export let onChange:
14
+ | ((event: MouseEvent | KeyboardEvent, item: ZdpSegmentedControlItem) => void)
15
+ | null = null;
16
+
17
+ const fallbackIdPrefix = `zdp-segmented-control-${++nextSegmentedControlInstanceId}`;
18
+
19
+ $: selectedItem =
20
+ items.find((item) => item.id === selectedId && !item.disabled) ??
21
+ items.find((item) => !item.disabled) ??
22
+ items[0] ??
23
+ null;
24
+ $: activeId = selectedItem?.id ?? '';
25
+ $: resolvedIdPrefix = toDomId(idPrefix ?? fallbackIdPrefix);
26
+
27
+ function selectItem(event: MouseEvent | KeyboardEvent, item: ZdpSegmentedControlItem): void {
28
+ if (item.disabled) {
29
+ return;
30
+ }
31
+
32
+ const previousId = selectedId;
33
+ selectedId = item.id;
34
+
35
+ if (previousId !== item.id) {
36
+ onChange?.(event, item);
37
+ }
38
+ }
39
+
40
+ function handleKeydown(event: KeyboardEvent): void {
41
+ if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
42
+ return;
43
+ }
44
+
45
+ const target = event.currentTarget as HTMLElement;
46
+ const options = Array.from(target.querySelectorAll<HTMLButtonElement>('[role="radio"]:not(:disabled)'));
47
+
48
+ if (options.length === 0) {
49
+ return;
50
+ }
51
+
52
+ event.preventDefault();
53
+
54
+ const currentIndex = Math.max(
55
+ 0,
56
+ options.findIndex((option) => option.getAttribute('aria-checked') === 'true')
57
+ );
58
+ const nextIndex = getNextIndex(event.key, currentIndex, options.length);
59
+ const nextOption = options[nextIndex];
60
+
61
+ nextOption.focus();
62
+ nextOption.click();
63
+ }
64
+
65
+ function getNextIndex(key: string, currentIndex: number, length: number): number {
66
+ if (key === 'Home') {
67
+ return 0;
68
+ }
69
+
70
+ if (key === 'End') {
71
+ return length - 1;
72
+ }
73
+
74
+ if (key === 'ArrowLeft') {
75
+ return (currentIndex - 1 + length) % length;
76
+ }
77
+
78
+ return (currentIndex + 1) % length;
79
+ }
80
+
81
+ function itemId(id: string): string {
82
+ return `${resolvedIdPrefix}-item-${toDomId(id)}`;
83
+ }
84
+
85
+ function toDomId(value: string): string {
86
+ return value.trim().replace(/[^a-zA-Z0-9_-]+/g, '-') || 'item';
87
+ }
88
+ </script>
89
+
90
+ <div
91
+ class={`zdp-segmented-control zdp-segmented-control--${size}`}
92
+ role="radiogroup"
93
+ aria-label={ariaLabel}
94
+ tabindex="-1"
95
+ onkeydown={handleKeydown}
96
+ >
97
+ {#each items as item (item.id)}
98
+ <button
99
+ class={`zdp-segmented-control__item ${item.id === activeId ? 'zdp-segmented-control__item--selected' : ''}`}
100
+ id={itemId(item.id)}
101
+ type="button"
102
+ role="radio"
103
+ aria-label={item.ariaLabel ?? undefined}
104
+ aria-checked={item.id === activeId}
105
+ tabindex={item.id === activeId ? 0 : -1}
106
+ disabled={item.disabled}
107
+ onclick={(event) => selectItem(event, item)}
108
+ >
109
+ {item.label}
110
+ </button>
111
+ {/each}
112
+ </div>
113
+
114
+ <style>
115
+ .zdp-segmented-control {
116
+ align-items: center;
117
+ background: var(--zdp-color-surface-panel);
118
+ border: var(--zdp-control-border-width) solid var(--zdp-color-line-subtle);
119
+ border-radius: var(--zdp-control-radius);
120
+ box-sizing: border-box;
121
+ color: var(--zdp-color-ink-normal);
122
+ display: inline-flex;
123
+ flex-wrap: wrap;
124
+ font-family: var(--zdp-font-family-sans);
125
+ gap: var(--zdp-space-1);
126
+ max-width: 100%;
127
+ min-width: 0;
128
+ padding: var(--zdp-space-1);
129
+ }
130
+
131
+ .zdp-segmented-control__item {
132
+ align-items: center;
133
+ background: transparent;
134
+ border: var(--zdp-control-border-width) solid transparent;
135
+ border-radius: var(--zdp-control-radius);
136
+ box-sizing: border-box;
137
+ color: var(--zdp-color-ink-muted);
138
+ cursor: pointer;
139
+ display: inline-flex;
140
+ font-family: var(--zdp-font-family-sans);
141
+ font-weight: var(--zdp-font-weight-medium);
142
+ justify-content: center;
143
+ line-height: var(--zdp-type-control-line-height);
144
+ min-width: 0;
145
+ overflow-wrap: var(--zdp-i18n-overflow-wrap);
146
+ text-align: center;
147
+ transition:
148
+ background-color var(--zdp-motion-fast) ease,
149
+ border-color var(--zdp-motion-fast) ease,
150
+ color var(--zdp-motion-fast) ease;
151
+ -webkit-user-select: none;
152
+ user-select: none;
153
+ }
154
+
155
+ .zdp-segmented-control--sm .zdp-segmented-control__item {
156
+ font-size: var(--zdp-font-size-sm);
157
+ min-block-size: var(--zdp-control-height-sm);
158
+ padding: 0 var(--zdp-space-2);
159
+ }
160
+
161
+ .zdp-segmented-control--md .zdp-segmented-control__item {
162
+ font-size: var(--zdp-type-control-size);
163
+ min-block-size: var(--zdp-control-height-md);
164
+ padding: 0 var(--zdp-space-3);
165
+ }
166
+
167
+ .zdp-segmented-control__item:hover:not(:disabled):not([aria-checked='true']) {
168
+ background: var(--zdp-color-surface-raised);
169
+ border-color: var(--zdp-color-line-strong);
170
+ color: var(--zdp-color-ink-strong);
171
+ }
172
+
173
+ .zdp-segmented-control__item:focus-visible {
174
+ border-color: var(--zdp-color-focus-line);
175
+ outline: var(--zdp-control-focus-outline-width) solid var(--zdp-color-focus-surface);
176
+ outline-offset: var(--zdp-control-focus-outline-offset);
177
+ }
178
+
179
+ .zdp-segmented-control__item--selected,
180
+ .zdp-segmented-control__item[aria-checked='true'] {
181
+ background: var(--zdp-color-accent-primary-soft);
182
+ border-color: var(--zdp-color-accent-primary-strong);
183
+ color: var(--zdp-color-ink-strong);
184
+ }
185
+
186
+ .zdp-segmented-control__item:disabled {
187
+ cursor: not-allowed;
188
+ opacity: 0.56;
189
+ }
190
+ </style>
@@ -0,0 +1,88 @@
1
+ <script lang="ts">
2
+ type DescribedBy = string | readonly string[] | null;
3
+
4
+ export let id: string | null = null;
5
+ export let name: string | null = null;
6
+ export let value = '';
7
+ export let describedBy: DescribedBy = null;
8
+ export let errorMessageId: string | null = null;
9
+ export let invalid = false;
10
+ export let disabled = false;
11
+ export let required = false;
12
+
13
+ $: ariaDescribedBy = normalizeIdRefs(describedBy);
14
+ $: resolvedErrorMessageId = invalid && errorMessageId ? errorMessageId : null;
15
+
16
+ function handleChange(event: Event): void {
17
+ value = (event.currentTarget as HTMLSelectElement).value;
18
+ }
19
+
20
+ function normalizeIdRefs(value: DescribedBy): string | null {
21
+ if (value === null) {
22
+ return null;
23
+ }
24
+
25
+ if (typeof value === 'string') {
26
+ const normalized = value.trim();
27
+ return normalized ? normalized : null;
28
+ }
29
+
30
+ const normalized = value.map((entry) => entry.trim()).filter(Boolean);
31
+ return normalized.length > 0 ? normalized.join(' ') : null;
32
+ }
33
+ </script>
34
+
35
+ <select
36
+ class="zdp-select"
37
+ id={id ?? undefined}
38
+ name={name ?? undefined}
39
+ {value}
40
+ aria-describedby={ariaDescribedBy ?? undefined}
41
+ aria-errormessage={resolvedErrorMessageId ?? undefined}
42
+ aria-invalid={invalid ? 'true' : undefined}
43
+ {disabled}
44
+ {required}
45
+ onchange={handleChange}
46
+ >
47
+ <slot />
48
+ </select>
49
+
50
+ <style>
51
+ .zdp-select {
52
+ background: var(--zdp-color-surface-panel);
53
+ border: var(--zdp-control-border-width) solid var(--zdp-color-line-strong);
54
+ border-radius: var(--zdp-control-radius);
55
+ box-sizing: border-box;
56
+ color: var(--zdp-color-ink-strong);
57
+ font-family: var(--zdp-font-family-sans);
58
+ font-size: var(--zdp-type-control-size);
59
+ line-height: var(--zdp-type-control-line-height);
60
+ min-height: var(--zdp-control-height-md);
61
+ padding: 0 var(--zdp-space-3);
62
+ transition:
63
+ background-color var(--zdp-motion-fast) ease,
64
+ border-color var(--zdp-motion-fast) ease,
65
+ color var(--zdp-motion-fast) ease;
66
+ width: 100%;
67
+ }
68
+
69
+ .zdp-select:hover:not(:disabled) {
70
+ background: var(--zdp-color-surface-raised);
71
+ border-color: var(--zdp-color-line-strong);
72
+ }
73
+
74
+ .zdp-select:focus-visible {
75
+ border-color: var(--zdp-color-focus-line);
76
+ outline: var(--zdp-control-focus-outline-width) solid var(--zdp-color-focus-surface);
77
+ outline-offset: var(--zdp-control-focus-outline-offset);
78
+ }
79
+
80
+ .zdp-select[aria-invalid="true"] {
81
+ border-color: var(--zdp-color-accent-danger);
82
+ }
83
+
84
+ .zdp-select:disabled {
85
+ cursor: not-allowed;
86
+ opacity: 0.56;
87
+ }
88
+ </style>