@leavepulse/ui 0.22.21 → 0.23.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/dist/chunks/{LpAddressInput-CxKwIG6T.js → LpAddressInput-BTqnUXZG.js} +3 -3
- package/dist/chunks/{LpAppShell-D8CAP9oF.js → LpAppShell-CaQYQKZV.js} +25 -14
- package/dist/chunks/{LpAvatar-B1Ez0ZAx.js → LpAvatar-D-jHoHR7.js} +15 -5
- package/dist/chunks/{LpConfirmDialog-CmgeAdCh.js → LpConfirmDialog-CObRah9c.js} +11 -6
- package/dist/chunks/{LpFileTree-Cw50eG_y.js → LpFileTree-CN0IOIY7.js} +1 -1
- package/dist/chunks/{LpFileTreeNode-DFg4PhOK.js → LpFileTreeNode-D7WgUPcJ.js} +23 -21
- package/dist/chunks/{LpFormField-Bn-ZwC6z.js → LpFormField-CesaPWPO.js} +12 -6
- package/dist/chunks/{LpInput-BkomKdqQ.js → LpInput-jwqXlAy0.js} +6 -3
- package/dist/chunks/{LpLink-DHwOEp4e.js → LpLink-DU9kkKGW.js} +25 -10
- package/dist/chunks/{LpModal-CNNSf5pv.js → LpModal-D_o-56To.js} +13 -76
- package/dist/chunks/{LpNotificationBell-DWDEkmdA.js → LpNotificationBell-a08cl0yY.js} +67 -61
- package/dist/chunks/{LpPasswordInput-DgUC2Ur7.js → LpPasswordInput-Bmo6q9Kd.js} +11 -3
- package/dist/chunks/LpShift-DXNsauQZ.js +40 -0
- package/dist/chunks/{LpTextarea-CRAkhemZ.js → LpTextarea-1ENb3ZAO.js} +7 -4
- package/dist/chunks/{LpThemeSwitcher-B_kj0T2b.js → LpThemeSwitcher-BgpJgrnP.js} +27 -0
- package/dist/component-names.d.ts +1 -1
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAppShell.vue.d.ts +6 -6
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpAvatar.vue.d.ts +10 -0
- package/dist/components/LpAvatar.vue.js +1 -1
- package/dist/components/LpConfirmDialog.vue.d.ts +8 -0
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpFileTree.vue.js +1 -1
- package/dist/components/LpFileTreeNode.vue.js +1 -1
- package/dist/components/LpFormField.vue.js +1 -1
- package/dist/components/LpInput.vue.d.ts +12 -0
- package/dist/components/LpInput.vue.js +1 -1
- package/dist/components/LpLink.vue.d.ts +20 -2
- package/dist/components/LpLink.vue.js +1 -1
- package/dist/components/LpModal.vue.js +1 -1
- package/dist/components/LpNotificationBell.vue.js +1 -1
- package/dist/components/LpPasswordInput.vue.d.ts +8 -0
- package/dist/components/LpPasswordInput.vue.js +1 -1
- package/dist/components/LpShift.vue.d.ts +36 -0
- package/dist/components/LpShift.vue.js +4 -0
- package/dist/components/LpShortcutsDialog.vue.js +1 -1
- package/dist/components/LpTextarea.vue.d.ts +5 -0
- package/dist/components/LpTextarea.vue.js +1 -1
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/composables/useShift.d.ts +35 -0
- package/dist/composables/useShift.js +112 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +48 -44
- package/dist/theme/tokens.d.ts +3 -0
- package/package.json +1 -1
- package/src/component-names.ts +1 -0
- package/src/components/LpAppShell.vue +27 -7
- package/src/components/LpAvatar.vue +17 -5
- package/src/components/LpConfirmDialog.vue +21 -6
- package/src/components/LpFileTreeNode.vue +11 -2
- package/src/components/LpFormField.vue +19 -2
- package/src/components/LpInput.vue +8 -0
- package/src/components/LpLink.vue +40 -8
- package/src/components/LpModal.vue +20 -128
- package/src/components/LpNotificationBell.vue +48 -42
- package/src/components/LpPasswordInput.vue +16 -1
- package/src/components/LpShift.vue +90 -0
- package/src/components/LpTextarea.vue +7 -0
- package/src/composables/useShift.ts +236 -0
- package/src/index.ts +3 -0
- package/src/theme/presets.ts +24 -0
- package/src/theme/tokens.ts +6 -0
- package/src/tokens/tokens.css +3 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { onBeforeUnmount, ref, toValue, watch, type MaybeRefOrGetter, type Ref } from "vue"
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* "Let this box shift its neighbours smoothly instead of jolting them."
|
|
5
|
+
*
|
|
6
|
+
* A box sized by what's inside it resizes in a single frame: a button appears
|
|
7
|
+
* in a toolbar, a translation swaps a short word for a long one, a placeholder
|
|
8
|
+
* is replaced by the loaded thing — and the layout snaps. Every neighbour it
|
|
9
|
+
* pushes snaps with it.
|
|
10
|
+
*
|
|
11
|
+
* The easing is applied to the BOX, but the point of it is the neighbours. A
|
|
12
|
+
* header of fixed height never resizes, yet the controls inside it jump the
|
|
13
|
+
* moment one of them changes width; giving that one box its width back
|
|
14
|
+
* gradually is what turns the jump into a glide. So this is named for what the
|
|
15
|
+
* user sees — things shifting — not for the measurement that achieves it.
|
|
16
|
+
*
|
|
17
|
+
* CSS alone cannot smooth this. `width`/`height: auto` are not interpolable,
|
|
18
|
+
* and the keyword-interpolation escape hatches (`interpolate-size`,
|
|
19
|
+
* `calc-size()`) are Chromium-only, so they'd do nothing in the WebKitGTK
|
|
20
|
+
* launcher. Measuring the natural size and pinning it in pixels is what works
|
|
21
|
+
* on every engine.
|
|
22
|
+
*
|
|
23
|
+
* This was first solved inside LpModal, whose panel grows as its body arrives.
|
|
24
|
+
* The mechanism is the same wherever content drives size, so it lives here and
|
|
25
|
+
* LpModal consumes it — see also LpShift, the wrapper form.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export type ShiftAxis = "height" | "width" | "both"
|
|
29
|
+
|
|
30
|
+
export interface UseShiftOptions {
|
|
31
|
+
/** Which dimension is content-derived. Default `"height"`. */
|
|
32
|
+
axis?: MaybeRefOrGetter<ShiftAxis | undefined>
|
|
33
|
+
/** Tween length. Defaults to the kit's `--duration-fast` (160ms). */
|
|
34
|
+
duration?: MaybeRefOrGetter<number | undefined>
|
|
35
|
+
/**
|
|
36
|
+
* Gate: while falsy the element is left entirely alone — no observers, no
|
|
37
|
+
* pinning. Use it for a box that only exists while something is open, so a
|
|
38
|
+
* remounted element starts measuring from scratch rather than easing in from
|
|
39
|
+
* a size it held in a previous life. Default: always active.
|
|
40
|
+
*/
|
|
41
|
+
enabled?: MaybeRefOrGetter<unknown>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface UseShift {
|
|
45
|
+
/** Attach to the element whose content-derived size should ease. */
|
|
46
|
+
el: Ref<HTMLElement | null>
|
|
47
|
+
/**
|
|
48
|
+
* True while a tween owns the size. Bind the transition utilities off this,
|
|
49
|
+
* so the element is only transition-enabled once it has a size to ease FROM
|
|
50
|
+
* (otherwise the very first pin animates in from zero).
|
|
51
|
+
*/
|
|
52
|
+
tweening: Ref<boolean>
|
|
53
|
+
/**
|
|
54
|
+
* True while the element is still catching up to its new size. During the
|
|
55
|
+
* tween the box is briefly smaller than the content it already holds, so any
|
|
56
|
+
* scroll region inside it would raise a bar for an overflow that resolves
|
|
57
|
+
* itself as the tween lands — hide the bar (not the scrolling) on this.
|
|
58
|
+
*/
|
|
59
|
+
resizing: Ref<boolean>
|
|
60
|
+
/** Re-measure and ease to the current natural size. Rarely needed by hand. */
|
|
61
|
+
retune: () => void
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Kept in step with the `duration-fast` token the transition utilities use. */
|
|
65
|
+
const TWEEN_MS = 160
|
|
66
|
+
|
|
67
|
+
export function useShift(
|
|
68
|
+
options: UseShiftOptions = {},
|
|
69
|
+
): UseShift {
|
|
70
|
+
const el = ref<HTMLElement | null>(null)
|
|
71
|
+
const tweening = ref(false)
|
|
72
|
+
const resizing = ref(false)
|
|
73
|
+
|
|
74
|
+
let ro: ResizeObserver | undefined
|
|
75
|
+
let mo: MutationObserver | undefined
|
|
76
|
+
let raf = 0
|
|
77
|
+
let settleTimer: ReturnType<typeof setTimeout> | undefined
|
|
78
|
+
/** Where the box last settled, so a retune has a size to ease FROM. */
|
|
79
|
+
let lastHeight = 0
|
|
80
|
+
let lastWidth = 0
|
|
81
|
+
/** True while a tween owns the size, so observers don't cancel it midway. */
|
|
82
|
+
let inFlight = false
|
|
83
|
+
|
|
84
|
+
const axisOf = () => toValue(options.axis) ?? "height"
|
|
85
|
+
const wantsHeight = () => axisOf() !== "width"
|
|
86
|
+
const wantsWidth = () => axisOf() !== "height"
|
|
87
|
+
|
|
88
|
+
function reducedMotion() {
|
|
89
|
+
return (
|
|
90
|
+
typeof window !== "undefined" &&
|
|
91
|
+
window.matchMedia?.("(prefers-reduced-motion: reduce)").matches
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* The size is driven imperatively rather than through a style binding. By the
|
|
97
|
+
* time replacement content is in the DOM the box has already reflowed to its
|
|
98
|
+
* new size, so a bound value would only ever be written once, with no earlier
|
|
99
|
+
* size for the transition to start from. Writing the OLD size, forcing a
|
|
100
|
+
* reflow, then writing the new one gives the transition both ends.
|
|
101
|
+
*/
|
|
102
|
+
function retune() {
|
|
103
|
+
const node = el.value
|
|
104
|
+
if (!node) return
|
|
105
|
+
// One swap wakes both observers — the mutation as content lands, the resize
|
|
106
|
+
// as it reflows — and the second call would clear the pin the first wrote.
|
|
107
|
+
if (inFlight) return
|
|
108
|
+
|
|
109
|
+
// Remembered, not measured: by the time either observer fires the box has
|
|
110
|
+
// already reflowed, so the element can only report where it is going.
|
|
111
|
+
const fromHeight = lastHeight
|
|
112
|
+
const fromWidth = lastWidth
|
|
113
|
+
|
|
114
|
+
// Measured with any cap lifted, then the clamp is left to CSS. A `max-*`
|
|
115
|
+
// from a class makes the element report the clipped figure once the cap
|
|
116
|
+
// bites, and pinning that would hold the box short of the content it now
|
|
117
|
+
// has to fit.
|
|
118
|
+
if (wantsHeight()) {
|
|
119
|
+
node.style.height = ""
|
|
120
|
+
node.style.maxHeight = "none"
|
|
121
|
+
}
|
|
122
|
+
if (wantsWidth()) {
|
|
123
|
+
node.style.width = ""
|
|
124
|
+
node.style.maxWidth = "none"
|
|
125
|
+
}
|
|
126
|
+
const toHeight = wantsHeight() ? node.offsetHeight : 0
|
|
127
|
+
const toWidth = wantsWidth() ? node.offsetWidth : 0
|
|
128
|
+
if (wantsHeight()) node.style.maxHeight = ""
|
|
129
|
+
if (wantsWidth()) node.style.maxWidth = ""
|
|
130
|
+
lastHeight = toHeight
|
|
131
|
+
lastWidth = toWidth
|
|
132
|
+
|
|
133
|
+
// Nothing moved on either axis, so there is nothing to ease — and leaving
|
|
134
|
+
// the size unset keeps the box free to size itself.
|
|
135
|
+
//
|
|
136
|
+
// Only the FROM size has to be non-zero. A target of zero is a real
|
|
137
|
+
// collapse — the last message cleared, the list emptied — and is exactly
|
|
138
|
+
// the case worth easing; an earlier guard against `to === 0` silently
|
|
139
|
+
// dropped it, so content vanishing still snapped. A zero FROM is the
|
|
140
|
+
// different thing it was meant to catch: the box was not in the layout yet,
|
|
141
|
+
// so there is no size to ease out of.
|
|
142
|
+
const movesHeight =
|
|
143
|
+
wantsHeight() && fromHeight !== 0 && toHeight !== fromHeight
|
|
144
|
+
const movesWidth = wantsWidth() && fromWidth !== 0 && toWidth !== fromWidth
|
|
145
|
+
if (!movesHeight && !movesWidth) return
|
|
146
|
+
|
|
147
|
+
if (movesHeight) node.style.height = `${fromHeight}px`
|
|
148
|
+
if (movesWidth) node.style.width = `${fromWidth}px`
|
|
149
|
+
void node.offsetHeight
|
|
150
|
+
if (movesHeight) node.style.height = `${toHeight}px`
|
|
151
|
+
if (movesWidth) node.style.width = `${toWidth}px`
|
|
152
|
+
|
|
153
|
+
inFlight = true
|
|
154
|
+
resizing.value = true
|
|
155
|
+
clearTimeout(settleTimer)
|
|
156
|
+
const wait = reducedMotion() ? 0 : (toValue(options.duration) ?? TWEEN_MS)
|
|
157
|
+
settleTimer = setTimeout(() => {
|
|
158
|
+
inFlight = false
|
|
159
|
+
resizing.value = false
|
|
160
|
+
// Released once the box has arrived. A size left pinned in pixels stops
|
|
161
|
+
// being a starting point and becomes a cap: content that grows afterwards
|
|
162
|
+
// is clipped, and `max-*` can no longer size the element itself.
|
|
163
|
+
node.style.height = ""
|
|
164
|
+
node.style.width = ""
|
|
165
|
+
// Re-read rather than trusting the target: a `max-*` may have clamped the
|
|
166
|
+
// box short of it, and the next tween has to start from where it sits.
|
|
167
|
+
lastHeight = node.offsetHeight
|
|
168
|
+
lastWidth = node.offsetWidth
|
|
169
|
+
}, wait)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function teardown() {
|
|
173
|
+
ro?.disconnect()
|
|
174
|
+
mo?.disconnect()
|
|
175
|
+
ro = undefined
|
|
176
|
+
mo = undefined
|
|
177
|
+
cancelAnimationFrame(raf)
|
|
178
|
+
clearTimeout(settleTimer)
|
|
179
|
+
tweening.value = false
|
|
180
|
+
resizing.value = false
|
|
181
|
+
lastHeight = 0
|
|
182
|
+
lastWidth = 0
|
|
183
|
+
inFlight = false
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Keyed off the element AND the gate: a portalled box remounts on every open,
|
|
187
|
+
// and the teardown has to run on close, when the ref is already gone.
|
|
188
|
+
watch(
|
|
189
|
+
[el, () => toValue(options.enabled) ?? true],
|
|
190
|
+
([node, enabled]) => {
|
|
191
|
+
teardown()
|
|
192
|
+
if (!enabled || !node) return
|
|
193
|
+
|
|
194
|
+
lastHeight = node.offsetHeight
|
|
195
|
+
lastWidth = node.offsetWidth
|
|
196
|
+
if (wantsHeight()) node.style.height = `${lastHeight}px`
|
|
197
|
+
if (wantsWidth()) node.style.width = `${lastWidth}px`
|
|
198
|
+
// A box must not animate in from its pre-content size, so the transition
|
|
199
|
+
// only arms once that first pin has painted. The pin is dropped in the
|
|
200
|
+
// same frame: it exists to give the first `retune` something to start
|
|
201
|
+
// from, and holding it would cap the box at its opening size.
|
|
202
|
+
raf = requestAnimationFrame(() => {
|
|
203
|
+
tweening.value = true
|
|
204
|
+
node.style.height = ""
|
|
205
|
+
node.style.width = ""
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
// Two triggers, since either can move the size alone: the resize observer
|
|
209
|
+
// catches a child growing in place (an image decoding, a list filling
|
|
210
|
+
// in), the mutation observer catches one subtree swapped for another,
|
|
211
|
+
// where every observed box may keep its size. Children are observed,
|
|
212
|
+
// never the element itself — that would feed the pin straight back in.
|
|
213
|
+
const watchChildren = () => {
|
|
214
|
+
if (!ro) return
|
|
215
|
+
ro.disconnect()
|
|
216
|
+
for (const child of Array.from(node.children)) ro.observe(child)
|
|
217
|
+
}
|
|
218
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
219
|
+
ro = new ResizeObserver(() => retune())
|
|
220
|
+
watchChildren()
|
|
221
|
+
}
|
|
222
|
+
if (typeof MutationObserver !== "undefined") {
|
|
223
|
+
mo = new MutationObserver(() => {
|
|
224
|
+
watchChildren()
|
|
225
|
+
retune()
|
|
226
|
+
})
|
|
227
|
+
mo.observe(node, { childList: true, subtree: true, characterData: true })
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
{ flush: "post" },
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
onBeforeUnmount(teardown)
|
|
234
|
+
|
|
235
|
+
return { el, tweening, resizing, retune }
|
|
236
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -99,6 +99,7 @@ export { default as LpSelect } from "./components/LpSelect.vue"
|
|
|
99
99
|
export type { SelectOption, SelectValue } from "./components/LpSelect.vue"
|
|
100
100
|
export { default as LpServiceNode } from "./components/LpServiceNode.vue"
|
|
101
101
|
export type { ServiceNodeData } from "./components/LpServiceNode.vue"
|
|
102
|
+
export { default as LpShift } from "./components/LpShift.vue"
|
|
102
103
|
export { default as LpShortcutsDialog } from "./components/LpShortcutsDialog.vue"
|
|
103
104
|
export type { ShortcutEntry, ShortcutGroup } from "./components/LpShortcutsDialog.vue"
|
|
104
105
|
export { default as LpSidebar } from "./components/LpSidebar.vue"
|
|
@@ -192,6 +193,8 @@ export { useRovingFocus } from "./composables/useRovingFocus"
|
|
|
192
193
|
export type { RovingItem, UseRovingFocusOptions } from "./composables/useRovingFocus"
|
|
193
194
|
export { useSettled } from "./composables/useSettled"
|
|
194
195
|
export type { UseSettledOptions } from "./composables/useSettled"
|
|
196
|
+
export { useShift } from "./composables/useShift"
|
|
197
|
+
export type { ShiftAxis, UseShift, UseShiftOptions } from "./composables/useShift"
|
|
195
198
|
export { useTilt } from "./composables/useTilt"
|
|
196
199
|
export type { UseTilt, UseTiltOptions } from "./composables/useTilt"
|
|
197
200
|
export { useZoomPan } from "./composables/useZoomPan"
|
package/src/theme/presets.ts
CHANGED
|
@@ -35,7 +35,10 @@ export const dark: TokenSet = {
|
|
|
35
35
|
brandSoft: "rgba(0, 188, 255, 0.16)",
|
|
36
36
|
action: "#39e58c",
|
|
37
37
|
actionHover: "#4dffa1",
|
|
38
|
+
actionSoft: "rgba(57, 229, 140, 0.14)",
|
|
38
39
|
accent: "#f0b35a",
|
|
40
|
+
accentHover: "#f2bf74",
|
|
41
|
+
accentSoft: "rgba(240, 179, 90, 0.14)",
|
|
39
42
|
danger: "#ff6f6f",
|
|
40
43
|
dangerHover: "#ff8585",
|
|
41
44
|
dangerSoft: "rgba(255, 111, 111, 0.14)",
|
|
@@ -64,7 +67,10 @@ export const light: TokenSet = {
|
|
|
64
67
|
brandSoft: "rgba(0, 134, 199, 0.12)",
|
|
65
68
|
action: "#1f9d5f",
|
|
66
69
|
actionHover: "#23b06b",
|
|
70
|
+
actionSoft: "rgba(31, 157, 95, 0.12)",
|
|
67
71
|
accent: "#aa6f1d",
|
|
72
|
+
accentHover: "#b88641",
|
|
73
|
+
accentSoft: "rgba(170, 111, 29, 0.12)",
|
|
68
74
|
danger: "#c2333b",
|
|
69
75
|
dangerHover: "#d23b44",
|
|
70
76
|
dangerSoft: "rgba(194, 51, 59, 0.12)",
|
|
@@ -93,7 +99,10 @@ export const lime: TokenSet = {
|
|
|
93
99
|
brandSoft: "rgba(196, 240, 66, 0.14)",
|
|
94
100
|
action: "#5fd97a",
|
|
95
101
|
actionHover: "#74e88d",
|
|
102
|
+
actionSoft: "rgba(95, 217, 122, 0.14)",
|
|
96
103
|
accent: "#ffb84d",
|
|
104
|
+
accentHover: "#ffc369",
|
|
105
|
+
accentSoft: "rgba(255, 184, 77, 0.14)",
|
|
97
106
|
danger: "#ff6f6f",
|
|
98
107
|
dangerHover: "#ff8585",
|
|
99
108
|
dangerSoft: "rgba(255, 111, 111, 0.14)",
|
|
@@ -148,7 +157,10 @@ export const leavepulse: TokenSet = {
|
|
|
148
157
|
brandSoft: "rgba(0, 188, 255, 0.2)",
|
|
149
158
|
action: "#44c2ad",
|
|
150
159
|
actionHover: "#56d3be",
|
|
160
|
+
actionSoft: "rgba(68, 194, 173, 0.14)",
|
|
151
161
|
accent: "#d36a2c",
|
|
162
|
+
accentHover: "#da824e",
|
|
163
|
+
accentSoft: "rgba(211, 106, 44, 0.14)",
|
|
152
164
|
danger: "#f87171",
|
|
153
165
|
dangerHover: "#fca5a5",
|
|
154
166
|
dangerSoft: "rgba(248, 113, 113, 0.14)",
|
|
@@ -181,7 +193,10 @@ export const rose: TokenSet = {
|
|
|
181
193
|
brandSoft: "rgba(251, 113, 133, 0.14)",
|
|
182
194
|
action: "#34d399",
|
|
183
195
|
actionHover: "#4adeaa",
|
|
196
|
+
actionSoft: "rgba(52, 211, 153, 0.14)",
|
|
184
197
|
accent: "#fbbf24",
|
|
198
|
+
accentHover: "#fcc947",
|
|
199
|
+
accentSoft: "rgba(251, 191, 36, 0.14)",
|
|
185
200
|
danger: "#ef4444",
|
|
186
201
|
dangerHover: "#f56565",
|
|
187
202
|
dangerSoft: "rgba(239, 68, 68, 0.14)",
|
|
@@ -210,7 +225,10 @@ export const amber: TokenSet = {
|
|
|
210
225
|
brandSoft: "rgba(245, 158, 11, 0.14)",
|
|
211
226
|
action: "#4ade80",
|
|
212
227
|
actionHover: "#5cea90",
|
|
228
|
+
actionSoft: "rgba(74, 222, 128, 0.14)",
|
|
213
229
|
accent: "#38bdf8",
|
|
230
|
+
accentHover: "#58c8f9",
|
|
231
|
+
accentSoft: "rgba(56, 189, 248, 0.14)",
|
|
214
232
|
danger: "#f87171",
|
|
215
233
|
dangerHover: "#fa8a8a",
|
|
216
234
|
dangerSoft: "rgba(248, 113, 113, 0.14)",
|
|
@@ -239,7 +257,10 @@ export const violet: TokenSet = {
|
|
|
239
257
|
brandSoft: "rgba(167, 139, 250, 0.14)",
|
|
240
258
|
action: "#34d399",
|
|
241
259
|
actionHover: "#4adeaa",
|
|
260
|
+
actionSoft: "rgba(52, 211, 153, 0.14)",
|
|
242
261
|
accent: "#fbbf24",
|
|
262
|
+
accentHover: "#fcc947",
|
|
263
|
+
accentSoft: "rgba(251, 191, 36, 0.14)",
|
|
243
264
|
danger: "#f87171",
|
|
244
265
|
dangerHover: "#fa8a8a",
|
|
245
266
|
dangerSoft: "rgba(248, 113, 113, 0.14)",
|
|
@@ -268,7 +289,10 @@ export const nord: TokenSet = {
|
|
|
268
289
|
brandSoft: "rgba(136, 192, 208, 0.16)",
|
|
269
290
|
action: "#a3be8c",
|
|
270
291
|
actionHover: "#b3cb9f",
|
|
292
|
+
actionSoft: "rgba(163, 190, 140, 0.16)",
|
|
271
293
|
accent: "#ebcb8b",
|
|
294
|
+
accentHover: "#eed39e",
|
|
295
|
+
accentSoft: "rgba(235, 203, 139, 0.16)",
|
|
272
296
|
danger: "#bf616a",
|
|
273
297
|
dangerHover: "#cb727b",
|
|
274
298
|
dangerSoft: "rgba(191, 97, 106, 0.16)",
|
package/src/theme/tokens.ts
CHANGED
|
@@ -18,7 +18,10 @@ export interface ColorTokens {
|
|
|
18
18
|
brandSoft: string
|
|
19
19
|
action: string
|
|
20
20
|
actionHover: string
|
|
21
|
+
actionSoft: string
|
|
21
22
|
accent: string
|
|
23
|
+
accentHover: string
|
|
24
|
+
accentSoft: string
|
|
22
25
|
danger: string
|
|
23
26
|
dangerHover: string
|
|
24
27
|
dangerSoft: string
|
|
@@ -99,7 +102,10 @@ export const COLOR_VARS: Record<keyof ColorTokens, string> = {
|
|
|
99
102
|
brandSoft: "--color-brand-soft",
|
|
100
103
|
action: "--color-action",
|
|
101
104
|
actionHover: "--color-action-hover",
|
|
105
|
+
actionSoft: "--color-action-soft",
|
|
102
106
|
accent: "--color-accent",
|
|
107
|
+
accentHover: "--color-accent-hover",
|
|
108
|
+
accentSoft: "--color-accent-soft",
|
|
103
109
|
danger: "--color-danger",
|
|
104
110
|
dangerHover: "--color-danger-hover",
|
|
105
111
|
dangerSoft: "--color-danger-soft",
|
package/src/tokens/tokens.css
CHANGED
|
@@ -36,7 +36,10 @@
|
|
|
36
36
|
--color-brand-soft: rgba(0, 188, 255, 0.16);
|
|
37
37
|
--color-action: #39e58c;
|
|
38
38
|
--color-action-hover: #4dffa1;
|
|
39
|
+
--color-action-soft: rgba(57, 229, 140, 0.14);
|
|
39
40
|
--color-accent: #f0b35a;
|
|
41
|
+
--color-accent-hover: #f2bf74;
|
|
42
|
+
--color-accent-soft: rgba(240, 179, 90, 0.14);
|
|
40
43
|
--color-danger: #ff6f6f;
|
|
41
44
|
--color-danger-hover: #ff8585;
|
|
42
45
|
--color-danger-soft: rgba(255, 111, 111, 0.14);
|