@pgcorp/ui-kit 0.5.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/SHeaderSurface.css +98 -0
- package/src/components/shared/_internal/SHeaderSurface.vue +80 -0
- package/src/components/shared/_internal/SToastItem.css +8 -8
- package/src/components/shared/_internal/SToastItem.vue +8 -1
- package/src/components/shared/_internal/useRadioGroup.ts +106 -0
- package/src/components/shared/containers/SPageHeader.vue +13 -20
- package/src/components/shared/controls/SButton.css +6 -6
- package/src/components/shared/controls/SButton.vue +9 -1
- package/src/components/shared/controls/SCheckbox.vue +14 -43
- package/src/components/shared/controls/SChoiceCards.vue +16 -39
- package/src/components/shared/controls/SField.css +0 -12
- package/src/components/shared/controls/SField.vue +14 -10
- package/src/components/shared/controls/SFieldGroup.css +1 -19
- package/src/components/shared/controls/SFieldGroup.vue +13 -10
- package/src/components/shared/controls/SFieldLabel.css +0 -1
- package/src/components/shared/controls/SFieldLabel.vue +2 -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/controls/SSegmentedControl.vue +15 -43
- package/src/components/shared/controls/SSwitch.vue +14 -32
- 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/SBadge.vue +41 -18
- package/src/components/shared/data-display/SChip.vue +22 -10
- 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/SSectionHeader.vue +17 -21
- 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/database/SDataGrid.vue +13 -0
- package/src/components/shared/navigation/STabs.vue +11 -3
- package/src/internal/fieldPresentation.ts +28 -0
- package/src/internal/ownedAttrs.ts +3 -0
- package/src/internal/pillSurface.ts +93 -0
- package/src/internal/semanticTone.ts +23 -0
- package/src/internal/useBinaryInput.ts +76 -0
- package/src/styles/style.css +114 -0
- package/src/styles/tokens.css +31 -0
- package/src/components/shared/containers/SPageHeader.css +0 -82
- package/src/components/shared/data-display/SBadge.css +0 -73
- package/src/components/shared/data-display/SChip.css +0 -59
- package/src/components/shared/data-display/SSectionHeader.css +0 -84
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
<template #default="field">
|
|
14
14
|
<span class="s-switch-control">
|
|
15
15
|
<input
|
|
16
|
+
ref="inputEl"
|
|
16
17
|
v-bind="ownedAttrs.bindings()"
|
|
17
18
|
:id="field.controlId"
|
|
18
19
|
type="checkbox"
|
|
@@ -37,10 +38,9 @@
|
|
|
37
38
|
</template>
|
|
38
39
|
|
|
39
40
|
<script setup lang="ts">
|
|
40
|
-
import { computed, useId } from 'vue'
|
|
41
41
|
import { mergeIdReferences, useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
42
42
|
import { useInteractiveLeafRegistration } from '../../../internal/passiveContentContract'
|
|
43
|
-
import {
|
|
43
|
+
import { useBinaryInput } from '../../../internal/useBinaryInput'
|
|
44
44
|
import SField from './SField.vue'
|
|
45
45
|
|
|
46
46
|
defineOptions({ inheritAttrs: false })
|
|
@@ -73,37 +73,19 @@ const emit = defineEmits<{
|
|
|
73
73
|
}>()
|
|
74
74
|
const ownedAttrs = useOwnedAttrs({ component: 'SSwitch', owner: 'native switch input' })
|
|
75
75
|
useInteractiveLeafRegistration({ owner: 'SSwitch' })
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return props.modelValue
|
|
76
|
+
const {
|
|
77
|
+
checkedValue,
|
|
78
|
+
inputEl,
|
|
79
|
+
inputId,
|
|
80
|
+
onChange,
|
|
81
|
+
onClick,
|
|
82
|
+
} = useBinaryInput({
|
|
83
|
+
owner: 'SSwitch',
|
|
84
|
+
inputName: 'switch',
|
|
85
|
+
props,
|
|
86
|
+
emitUpdate: (value) => emit('update:modelValue', value),
|
|
87
|
+
emitClick: (event) => emit('click', event),
|
|
89
88
|
})
|
|
90
|
-
|
|
91
|
-
function onChange(event: Event): void {
|
|
92
|
-
if (props.readonly) return
|
|
93
|
-
const target = event.currentTarget
|
|
94
|
-
if (!(target instanceof HTMLInputElement)) {
|
|
95
|
-
throw new TypeError('SSwitch: change event owner must be the native switch input')
|
|
96
|
-
}
|
|
97
|
-
emit('update:modelValue', target.checked)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function onClick(event: MouseEvent): void {
|
|
101
|
-
if (props.readonly) {
|
|
102
|
-
event.preventDefault()
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
emit('click', event)
|
|
106
|
-
}
|
|
107
89
|
</script>
|
|
108
90
|
|
|
109
91
|
<style lang="postcss" src="./SSwitch.css" scoped></style>
|
|
@@ -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"
|
|
@@ -1,42 +1,56 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span
|
|
3
|
-
v-bind="ownedAttrs.bindings()"
|
|
3
|
+
v-bind="{ ...ownedAttrs.bindings(), ...surfaceBindings }"
|
|
4
4
|
class="s-badge"
|
|
5
|
-
:class="{ 's-badge--dot': dot }"
|
|
6
|
-
:data-severity="severity"
|
|
7
|
-
:data-size="size"
|
|
8
|
-
:data-max-width="maxWidth"
|
|
9
|
-
:data-truncate="truncate || undefined"
|
|
10
|
-
:data-icon-motion="iconMotion"
|
|
11
5
|
>
|
|
12
6
|
<template v-if="!dot">
|
|
13
|
-
<span v-if="leadingIcon" class="
|
|
14
|
-
<component
|
|
7
|
+
<span v-if="leadingIcon" :class="PILL_ICON_CLASS" aria-hidden="true">
|
|
8
|
+
<component
|
|
9
|
+
:is="leadingIcon"
|
|
10
|
+
:class="[
|
|
11
|
+
PILL_ICON_GRAPHIC_CLASS,
|
|
12
|
+
{ [PILL_ICON_SPIN_CLASS]: iconMotion === 'spin' },
|
|
13
|
+
]"
|
|
14
|
+
/>
|
|
15
|
+
</span>
|
|
16
|
+
<span :class="[PILL_LABEL_CLASS, { [PILL_LABEL_TRUNCATE_CLASS]: truncate }]">
|
|
17
|
+
<slot />
|
|
15
18
|
</span>
|
|
16
|
-
<span class="s-badge__label"><slot /></span>
|
|
17
19
|
</template>
|
|
18
20
|
</span>
|
|
19
21
|
</template>
|
|
20
22
|
|
|
21
23
|
<script setup lang="ts">
|
|
22
|
-
import type
|
|
24
|
+
import { computed, type Component } from 'vue';
|
|
23
25
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs';
|
|
26
|
+
import {
|
|
27
|
+
PILL_ICON_CLASS,
|
|
28
|
+
PILL_ICON_GRAPHIC_CLASS,
|
|
29
|
+
PILL_ICON_SPIN_CLASS,
|
|
30
|
+
PILL_LABEL_CLASS,
|
|
31
|
+
PILL_LABEL_TRUNCATE_CLASS,
|
|
32
|
+
resolvePillSurfaceBindings,
|
|
33
|
+
type PillSurfaceIconMotion,
|
|
34
|
+
type PillSurfaceMaxWidth,
|
|
35
|
+
type PillSurfaceSeverity,
|
|
36
|
+
type PillSurfaceSize,
|
|
37
|
+
} from '../../../internal/pillSurface';
|
|
24
38
|
|
|
25
39
|
defineOptions({ inheritAttrs: false });
|
|
26
40
|
|
|
27
|
-
export type BadgeSeverity =
|
|
41
|
+
export type BadgeSeverity = PillSurfaceSeverity;
|
|
28
42
|
|
|
29
43
|
export interface Props {
|
|
30
44
|
severity?: BadgeSeverity;
|
|
31
45
|
dot?: boolean;
|
|
32
|
-
size?:
|
|
46
|
+
size?: PillSurfaceSize;
|
|
33
47
|
leadingIcon?: Component;
|
|
34
|
-
iconMotion?:
|
|
48
|
+
iconMotion?: PillSurfaceIconMotion;
|
|
35
49
|
truncate?: boolean;
|
|
36
|
-
maxWidth?:
|
|
50
|
+
maxWidth?: PillSurfaceMaxWidth;
|
|
37
51
|
}
|
|
38
52
|
|
|
39
|
-
withDefaults(defineProps<Props>(), {
|
|
53
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
40
54
|
severity: 'secondary',
|
|
41
55
|
dot: false,
|
|
42
56
|
size: 'md',
|
|
@@ -47,6 +61,15 @@ withDefaults(defineProps<Props>(), {
|
|
|
47
61
|
});
|
|
48
62
|
|
|
49
63
|
const ownedAttrs = useOwnedAttrs({ component: 'SBadge', owner: 'badge root' });
|
|
64
|
+
const surfaceBindings = computed(() => resolvePillSurfaceBindings('SBadge', {
|
|
65
|
+
kind: 'badge',
|
|
66
|
+
severity: props.severity,
|
|
67
|
+
size: props.size,
|
|
68
|
+
dot: props.dot,
|
|
69
|
+
closable: false,
|
|
70
|
+
disabled: false,
|
|
71
|
+
truncate: props.truncate,
|
|
72
|
+
maxWidth: props.maxWidth,
|
|
73
|
+
iconMotion: props.iconMotion,
|
|
74
|
+
}));
|
|
50
75
|
</script>
|
|
51
|
-
|
|
52
|
-
<style lang="postcss" src="./SBadge.css" scoped></style>
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span
|
|
3
|
-
v-bind="ownedAttrs.bindings()"
|
|
3
|
+
v-bind="{ ...ownedAttrs.bindings(), ...surfaceBindings }"
|
|
4
4
|
class="s-chip"
|
|
5
|
-
:data-severity="validatedSeverity"
|
|
6
|
-
:data-size="validatedSize"
|
|
7
|
-
:data-closable="closable || undefined"
|
|
8
|
-
:data-disabled="disabled || undefined"
|
|
9
5
|
>
|
|
10
|
-
<span v-if="leadingIcon" class="
|
|
11
|
-
<component :is="leadingIcon" class="
|
|
6
|
+
<span v-if="leadingIcon" :class="PILL_ICON_CLASS" aria-hidden="true">
|
|
7
|
+
<component :is="leadingIcon" :class="PILL_ICON_GRAPHIC_CLASS" />
|
|
12
8
|
</span>
|
|
13
|
-
<span class="
|
|
9
|
+
<span :class="[PILL_LABEL_CLASS, PILL_LABEL_TRUNCATE_CLASS]">{{ validatedLabel }}</span>
|
|
14
10
|
<SButton
|
|
15
11
|
v-if="closable"
|
|
16
12
|
label=""
|
|
@@ -34,6 +30,13 @@
|
|
|
34
30
|
import { computed, type Component } from 'vue'
|
|
35
31
|
import { X } from '../../icons/sputnigUiIcons'
|
|
36
32
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
33
|
+
import {
|
|
34
|
+
PILL_ICON_CLASS,
|
|
35
|
+
PILL_ICON_GRAPHIC_CLASS,
|
|
36
|
+
PILL_LABEL_CLASS,
|
|
37
|
+
PILL_LABEL_TRUNCATE_CLASS,
|
|
38
|
+
resolvePillSurfaceBindings,
|
|
39
|
+
} from '../../../internal/pillSurface'
|
|
37
40
|
import {
|
|
38
41
|
validateBoolean,
|
|
39
42
|
validateExactString,
|
|
@@ -80,6 +83,17 @@ const validatedSeverity = computed(() => validateExactString(
|
|
|
80
83
|
const validatedSize = computed(() => validateExactString(
|
|
81
84
|
'SChip', 'size', props.size, ['sm', 'md'] as const,
|
|
82
85
|
))
|
|
86
|
+
const surfaceBindings = computed(() => resolvePillSurfaceBindings('SChip', {
|
|
87
|
+
kind: 'chip',
|
|
88
|
+
severity: validatedSeverity.value,
|
|
89
|
+
size: validatedSize.value,
|
|
90
|
+
dot: false,
|
|
91
|
+
closable: props.closable,
|
|
92
|
+
disabled: props.disabled,
|
|
93
|
+
truncate: true,
|
|
94
|
+
maxWidth: 'none',
|
|
95
|
+
iconMotion: 'static',
|
|
96
|
+
}))
|
|
83
97
|
const resolvedCloseLabel = computed(() => {
|
|
84
98
|
validateBoolean('SChip', 'closable', props.closable)
|
|
85
99
|
validateBoolean('SChip', 'disabled', props.disabled)
|
|
@@ -88,5 +102,3 @@ const resolvedCloseLabel = computed(() => {
|
|
|
88
102
|
: validateNonEmptyString('SChip', 'closeLabel', props.closeLabel)
|
|
89
103
|
})
|
|
90
104
|
</script>
|
|
91
|
-
|
|
92
|
-
<style lang="postcss" src="./SChip.css" scoped></style>
|
|
@@ -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
|
}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
>
|
|
15
15
|
<div
|
|
16
16
|
v-if="mode === 'determinate'"
|
|
17
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
17
18
|
class="s-progress-bar-value"
|
|
18
|
-
:data-severity="severity"
|
|
19
19
|
:style="{ width: `${value}%` }"
|
|
20
20
|
>
|
|
21
21
|
<span v-if="showValue" class="s-progress-bar-label">
|
|
@@ -24,19 +24,21 @@
|
|
|
24
24
|
</div>
|
|
25
25
|
<div
|
|
26
26
|
v-else
|
|
27
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
27
28
|
class="s-progress-bar-value--indeterminate"
|
|
28
|
-
:data-severity="severity"
|
|
29
29
|
></div>
|
|
30
30
|
</div>
|
|
31
31
|
</template>
|
|
32
32
|
|
|
33
33
|
<script setup lang="ts">
|
|
34
|
-
import { watchEffect } from 'vue';
|
|
34
|
+
import { computed, watchEffect } from 'vue';
|
|
35
35
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs';
|
|
36
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone';
|
|
36
37
|
|
|
37
38
|
defineOptions({ inheritAttrs: false });
|
|
38
39
|
|
|
39
40
|
export type Severity = 'primary' | 'success' | 'info' | 'warn' | 'danger' | 'neutral';
|
|
41
|
+
const PROGRESS_SEVERITIES = ['primary', 'success', 'info', 'warn', 'danger', 'neutral'] as const satisfies readonly Severity[];
|
|
40
42
|
export type ProgressBarMode = 'determinate' | 'indeterminate';
|
|
41
43
|
export type SProgressBarAccessibility =
|
|
42
44
|
| { readonly mode: 'decorative' }
|
|
@@ -62,6 +64,12 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
62
64
|
});
|
|
63
65
|
|
|
64
66
|
const ownedAttrs = useOwnedAttrs({ component: 'SProgressBar', owner: 'progressbar root' });
|
|
67
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
68
|
+
'SProgressBar',
|
|
69
|
+
'severity',
|
|
70
|
+
props.severity,
|
|
71
|
+
PROGRESS_SEVERITIES,
|
|
72
|
+
));
|
|
65
73
|
|
|
66
74
|
watchEffect(() => {
|
|
67
75
|
if (!Number.isFinite(props.value) || props.value < 0 || props.value > 100) {
|
|
@@ -70,9 +78,7 @@ watchEffect(() => {
|
|
|
70
78
|
if (!['determinate', 'indeterminate'].includes(props.mode)) {
|
|
71
79
|
throw new TypeError(`SProgressBar: неизвестный mode "${String(props.mode)}"`);
|
|
72
80
|
}
|
|
73
|
-
|
|
74
|
-
throw new TypeError(`SProgressBar: неизвестный severity "${String(props.severity)}"`);
|
|
75
|
-
}
|
|
81
|
+
void toneBinding.value;
|
|
76
82
|
if (!['xs', 'sm', 'md'].includes(props.size)) {
|
|
77
83
|
throw new TypeError(`SProgressBar: неизвестный size "${String(props.size)}"`);
|
|
78
84
|
}
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
.s-progress-indicator[data-size='md'] { --s-progress-indicator-size: var(--s-icon-size-md); }
|
|
24
24
|
.s-progress-indicator[data-size='lg'] { --s-progress-indicator-size: var(--s-icon-size-lg); }
|
|
25
25
|
|
|
26
|
-
.s-progress-indicator[data-tone='neutral'] { color: var(--s-progress-indicator-foreground-neutral); }
|
|
27
|
-
.s-progress-indicator[data-tone='info'] { color: var(--s-progress-indicator-foreground-info); }
|
|
28
|
-
.s-progress-indicator[data-tone='success'] { color: var(--s-progress-indicator-foreground-success); }
|
|
29
|
-
.s-progress-indicator[data-tone='warn'] { color: var(--s-progress-indicator-foreground-warn); }
|
|
30
|
-
.s-progress-indicator[data-tone='danger'] { color: var(--s-progress-indicator-foreground-danger); }
|
|
26
|
+
.s-progress-indicator[data-s-tone='neutral'] { color: var(--s-progress-indicator-foreground-neutral); }
|
|
27
|
+
.s-progress-indicator[data-s-tone='info'] { color: var(--s-progress-indicator-foreground-info); }
|
|
28
|
+
.s-progress-indicator[data-s-tone='success'] { color: var(--s-progress-indicator-foreground-success); }
|
|
29
|
+
.s-progress-indicator[data-s-tone='warn'] { color: var(--s-progress-indicator-foreground-warn); }
|
|
30
|
+
.s-progress-indicator[data-s-tone='danger'] { color: var(--s-progress-indicator-foreground-danger); }
|
|
31
31
|
|
|
32
32
|
.s-progress-indicator__graphic {
|
|
33
33
|
width: 100%;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span
|
|
3
3
|
v-bind="ownedAttrs.bindings()"
|
|
4
|
+
:data-s-tone="toneBinding['data-s-tone']"
|
|
4
5
|
class="s-progress-indicator"
|
|
5
6
|
:data-size="size"
|
|
6
|
-
:data-tone="tone"
|
|
7
7
|
:data-motion="presentation.motion"
|
|
8
8
|
:data-show-label="validatedShowLabel || undefined"
|
|
9
9
|
:role="liveAttributes.role"
|
|
@@ -30,12 +30,14 @@ import { computed, watchEffect } from 'vue'
|
|
|
30
30
|
|
|
31
31
|
import { resolveFeedbackIndicator, resolveFeedbackLive, type FeedbackLiveMode } from '../../../internal/feedbackPresentation'
|
|
32
32
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
33
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
33
34
|
import { validateBoolean } from '../../../internal/runtimeContract'
|
|
34
35
|
|
|
35
36
|
defineOptions({ inheritAttrs: false })
|
|
36
37
|
|
|
37
38
|
export type SProgressIndicatorSize = 'xs' | 'sm' | 'md' | 'lg'
|
|
38
39
|
export type SProgressIndicatorTone = 'current' | 'neutral' | 'info' | 'success' | 'warn' | 'danger'
|
|
40
|
+
const PROGRESS_INDICATOR_TONES = ['current', 'neutral', 'info', 'success', 'warn', 'danger'] as const satisfies readonly SProgressIndicatorTone[]
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
* Декоративный progress принадлежит labelled parent; standalone status требует собственного имени.
|
|
@@ -64,6 +66,12 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
64
66
|
})
|
|
65
67
|
|
|
66
68
|
const ownedAttrs = useOwnedAttrs({ component: 'SProgressIndicator', owner: 'progress indicator root' })
|
|
69
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
70
|
+
'SProgressIndicator',
|
|
71
|
+
'tone',
|
|
72
|
+
props.tone,
|
|
73
|
+
PROGRESS_INDICATOR_TONES,
|
|
74
|
+
))
|
|
67
75
|
const presentation = resolveFeedbackIndicator('progress')
|
|
68
76
|
const validatedShowLabel = computed(() => validateBoolean('SProgressIndicator', 'showLabel', props.showLabel))
|
|
69
77
|
const feedbackTone = computed(() => props.tone === 'current' ? 'info' : props.tone)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
3
|
+
import SHeaderSurface from '../_internal/SHeaderSurface.vue'
|
|
3
4
|
|
|
4
5
|
defineOptions({ inheritAttrs: false })
|
|
5
6
|
|
|
@@ -32,27 +33,22 @@ const ownedAttrs = useOwnedAttrs({ component: 'SSectionHeader', owner: 'section
|
|
|
32
33
|
</script>
|
|
33
34
|
|
|
34
35
|
<template>
|
|
35
|
-
<
|
|
36
|
+
<SHeaderSurface
|
|
36
37
|
v-bind="ownedAttrs.bindings()"
|
|
37
|
-
|
|
38
|
-
:
|
|
39
|
-
:
|
|
40
|
-
:
|
|
41
|
-
:
|
|
42
|
-
:
|
|
43
|
-
:
|
|
38
|
+
kind="section"
|
|
39
|
+
:title="title"
|
|
40
|
+
:eyebrow="eyebrow"
|
|
41
|
+
:description="description"
|
|
42
|
+
:meta="meta"
|
|
43
|
+
:heading-level="headingLevel"
|
|
44
|
+
:size="size"
|
|
45
|
+
:variant="variant"
|
|
46
|
+
:divider="divider"
|
|
47
|
+
:padding="padding"
|
|
48
|
+
:spacing-after="spacingAfter"
|
|
49
|
+
:trailing-layout="trailingLayout"
|
|
44
50
|
>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<p v-if="description" class="s-section-header__description">{{ description }}</p>
|
|
49
|
-
<p v-if="meta" class="s-section-header__meta">{{ meta }}</p>
|
|
50
|
-
</div>
|
|
51
|
-
<div v-if="$slots.badges || $slots.actions" class="s-section-header__trailing">
|
|
52
|
-
<div v-if="$slots.badges" class="s-section-header__badges"><slot name="badges" /></div>
|
|
53
|
-
<div v-if="$slots.actions" class="s-section-header__actions"><slot name="actions" /></div>
|
|
54
|
-
</div>
|
|
55
|
-
</header>
|
|
51
|
+
<template v-if="$slots.badges" #badges><slot name="badges" /></template>
|
|
52
|
+
<template v-if="$slots.actions" #actions><slot name="actions" /></template>
|
|
53
|
+
</SHeaderSurface>
|
|
56
54
|
</template>
|
|
57
|
-
|
|
58
|
-
<style lang="postcss" src="./SSectionHeader.css" scoped></style>
|
|
@@ -49,42 +49,42 @@
|
|
|
49
49
|
@apply sr-only;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
.s-status[data-tone='neutral'] {
|
|
52
|
+
.s-status[data-s-tone='neutral'] {
|
|
53
53
|
@apply text-surface-500 dark:text-surface-400;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
.s-status[data-tone='info'] {
|
|
56
|
+
.s-status[data-s-tone='info'] {
|
|
57
57
|
@apply text-info-700 dark:text-info-300;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
.s-status[data-tone='success'] {
|
|
60
|
+
.s-status[data-s-tone='success'] {
|
|
61
61
|
@apply text-success-700 dark:text-success-300;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
.s-status[data-tone='warn'] {
|
|
64
|
+
.s-status[data-s-tone='warn'] {
|
|
65
65
|
@apply text-warn-700 dark:text-warn-300;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
.s-status[data-tone='danger'] {
|
|
68
|
+
.s-status[data-s-tone='danger'] {
|
|
69
69
|
@apply text-danger-700 dark:text-danger-300;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
.s-status[data-appearance='soft'][data-tone='neutral'] {
|
|
72
|
+
.s-status[data-appearance='soft'][data-s-tone='neutral'] {
|
|
73
73
|
@apply border-surface-200 bg-surface-100 dark:border-surface-700 dark:bg-surface-800;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
.s-status[data-appearance='soft'][data-tone='info'] {
|
|
76
|
+
.s-status[data-appearance='soft'][data-s-tone='info'] {
|
|
77
77
|
@apply border-info-200 bg-info-50 dark:border-info-800 dark:bg-info-950;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
.s-status[data-appearance='soft'][data-tone='success'] {
|
|
80
|
+
.s-status[data-appearance='soft'][data-s-tone='success'] {
|
|
81
81
|
@apply border-success-200 bg-success-50 dark:border-success-800 dark:bg-success-950;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
.s-status[data-appearance='soft'][data-tone='warn'] {
|
|
84
|
+
.s-status[data-appearance='soft'][data-s-tone='warn'] {
|
|
85
85
|
@apply border-warn-200 bg-warn-50 dark:border-warn-800 dark:bg-warn-950;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
.s-status[data-appearance='soft'][data-tone='danger'] {
|
|
88
|
+
.s-status[data-appearance='soft'][data-s-tone='danger'] {
|
|
89
89
|
@apply border-danger-200 bg-danger-50 dark:border-danger-800 dark:bg-danger-950;
|
|
90
90
|
}
|
|
@@ -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-status"
|
|
5
|
-
:data-tone="tone"
|
|
6
6
|
:data-appearance="appearance"
|
|
7
7
|
:data-size="size"
|
|
8
8
|
:data-label-visibility="labelVisibility"
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<script setup lang="ts">
|
|
23
23
|
import { computed, markRaw, toRaw, type Component } from 'vue'
|
|
24
24
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
25
|
+
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
25
26
|
|
|
26
27
|
import {
|
|
27
28
|
resolveFeedbackLive,
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
defineOptions({ inheritAttrs: false })
|
|
34
35
|
|
|
35
36
|
export type StatusTone = FeedbackTone
|
|
37
|
+
const STATUS_TONES = ['neutral', 'info', 'success', 'warn', 'danger'] as const satisfies readonly StatusTone[]
|
|
36
38
|
export type StatusAppearance = 'text' | 'soft'
|
|
37
39
|
export type StatusSize = 'xs' | 'sm' | 'md'
|
|
38
40
|
export type StatusLiveMode = Exclude<FeedbackLiveMode, 'auto'>
|
|
@@ -66,6 +68,12 @@ const props = withDefaults(defineProps<{
|
|
|
66
68
|
|
|
67
69
|
const defaultIcon = computed<Component>(() => resolveFeedbackPresentation(props.tone).icon)
|
|
68
70
|
const ownedAttrs = useOwnedAttrs({ component: 'SStatus', owner: 'status root' })
|
|
71
|
+
const toneBinding = computed(() => resolveSemanticToneBinding(
|
|
72
|
+
'SStatus',
|
|
73
|
+
'tone',
|
|
74
|
+
props.tone,
|
|
75
|
+
STATUS_TONES,
|
|
76
|
+
))
|
|
69
77
|
const liveAttributes = computed(() => resolveFeedbackLive(props.tone, props.live))
|
|
70
78
|
|
|
71
79
|
const resolvedIcon = computed<Component | null>(() => {
|