@pgcorp/ui-kit 0.6.0 → 0.7.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/README.md +39 -0
- package/docs/public-api.md +6 -0
- package/package.json +5 -1
- package/src/components/shared/_internal/SToastItem.css +8 -8
- package/src/components/shared/_internal/SToastItem.vue +8 -1
- package/src/components/shared/controls/SButton.css +6 -6
- package/src/components/shared/controls/SButton.vue +9 -1
- package/src/components/shared/controls/SInteractiveSurface.css +3 -3
- package/src/components/shared/controls/SInteractiveSurface.vue +9 -2
- package/src/components/shared/controls/SMarker.css +16 -16
- package/src/components/shared/controls/SMarker.vue +27 -1
- package/src/components/shared/data-display/SActionListItem.css +2 -2
- package/src/components/shared/data-display/SActionListItem.vue +8 -1
- package/src/components/shared/data-display/SMessage.css +8 -8
- package/src/components/shared/data-display/SMessage.vue +8 -1
- package/src/components/shared/data-display/SProgressBar.css +12 -12
- package/src/components/shared/data-display/SProgressBar.vue +12 -6
- package/src/components/shared/data-display/SProgressIndicator.css +5 -5
- package/src/components/shared/data-display/SProgressIndicator.vue +9 -1
- package/src/components/shared/data-display/SStatus.css +10 -10
- package/src/components/shared/data-display/SStatus.vue +9 -1
- package/src/components/shared/data-display/STable.vue +27 -4
- package/src/components/shared/data-display/STooltip.css +4 -4
- package/src/components/shared/data-display/STooltip.vue +159 -29
- package/src/components/shared/data-display/STooltipTarget.css +26 -0
- package/src/components/shared/data-display/STooltipTarget.vue +94 -0
- package/src/components/shared/navigation/STabs.vue +11 -3
- package/src/internal/ownedAttrs.ts +3 -0
- package/src/internal/pillSurface.ts +4 -3
- package/src/internal/semanticTone.ts +23 -0
- package/src/styles/style.css +7 -7
package/README.md
CHANGED
|
@@ -159,6 +159,16 @@ Multi-column sorting uses controlled `v-model:sorts`: the consumer sets
|
|
|
159
159
|
adds a descriptor, changes its direction, or removes it; the visible number is
|
|
160
160
|
the priority. The table never reorders rows on its own.
|
|
161
161
|
|
|
162
|
+
Последовательные действия заголовков формируют внутренний intent draft до
|
|
163
|
+
подтверждения controlled prop. Consumer может применить `sort`/`sorts` через
|
|
164
|
+
store или асинхронный render-cycle: второй критерий не теряет первый. Любое
|
|
165
|
+
authoritative обновление prop становится новой базой следующих действий.
|
|
166
|
+
|
|
167
|
+
Sequential header actions update an internal intent draft until the controlled
|
|
168
|
+
prop is acknowledged. Consumers may apply `sort` or `sorts` through a store or
|
|
169
|
+
an asynchronous render cycle without losing an earlier criterion. Any
|
|
170
|
+
authoritative prop update becomes the base for subsequent actions.
|
|
171
|
+
|
|
162
172
|
```vue
|
|
163
173
|
<STable
|
|
164
174
|
v-model:sorts="sorts"
|
|
@@ -170,6 +180,31 @@ the priority. The table never reorders rows on its own.
|
|
|
170
180
|
/>
|
|
171
181
|
```
|
|
172
182
|
|
|
183
|
+
### Подсказка на части действия / Tooltip for part of an action
|
|
184
|
+
|
|
185
|
+
Обычный tooltip использует combined `trigger`. Для пассивного фрагмента внутри
|
|
186
|
+
уже интерактивного leaf используйте split bindings: `focusOwner` остаётся на
|
|
187
|
+
кнопке и владеет ARIA/focus, а `pointerTarget` получает пассивный
|
|
188
|
+
`STooltipTarget`. Компонент target не создаёт `role` или `tabindex`.
|
|
189
|
+
|
|
190
|
+
A regular tooltip uses the combined `trigger`. For a passive fragment inside an
|
|
191
|
+
existing interactive leaf, use split bindings: `focusOwner` remains on the
|
|
192
|
+
button and owns ARIA/focus, while `pointerTarget` is applied to a passive
|
|
193
|
+
`STooltipTarget`. The target component adds neither a role nor a tab stop.
|
|
194
|
+
|
|
195
|
+
```vue
|
|
196
|
+
<STooltip text="Открывает палитру команд" v-slot="{ focusOwner, pointerTarget }">
|
|
197
|
+
<SButton v-bind="focusOwner" width="full" content-align="between">
|
|
198
|
+
Открыть палитру команд
|
|
199
|
+
<STooltipTarget
|
|
200
|
+
v-bind="pointerTarget"
|
|
201
|
+
as="kbd"
|
|
202
|
+
appearance="keycap"
|
|
203
|
+
>⌘K</STooltipTarget>
|
|
204
|
+
</SButton>
|
|
205
|
+
</STooltip>
|
|
206
|
+
```
|
|
207
|
+
|
|
173
208
|
## Темы и стили / Themes and styles
|
|
174
209
|
|
|
175
210
|
Для обычного приложения подключайте полный style entrypoint один раз:
|
|
@@ -244,6 +279,10 @@ import { themeVariants } from '@pgcorp/ui-kit/theme'
|
|
|
244
279
|
Do not style internal DOM through `:deep` or private selectors.
|
|
245
280
|
- Выражайте состояние через documented props, slots, variants и tokens.
|
|
246
281
|
Express state through documented props, slots, variants, and tokens.
|
|
282
|
+
- Используйте собственные `data-*` как test/tour hooks; UI-kit-owned `data-s-*`
|
|
283
|
+
являются внутренней presentation boundary и не являются selector API.
|
|
284
|
+
Use consumer-owned `data-*` for test and tour hooks; UI-kit-owned `data-s-*`
|
|
285
|
+
are an internal presentation boundary, not a selector API.
|
|
247
286
|
- Передавайте человекочитаемые labels интерактивным компонентам.
|
|
248
287
|
Provide human-readable labels to interactive components.
|
|
249
288
|
|
package/docs/public-api.md
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
|
|
19
19
|
Компонентный contract выражается через typed props, slots, events и exposed
|
|
20
20
|
methods. Внутренний DOM, CSS-классы и private modules не являются API.
|
|
21
|
+
UI-kit-owned атрибуты `data-s-*` относятся к внутренней presentation boundary и
|
|
22
|
+
не являются стабильными consumer selectors. Произвольные consumer-owned
|
|
23
|
+
`data-*` остаются поддерживаемыми test/tour hooks canonical owner.
|
|
21
24
|
Публичные source-SFC объявляют runtime props и events локально: consumer Vue
|
|
22
25
|
compiler регистрирует их без межфайлового filesystem type resolver.
|
|
23
26
|
Публикуемый production-source компилируется с `target/lib: ES2020`, совпадающим
|
|
@@ -41,6 +44,9 @@ Primary groups:
|
|
|
41
44
|
|
|
42
45
|
Component contracts are expressed through typed props, slots, events, and exposed
|
|
43
46
|
methods. Internal DOM, CSS classes, and private modules are not API.
|
|
47
|
+
UI-kit-owned `data-s-*` attributes belong to the internal presentation boundary
|
|
48
|
+
and are not stable consumer selectors. Arbitrary consumer-owned `data-*`
|
|
49
|
+
attributes remain supported test and tour hooks on the canonical owner.
|
|
44
50
|
Public source SFCs declare runtime props and events locally, so the consumer Vue
|
|
45
51
|
compiler registers them without a cross-file filesystem type resolver.
|
|
46
52
|
Published production source compiles with the `target/lib: ES2020` baseline from
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgcorp/ui-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Typed Vue 3 design system with accessible components, semantic themes, and workbench patterns.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.ts",
|
|
@@ -348,6 +348,9 @@
|
|
|
348
348
|
"shared/data-display/STooltipAnchor.vue": [
|
|
349
349
|
"src/components/shared/data-display/STooltipAnchor.vue"
|
|
350
350
|
],
|
|
351
|
+
"shared/data-display/STooltipTarget.vue": [
|
|
352
|
+
"src/components/shared/data-display/STooltipTarget.vue"
|
|
353
|
+
],
|
|
351
354
|
"shared/data-display/SVirtualList": [
|
|
352
355
|
"src/components/shared/data-display/SVirtualList.ts"
|
|
353
356
|
],
|
|
@@ -524,6 +527,7 @@
|
|
|
524
527
|
"./shared/data-display/SToastContainer.vue": "./src/components/shared/data-display/SToastContainer.vue",
|
|
525
528
|
"./shared/data-display/STooltip.vue": "./src/components/shared/data-display/STooltip.vue",
|
|
526
529
|
"./shared/data-display/STooltipAnchor.vue": "./src/components/shared/data-display/STooltipAnchor.vue",
|
|
530
|
+
"./shared/data-display/STooltipTarget.vue": "./src/components/shared/data-display/STooltipTarget.vue",
|
|
527
531
|
"./shared/data-display/SVirtualList": "./src/components/shared/data-display/SVirtualList.ts",
|
|
528
532
|
"./shared/data-display/SVirtualList.vue": "./src/components/shared/data-display/SVirtualList.vue",
|
|
529
533
|
"./shared/database/SDataGrid.vue": "./src/components/shared/database/SDataGrid.vue",
|
|
@@ -33,33 +33,33 @@
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/* Severity: info */
|
|
36
|
-
.s-toast[data-
|
|
36
|
+
.s-toast[data-s-tone='info'] {
|
|
37
37
|
box-shadow: var(--s-toast-shadow-info);
|
|
38
38
|
}
|
|
39
|
-
.s-toast[data-
|
|
39
|
+
.s-toast[data-s-tone='info'] .s-toast-icon {
|
|
40
40
|
@apply text-info-500;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/* Severity: success */
|
|
44
|
-
.s-toast[data-
|
|
44
|
+
.s-toast[data-s-tone='success'] {
|
|
45
45
|
box-shadow: var(--s-toast-shadow-success);
|
|
46
46
|
}
|
|
47
|
-
.s-toast[data-
|
|
47
|
+
.s-toast[data-s-tone='success'] .s-toast-icon {
|
|
48
48
|
@apply text-success-500;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/* Severity: warn */
|
|
52
|
-
.s-toast[data-
|
|
52
|
+
.s-toast[data-s-tone='warn'] {
|
|
53
53
|
box-shadow: var(--s-toast-shadow-warn);
|
|
54
54
|
}
|
|
55
|
-
.s-toast[data-
|
|
55
|
+
.s-toast[data-s-tone='warn'] .s-toast-icon {
|
|
56
56
|
@apply text-warn-500;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/* Severity: danger */
|
|
60
|
-
.s-toast[data-
|
|
60
|
+
.s-toast[data-s-tone='danger'] {
|
|
61
61
|
box-shadow: var(--s-toast-shadow-danger);
|
|
62
62
|
}
|
|
63
|
-
.s-toast[data-
|
|
63
|
+
.s-toast[data-s-tone='danger'] .s-toast-icon {
|
|
64
64
|
@apply text-danger-500;
|
|
65
65
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
3
4
|
class="s-toast"
|
|
4
|
-
:data-severity="notification.severity"
|
|
5
5
|
:role="liveAttributes.role"
|
|
6
6
|
:aria-live="liveAttributes.ariaLive"
|
|
7
7
|
:aria-atomic="liveAttributes.ariaAtomic"
|
|
@@ -40,6 +40,7 @@ import { computed } from 'vue'
|
|
|
40
40
|
|
|
41
41
|
import { X } from '../../icons/sputnigUiIcons'
|
|
42
42
|
import { resolveFeedbackLive, resolveFeedbackPresentation } from '../../../internal/feedbackPresentation'
|
|
43
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
43
44
|
import type { Notification } from '../../../stores/useNotifierStore';
|
|
44
45
|
import SButton from '../controls/SButton.vue'
|
|
45
46
|
|
|
@@ -53,6 +54,12 @@ const emit = defineEmits<{
|
|
|
53
54
|
dismiss: [id: string]
|
|
54
55
|
}>()
|
|
55
56
|
const presentation = computed(() => resolveFeedbackPresentation(props.notification.severity))
|
|
57
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
58
|
+
'SToastItem',
|
|
59
|
+
'notification.severity',
|
|
60
|
+
props.notification.severity,
|
|
61
|
+
['info', 'success', 'warn', 'danger'] as const,
|
|
62
|
+
))
|
|
56
63
|
const liveAttributes = computed(() => resolveFeedbackLive(props.notification.severity, 'auto'))
|
|
57
64
|
</script>
|
|
58
65
|
<style lang="postcss" src="./SToastItem.css" scoped></style>
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
.s-button[data-icon-only='true'][data-size='md'] { width: var(--s-control-hitbox-md); height: var(--s-control-hitbox-md); }
|
|
79
79
|
.s-button[data-icon-only='true'][data-size='lg'] { width: var(--s-control-hitbox-lg); height: var(--s-control-hitbox-lg); }
|
|
80
80
|
|
|
81
|
-
.s-button[data-
|
|
81
|
+
.s-button[data-s-tone='secondary'] {
|
|
82
82
|
--s-button-accent: var(--s-button-secondary-accent);
|
|
83
83
|
--s-button-solid-background: var(--s-button-secondary-solid-background);
|
|
84
84
|
--s-button-solid-background-hover: var(--s-button-secondary-solid-background-hover);
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
--s-button-outline: var(--color-surface-300);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
.s-button[data-
|
|
91
|
+
.s-button[data-s-tone='success'] {
|
|
92
92
|
--s-button-accent: var(--s-button-success-accent);
|
|
93
93
|
--s-button-solid-background: var(--s-button-success-solid-background);
|
|
94
94
|
--s-button-solid-background-hover: var(--s-button-success-solid-background-hover);
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
--s-button-foreground: var(--s-button-success-foreground);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
.s-button[data-
|
|
100
|
+
.s-button[data-s-tone='info'] {
|
|
101
101
|
--s-button-accent: var(--s-button-info-accent);
|
|
102
102
|
--s-button-solid-background: var(--s-button-info-solid-background);
|
|
103
103
|
--s-button-solid-background-hover: var(--s-button-info-solid-background-hover);
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
--s-button-foreground: var(--s-button-info-foreground);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
.s-button[data-
|
|
109
|
+
.s-button[data-s-tone='warn'] {
|
|
110
110
|
--s-button-accent: var(--s-button-warn-accent);
|
|
111
111
|
--s-button-solid-background: var(--s-button-warn-solid-background);
|
|
112
112
|
--s-button-solid-background-hover: var(--s-button-warn-solid-background-hover);
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
--s-button-foreground: var(--s-button-warn-foreground);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
.s-button[data-
|
|
118
|
+
.s-button[data-s-tone='danger'] {
|
|
119
119
|
--s-button-accent: var(--s-button-danger-accent);
|
|
120
120
|
--s-button-solid-background: var(--s-button-danger-solid-background);
|
|
121
121
|
--s-button-solid-background-hover: var(--s-button-danger-solid-background-hover);
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
--s-button-foreground: var(--s-button-danger-foreground);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
.s-button[data-
|
|
127
|
+
.s-button[data-s-tone='contrast'] {
|
|
128
128
|
--s-button-accent: var(--s-button-contrast-accent);
|
|
129
129
|
--s-button-solid-background: var(--s-button-contrast-solid-background);
|
|
130
130
|
--s-button-solid-background-hover: var(--s-button-contrast-solid-background-hover);
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
:is="rootComponent"
|
|
4
4
|
:ref="setRootRef"
|
|
5
5
|
v-bind="rootBindings"
|
|
6
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
6
7
|
class="s-button"
|
|
7
|
-
:data-severity="severity"
|
|
8
8
|
:data-size="size"
|
|
9
9
|
:data-width="width"
|
|
10
10
|
:data-content-align="contentAlign"
|
|
@@ -63,6 +63,7 @@ import { ChevronRight } from '../../icons/sputnigUiIcons'
|
|
|
63
63
|
import type { InteractiveElementApi } from '../../../internal/interactiveElement'
|
|
64
64
|
import { resolveLinkTarget } from '../../../internal/linkTarget'
|
|
65
65
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
66
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
66
67
|
import {
|
|
67
68
|
PassiveContentBoundary,
|
|
68
69
|
useInteractiveLeafRegistration,
|
|
@@ -79,6 +80,7 @@ import type {
|
|
|
79
80
|
defineOptions({ inheritAttrs: false })
|
|
80
81
|
|
|
81
82
|
export type SButtonSeverity = 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'contrast'
|
|
83
|
+
const BUTTON_SEVERITIES = ['primary', 'secondary', 'success', 'info', 'warn', 'danger', 'contrast'] as const satisfies readonly SButtonSeverity[]
|
|
82
84
|
export type SButtonSize = 'xs' | 'sm' | 'md' | 'lg'
|
|
83
85
|
export type SButtonIconSize = 'default' | 'large'
|
|
84
86
|
export type SButtonDensity = 'default' | 'compact'
|
|
@@ -186,6 +188,12 @@ const defaultContentComponent = (): ReturnType<NonNullable<typeof buttonSlots.de
|
|
|
186
188
|
)
|
|
187
189
|
const rootRef = ref<HTMLButtonElement | HTMLAnchorElement | null>(null)
|
|
188
190
|
const ownedAttrs = useOwnedAttrs({ component: 'SButton', owner: 'native button' })
|
|
191
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
192
|
+
'SButton',
|
|
193
|
+
'severity',
|
|
194
|
+
props.severity,
|
|
195
|
+
BUTTON_SEVERITIES,
|
|
196
|
+
))
|
|
189
197
|
const isRegisteredTreeAction = useTreeActionRegistration({
|
|
190
198
|
owner: 'SButton',
|
|
191
199
|
element: rootRef,
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
.s-interactive-surface[data-radius='md'] { @apply rounded-md; }
|
|
52
52
|
.s-interactive-surface[data-radius='lg'] { @apply rounded-lg; }
|
|
53
53
|
.s-interactive-surface[data-radius='xl'] { @apply rounded-xl; }
|
|
54
|
-
.s-interactive-surface[data-tone='primary'] { @apply border-primary-200 bg-primary-500/5 dark:border-primary-500/30 dark:bg-primary-500/10; }
|
|
55
|
-
.s-interactive-surface[data-tone='success'] { @apply border-success-200 bg-success-50 dark:border-success-800 dark:bg-success-950; }
|
|
56
|
-
.s-interactive-surface[data-tone='danger'] { @apply border-danger-200 bg-danger-50 dark:border-danger-800 dark:bg-danger-950; }
|
|
54
|
+
.s-interactive-surface[data-s-tone='primary'] { @apply border-primary-200 bg-primary-500/5 dark:border-primary-500/30 dark:bg-primary-500/10; }
|
|
55
|
+
.s-interactive-surface[data-s-tone='success'] { @apply border-success-200 bg-success-50 dark:border-success-800 dark:bg-success-950; }
|
|
56
|
+
.s-interactive-surface[data-s-tone='danger'] { @apply border-danger-200 bg-danger-50 dark:border-danger-800 dark:bg-danger-950; }
|
|
57
57
|
.s-interactive-surface[data-selected='true'] { @apply border-primary-400 bg-primary-50 dark:border-primary-600 dark:bg-primary-950; }
|
|
58
58
|
.s-interactive-surface[data-pressed='true'] { @apply border-primary-500 bg-primary-100 dark:border-primary-500 dark:bg-primary-950/70; }
|
|
59
59
|
.s-interactive-surface[data-disabled='true'] { @apply cursor-not-allowed opacity-60; }
|
|
@@ -5,6 +5,7 @@ import type { STooltipTriggerBinding } from '../data-display/STooltip.vue'
|
|
|
5
5
|
import { hasOwn } from '../../../internal/es2020'
|
|
6
6
|
import { resolveLinkTarget } from '../../../internal/linkTarget'
|
|
7
7
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
8
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
8
9
|
import {
|
|
9
10
|
PassiveContentBoundary,
|
|
10
11
|
useInteractiveLeafRegistration,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
defineOptions({ inheritAttrs: false })
|
|
15
16
|
|
|
16
17
|
export type InteractiveSurfaceTone = 'default' | 'primary' | 'success' | 'danger'
|
|
18
|
+
const INTERACTIVE_SURFACE_TONES = ['default', 'primary', 'success', 'danger'] as const satisfies readonly InteractiveSurfaceTone[]
|
|
17
19
|
export type InteractiveSurfaceDensity = 'compact' | 'comfortable'
|
|
18
20
|
export type InteractiveSurfacePadding = 'none' | 'sm' | 'md'
|
|
19
21
|
export type InteractiveSurfaceRadius = 'md' | 'lg' | 'xl'
|
|
@@ -84,6 +86,12 @@ defineSlots<{
|
|
|
84
86
|
}>()
|
|
85
87
|
|
|
86
88
|
const ownedAttrs = useOwnedAttrs({ component: 'SInteractiveSurface', owner: 'interactive surface owner' })
|
|
89
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
90
|
+
'SInteractiveSurface',
|
|
91
|
+
'tone',
|
|
92
|
+
props.tone,
|
|
93
|
+
INTERACTIVE_SURFACE_TONES,
|
|
94
|
+
))
|
|
87
95
|
|
|
88
96
|
const assertOptionalBoolean = (surface: Record<string, unknown>, field: 'disabled' | 'pressed'): void => {
|
|
89
97
|
if (surface[field] !== undefined && typeof surface[field] !== 'boolean') {
|
|
@@ -213,7 +221,6 @@ const validatedTooltipTrigger = computed<STooltipTriggerBinding | undefined>(()
|
|
|
213
221
|
}
|
|
214
222
|
return candidate as STooltipTriggerBinding
|
|
215
223
|
})
|
|
216
|
-
|
|
217
224
|
const activationBindings = (): Readonly<Record<string, unknown>> => ({
|
|
218
225
|
...ownedAttrs.bindings(),
|
|
219
226
|
...(validatedTooltipTrigger.value ?? {}),
|
|
@@ -282,9 +289,9 @@ function activateAction(event: MouseEvent): void {
|
|
|
282
289
|
<template>
|
|
283
290
|
<div
|
|
284
291
|
v-bind="surfaceMode === 'static' ? ownedAttrs.bindings() : undefined"
|
|
292
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
285
293
|
class="s-interactive-surface"
|
|
286
294
|
:data-mode="surfaceMode"
|
|
287
|
-
:data-tone="tone"
|
|
288
295
|
:data-density="density"
|
|
289
296
|
:data-padding="padding"
|
|
290
297
|
:data-radius="radius"
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
@reference "../../../styles/reference.css";
|
|
2
2
|
.s-marker { @apply inline-block h-2 w-2 shrink-0 rounded-full bg-surface-400 ring-1 ring-inset ring-surface-500/50; }
|
|
3
3
|
.s-marker[data-size='lg'] { @apply h-7 w-7 ring-2 ring-white/80 shadow-sm dark:ring-surface-950/80; }
|
|
4
|
-
.s-marker[data-tone='primary'] { @apply bg-primary-500 ring-primary-600/50; }
|
|
5
|
-
.s-marker[data-tone='success'] { @apply bg-success-500 ring-success-600/50; }
|
|
6
|
-
.s-marker[data-tone='blue'] { @apply bg-blue-400 ring-blue-500/50; }
|
|
7
|
-
.s-marker[data-tone='sky'] { @apply bg-sky-400 ring-sky-500/50; }
|
|
8
|
-
.s-marker[data-tone='indigo'] { @apply bg-indigo-400 ring-indigo-500/50; }
|
|
9
|
-
.s-marker[data-tone='emerald'] { @apply bg-emerald-400 ring-emerald-500/50; }
|
|
10
|
-
.s-marker[data-tone='green'] { @apply bg-green-400 ring-green-500/50; }
|
|
11
|
-
.s-marker[data-tone='teal'] { @apply bg-teal-400 ring-teal-500/50; }
|
|
12
|
-
.s-marker[data-tone='amber'] { @apply bg-amber-400 ring-amber-500/50; }
|
|
13
|
-
.s-marker[data-tone='orange'] { @apply bg-orange-400 ring-orange-500/50; }
|
|
14
|
-
.s-marker[data-tone='rose'] { @apply bg-rose-400 ring-rose-500/50; }
|
|
15
|
-
.s-marker[data-tone='pink'] { @apply bg-pink-400 ring-pink-500/50; }
|
|
16
|
-
.s-marker[data-tone='fuchsia'] { @apply bg-fuchsia-400 ring-fuchsia-500/50; }
|
|
17
|
-
.s-marker[data-tone='cyan'] { @apply bg-cyan-400 ring-cyan-500/50; }
|
|
18
|
-
.s-marker[data-tone='lime'] { @apply bg-lime-400 ring-lime-500/50; }
|
|
19
|
-
.s-marker[data-tone='custom'] { background-color: var(--s-marker-custom-color); --tw-ring-color: var(--s-marker-custom-color); }
|
|
4
|
+
.s-marker[data-s-tone='primary'] { @apply bg-primary-500 ring-primary-600/50; }
|
|
5
|
+
.s-marker[data-s-tone='success'] { @apply bg-success-500 ring-success-600/50; }
|
|
6
|
+
.s-marker[data-s-tone='blue'] { @apply bg-blue-400 ring-blue-500/50; }
|
|
7
|
+
.s-marker[data-s-tone='sky'] { @apply bg-sky-400 ring-sky-500/50; }
|
|
8
|
+
.s-marker[data-s-tone='indigo'] { @apply bg-indigo-400 ring-indigo-500/50; }
|
|
9
|
+
.s-marker[data-s-tone='emerald'] { @apply bg-emerald-400 ring-emerald-500/50; }
|
|
10
|
+
.s-marker[data-s-tone='green'] { @apply bg-green-400 ring-green-500/50; }
|
|
11
|
+
.s-marker[data-s-tone='teal'] { @apply bg-teal-400 ring-teal-500/50; }
|
|
12
|
+
.s-marker[data-s-tone='amber'] { @apply bg-amber-400 ring-amber-500/50; }
|
|
13
|
+
.s-marker[data-s-tone='orange'] { @apply bg-orange-400 ring-orange-500/50; }
|
|
14
|
+
.s-marker[data-s-tone='rose'] { @apply bg-rose-400 ring-rose-500/50; }
|
|
15
|
+
.s-marker[data-s-tone='pink'] { @apply bg-pink-400 ring-pink-500/50; }
|
|
16
|
+
.s-marker[data-s-tone='fuchsia'] { @apply bg-fuchsia-400 ring-fuchsia-500/50; }
|
|
17
|
+
.s-marker[data-s-tone='cyan'] { @apply bg-cyan-400 ring-cyan-500/50; }
|
|
18
|
+
.s-marker[data-s-tone='lime'] { @apply bg-lime-400 ring-lime-500/50; }
|
|
19
|
+
.s-marker[data-s-tone='custom'] { background-color: var(--s-marker-custom-color); --tw-ring-color: var(--s-marker-custom-color); }
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span
|
|
3
3
|
v-bind="ownedAttrs.bindings()"
|
|
4
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
4
5
|
class="s-marker"
|
|
5
|
-
:data-tone="marker.tone"
|
|
6
6
|
:data-size="size"
|
|
7
7
|
:style="customProperties"
|
|
8
8
|
aria-hidden="true"
|
|
@@ -17,12 +17,38 @@ export type { SCustomMarker, SMarker, SMarkerTone } from '../_internal/markerCon
|
|
|
17
17
|
<script setup lang="ts">
|
|
18
18
|
import { computed } from 'vue'
|
|
19
19
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
20
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
20
21
|
import { createCustomMarker, type SMarker } from '../_internal/markerContract'
|
|
21
22
|
|
|
22
23
|
defineOptions({ inheritAttrs: false })
|
|
23
24
|
|
|
24
25
|
const props = withDefaults(defineProps<{ marker: SMarker; size?: 'sm' | 'lg' }>(), { size: 'sm' })
|
|
25
26
|
const ownedAttrs = useOwnedAttrs({ component: 'SMarker', owner: 'marker root' })
|
|
27
|
+
const MARKER_TONES = [
|
|
28
|
+
'surface',
|
|
29
|
+
'primary',
|
|
30
|
+
'success',
|
|
31
|
+
'blue',
|
|
32
|
+
'sky',
|
|
33
|
+
'indigo',
|
|
34
|
+
'emerald',
|
|
35
|
+
'green',
|
|
36
|
+
'teal',
|
|
37
|
+
'amber',
|
|
38
|
+
'orange',
|
|
39
|
+
'rose',
|
|
40
|
+
'pink',
|
|
41
|
+
'fuchsia',
|
|
42
|
+
'cyan',
|
|
43
|
+
'lime',
|
|
44
|
+
'custom',
|
|
45
|
+
] as const
|
|
46
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
47
|
+
'SMarker',
|
|
48
|
+
'marker.tone',
|
|
49
|
+
props.marker.tone,
|
|
50
|
+
MARKER_TONES,
|
|
51
|
+
))
|
|
26
52
|
const customProperties = computed(() => {
|
|
27
53
|
if (props.marker.tone !== 'custom') return undefined
|
|
28
54
|
createCustomMarker(props.marker.color)
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
@apply dark:bg-primary-900 dark:text-primary-200;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
.s-action-list-item[data-tone='success'] .s-action-list-item__icon {
|
|
31
|
+
.s-action-list-item[data-s-tone='success'] .s-action-list-item__icon {
|
|
32
32
|
@apply bg-success-100 text-success-700 dark:bg-success-900 dark:text-success-200;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
.s-action-list-item[data-tone='danger'] .s-action-list-item__icon {
|
|
35
|
+
.s-action-list-item[data-s-tone='danger'] .s-action-list-item__icon {
|
|
36
36
|
@apply bg-danger-100 text-danger-700 dark:bg-danger-900 dark:text-danger-200;
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import type { Component, VNodeChild } from 'vue'
|
|
4
4
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
5
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
5
6
|
import { validateBoundedInteger, validateNonEmptyString } from '../../../internal/runtimeContract'
|
|
6
7
|
|
|
7
8
|
import SButton from '../controls/SButton.vue'
|
|
@@ -102,6 +103,12 @@ const itemStyle = computed(() => ({
|
|
|
102
103
|
'--s-action-list-item-indent': `${validatedIndentLevel.value * 0.875}rem`,
|
|
103
104
|
}))
|
|
104
105
|
const ownedAttrs = useOwnedAttrs({ component: 'SActionListItem', owner: 'action list item root' })
|
|
106
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
107
|
+
'SActionListItem',
|
|
108
|
+
'tone',
|
|
109
|
+
props.tone,
|
|
110
|
+
['default', 'primary', 'success', 'danger'] as const,
|
|
111
|
+
))
|
|
105
112
|
const rootBindings = computed(() => ownedAttrs.bindings())
|
|
106
113
|
const semanticRole = computed(() => {
|
|
107
114
|
const declaredRole = rootBindings.value.role
|
|
@@ -163,9 +170,9 @@ function emitAction(event: MouseEvent): void {
|
|
|
163
170
|
<template>
|
|
164
171
|
<div
|
|
165
172
|
v-bind="rootBindings"
|
|
173
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
166
174
|
class="s-action-list-item"
|
|
167
175
|
:data-selected="selected"
|
|
168
|
-
:data-tone="tone"
|
|
169
176
|
:data-density="density"
|
|
170
177
|
:data-interactive="resolvedMode !== 'static'"
|
|
171
178
|
:data-mode="resolvedMode"
|
|
@@ -52,37 +52,37 @@
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/* Severity: info */
|
|
55
|
-
.s-message[data-
|
|
55
|
+
.s-message[data-s-tone='info'] {
|
|
56
56
|
@apply bg-info-50 border-info-200 text-info-800;
|
|
57
57
|
@apply dark:bg-info-950 dark:border-info-800 dark:text-info-200;
|
|
58
58
|
}
|
|
59
|
-
.s-message[data-
|
|
59
|
+
.s-message[data-s-tone='info'] .s-message-icon {
|
|
60
60
|
@apply text-info-500 dark:text-info-400;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/* Severity: success */
|
|
64
|
-
.s-message[data-
|
|
64
|
+
.s-message[data-s-tone='success'] {
|
|
65
65
|
@apply bg-success-50 border-success-200 text-success-800;
|
|
66
66
|
@apply dark:bg-success-950 dark:border-success-800 dark:text-success-200;
|
|
67
67
|
}
|
|
68
|
-
.s-message[data-
|
|
68
|
+
.s-message[data-s-tone='success'] .s-message-icon {
|
|
69
69
|
@apply text-success-500 dark:text-success-400;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/* Severity: warn */
|
|
73
|
-
.s-message[data-
|
|
73
|
+
.s-message[data-s-tone='warn'] {
|
|
74
74
|
@apply bg-warn-50 border-warn-200 text-warn-800;
|
|
75
75
|
@apply dark:bg-warn-950 dark:border-warn-800 dark:text-warn-200;
|
|
76
76
|
}
|
|
77
|
-
.s-message[data-
|
|
77
|
+
.s-message[data-s-tone='warn'] .s-message-icon {
|
|
78
78
|
@apply text-warn-500 dark:text-warn-400;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/* Severity: danger */
|
|
82
|
-
.s-message[data-
|
|
82
|
+
.s-message[data-s-tone='danger'] {
|
|
83
83
|
@apply bg-danger-50 border-danger-200 text-danger-800;
|
|
84
84
|
@apply dark:bg-danger-950 dark:border-danger-800 dark:text-danger-200;
|
|
85
85
|
}
|
|
86
|
-
.s-message[data-
|
|
86
|
+
.s-message[data-s-tone='danger'] .s-message-icon {
|
|
87
87
|
@apply text-danger-500 dark:text-danger-400;
|
|
88
88
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
v-bind="ownedAttrs.bindings()"
|
|
4
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
4
5
|
class="s-message"
|
|
5
|
-
:data-severity="validatedSeverity"
|
|
6
6
|
:data-size="validatedSize"
|
|
7
7
|
:role="liveAttributes.role"
|
|
8
8
|
:aria-live="liveAttributes.ariaLive"
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
import { computed } from 'vue'
|
|
44
44
|
import { X } from '../../icons/sputnigUiIcons'
|
|
45
45
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
46
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
46
47
|
import {
|
|
47
48
|
resolveFeedbackLive,
|
|
48
49
|
resolveFeedbackPresentation,
|
|
@@ -112,6 +113,12 @@ const validatedSeverity = computed<Severity>(() => validateExactString(
|
|
|
112
113
|
props.severity,
|
|
113
114
|
MESSAGE_SEVERITIES,
|
|
114
115
|
))
|
|
116
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
117
|
+
'SMessage',
|
|
118
|
+
'severity',
|
|
119
|
+
validatedSeverity.value,
|
|
120
|
+
MESSAGE_SEVERITIES,
|
|
121
|
+
))
|
|
115
122
|
const validatedLive = computed<FeedbackLiveMode>(() => validateExactString(
|
|
116
123
|
'SMessage',
|
|
117
124
|
'live',
|
|
@@ -22,22 +22,22 @@
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/* Severity Colors */
|
|
25
|
-
.s-progress-bar-value[data-
|
|
25
|
+
.s-progress-bar-value[data-s-tone='primary'] {
|
|
26
26
|
background-color: var(--s-progress-bar-fill-primary);
|
|
27
27
|
}
|
|
28
|
-
.s-progress-bar-value[data-
|
|
28
|
+
.s-progress-bar-value[data-s-tone='success'] {
|
|
29
29
|
background-color: var(--s-progress-bar-fill-success);
|
|
30
30
|
}
|
|
31
|
-
.s-progress-bar-value[data-
|
|
31
|
+
.s-progress-bar-value[data-s-tone='info'] {
|
|
32
32
|
background-color: var(--s-progress-bar-fill-info);
|
|
33
33
|
}
|
|
34
|
-
.s-progress-bar-value[data-
|
|
34
|
+
.s-progress-bar-value[data-s-tone='warn'] {
|
|
35
35
|
background-color: var(--s-progress-bar-fill-warn);
|
|
36
36
|
}
|
|
37
|
-
.s-progress-bar-value[data-
|
|
37
|
+
.s-progress-bar-value[data-s-tone='danger'] {
|
|
38
38
|
background-color: var(--s-progress-bar-fill-danger);
|
|
39
39
|
}
|
|
40
|
-
.s-progress-bar-value[data-
|
|
40
|
+
.s-progress-bar-value[data-s-tone='neutral'] {
|
|
41
41
|
background-color: var(--s-progress-bar-fill-neutral);
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -64,21 +64,21 @@
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/* Indeterminate Severity Colors */
|
|
67
|
-
.s-progress-bar-value--indeterminate[data-
|
|
67
|
+
.s-progress-bar-value--indeterminate[data-s-tone='primary']::before {
|
|
68
68
|
background-color: var(--s-progress-bar-fill-primary);
|
|
69
69
|
}
|
|
70
|
-
.s-progress-bar-value--indeterminate[data-
|
|
70
|
+
.s-progress-bar-value--indeterminate[data-s-tone='success']::before {
|
|
71
71
|
background-color: var(--s-progress-bar-fill-success);
|
|
72
72
|
}
|
|
73
|
-
.s-progress-bar-value--indeterminate[data-
|
|
73
|
+
.s-progress-bar-value--indeterminate[data-s-tone='info']::before {
|
|
74
74
|
background-color: var(--s-progress-bar-fill-info);
|
|
75
75
|
}
|
|
76
|
-
.s-progress-bar-value--indeterminate[data-
|
|
76
|
+
.s-progress-bar-value--indeterminate[data-s-tone='warn']::before {
|
|
77
77
|
background-color: var(--s-progress-bar-fill-warn);
|
|
78
78
|
}
|
|
79
|
-
.s-progress-bar-value--indeterminate[data-
|
|
79
|
+
.s-progress-bar-value--indeterminate[data-s-tone='danger']::before {
|
|
80
80
|
background-color: var(--s-progress-bar-fill-danger);
|
|
81
81
|
}
|
|
82
|
-
.s-progress-bar-value--indeterminate[data-
|
|
82
|
+
.s-progress-bar-value--indeterminate[data-s-tone='neutral']::before {
|
|
83
83
|
background-color: var(--s-progress-bar-indeterminate-neutral-fill);
|
|
84
84
|
}
|