@redseed/redseed-ui-vue3 8.67.0 → 8.69.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/package.json
CHANGED
|
@@ -66,6 +66,39 @@ const props = defineProps({
|
|
|
66
66
|
type: Boolean,
|
|
67
67
|
default: false,
|
|
68
68
|
},
|
|
69
|
+
// CATEGORY colour, which is a different job from the semantic variants above.
|
|
70
|
+
// `brand`/`success`/`error` and friends say what STATE a thing is in; they
|
|
71
|
+
// cannot say which taxonomy a thing BELONGS to (a capability domain, a team, a
|
|
72
|
+
// location, a pathway), and there are always more categories than the semantic
|
|
73
|
+
// set has slots.
|
|
74
|
+
//
|
|
75
|
+
// Takes the name of a RUNTIME CSS custom property, applied as
|
|
76
|
+
// `var(--<color>, <neutral>)` — the same convention and the same neutral
|
|
77
|
+
// degrade as Pill's `color` prop, so the two components stay consistent and
|
|
78
|
+
// RSUI stays theme-agnostic. Pass a real runtime theme variable, e.g. the
|
|
79
|
+
// consuming app's palette (`color7` -> `var(--color7)`). NOTE: RSUI's own
|
|
80
|
+
// Tailwind `@theme` tokens (e.g. `--color-brand-500`) are inlined into
|
|
81
|
+
// utilities, not exposed as runtime vars, so they will NOT resolve here. An
|
|
82
|
+
// UNRESOLVABLE (undefined) token degrades to a neutral grey rather than an
|
|
83
|
+
// invisible bar; a token that *resolves* to `transparent`/empty is not caught.
|
|
84
|
+
//
|
|
85
|
+
// On its own this prop paints nothing — it needs `accent` to say which edge
|
|
86
|
+
// carries it.
|
|
87
|
+
color: {
|
|
88
|
+
type: String,
|
|
89
|
+
default: '',
|
|
90
|
+
},
|
|
91
|
+
// Which edge carries the category accent bar. Default 'none', so nothing
|
|
92
|
+
// changes for any existing consumer. Thickness is NOT a consumer decision —
|
|
93
|
+
// it comes from a token (see --rsui-card-accent-w in card.css). That is the
|
|
94
|
+
// whole point of the prop: the same concept was hand-rolled twice on one page
|
|
95
|
+
// at two different weights (4px and 3px) precisely because nothing told the
|
|
96
|
+
// author what the weight should be.
|
|
97
|
+
accent: {
|
|
98
|
+
type: String,
|
|
99
|
+
default: 'none',
|
|
100
|
+
validator: (value) => ['left', 'top', 'none'].includes(value),
|
|
101
|
+
},
|
|
69
102
|
ariaLabel: {
|
|
70
103
|
type: String,
|
|
71
104
|
default: undefined,
|
|
@@ -110,6 +143,16 @@ const ariaCurrent = computed(() => {
|
|
|
110
143
|
// conveyed by colour alone (WCAG 1.4.1).
|
|
111
144
|
const isActive = computed(() => props.pressed === true || Boolean(props.current))
|
|
112
145
|
|
|
146
|
+
// The accent token is only set when a color is supplied; otherwise the property
|
|
147
|
+
// is left unset so the CSS neutral fallback applies. When it IS supplied it
|
|
148
|
+
// carries an inline fallback to the neutral grey, so an unresolvable token
|
|
149
|
+
// degrades to grey rather than to an invisible edge. Mirrors Pill exactly.
|
|
150
|
+
const accentStyle = computed(() =>
|
|
151
|
+
props.color
|
|
152
|
+
? { '--rsui-card-accent': `var(--${props.color}, var(--Colors-Grey-500))` }
|
|
153
|
+
: {},
|
|
154
|
+
)
|
|
155
|
+
|
|
113
156
|
const slots = useSlots()
|
|
114
157
|
|
|
115
158
|
const cardElement = ref(null)
|
|
@@ -130,6 +173,8 @@ const cardClass = computed(() => [
|
|
|
130
173
|
'rsui-card--warning': props.warning,
|
|
131
174
|
'rsui-card--error': props.error,
|
|
132
175
|
'rsui-card--draft': props.draft,
|
|
176
|
+
'rsui-card--accent-left': props.accent === 'left',
|
|
177
|
+
'rsui-card--accent-top': props.accent === 'top',
|
|
133
178
|
'rsui-card--2xs': responsiveWidth.value['2xs'],
|
|
134
179
|
'rsui-card--xs': responsiveWidth.value['xs'],
|
|
135
180
|
'rsui-card--sm': responsiveWidth.value['sm'],
|
|
@@ -170,7 +215,7 @@ function onClick() {
|
|
|
170
215
|
}
|
|
171
216
|
</script>
|
|
172
217
|
<template>
|
|
173
|
-
<div ref="cardElement" :class="cardClass" data-testid="card">
|
|
218
|
+
<div ref="cardElement" :class="cardClass" :style="accentStyle" data-testid="card">
|
|
174
219
|
<svg
|
|
175
220
|
v-if="draft"
|
|
176
221
|
class="rsui-card__draft-border"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ref, watch } from 'vue'
|
|
2
|
+
import { computed, ref, useSlots, watch } from 'vue'
|
|
3
3
|
import Card from './Card.vue'
|
|
4
4
|
import CardHeader from './CardHeader.vue'
|
|
5
5
|
import FormFieldCheckbox from '../FormField/FormFieldCheckbox.vue'
|
|
@@ -31,6 +31,14 @@ const props = defineProps({
|
|
|
31
31
|
|
|
32
32
|
const emit = defineEmits(['check', 'uncheck', 'change'])
|
|
33
33
|
|
|
34
|
+
const slots = useSlots()
|
|
35
|
+
|
|
36
|
+
// Whether anything renders BELOW the header. When nothing does, the card is header-only
|
|
37
|
+
// and the header has to pay its own bottom padding — it is styled `pb-0` and normally
|
|
38
|
+
// borrows its bottom edge from the body's padding, so without this a title-only card sits
|
|
39
|
+
// flush against its own border.
|
|
40
|
+
const hasBody = computed(() => Boolean(slots.default || slots.meta))
|
|
41
|
+
|
|
34
42
|
const isChecked = ref(props.checked)
|
|
35
43
|
|
|
36
44
|
watch(() => props.checked, (val) => {
|
|
@@ -66,6 +74,7 @@ function onFieldInput() {
|
|
|
66
74
|
:showMoreActions="showMoreActions"
|
|
67
75
|
:showDivider="false"
|
|
68
76
|
:singleLine="false"
|
|
77
|
+
:headerOnlyCard="!hasBody"
|
|
69
78
|
>
|
|
70
79
|
<div class="rsui-checkbox-card__title-row">
|
|
71
80
|
<div class="rsui-checkbox-card__field">
|
|
@@ -102,7 +111,13 @@ function onFieldInput() {
|
|
|
102
111
|
</CardHeader>
|
|
103
112
|
</template>
|
|
104
113
|
|
|
105
|
-
<slot
|
|
114
|
+
<!-- v-if, not a bare <slot>. Card already guards its body with
|
|
115
|
+
`v-if="$slots.default || $slots.meta"`, but a bare <slot> here counts as a default
|
|
116
|
+
slot whether or not the consumer filled it, so that guard could never fire and a
|
|
117
|
+
title-only task card still rendered an empty padded body. -->
|
|
118
|
+
<template #default v-if="$slots.default">
|
|
119
|
+
<slot></slot>
|
|
120
|
+
</template>
|
|
106
121
|
|
|
107
122
|
<template #meta v-if="$slots.meta">
|
|
108
123
|
<slot name="meta"></slot>
|