@nonsuch/component-library 0.3.0 → 0.4.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 +159 -15
- package/dist/nonsuch-components.css +1 -1
- package/dist/nonsuch-components.js +235 -43
- package/fonts/global.css +2 -2
- package/package.json +5 -3
- package/src/tokens/tokens.css +236 -0
package/README.md
CHANGED
|
@@ -12,9 +12,9 @@ pnpm add @nonsuch/component-library
|
|
|
12
12
|
pnpm add quasar @quasar/extras @quasar/vite-plugin
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### Quick Start (Recommended)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
#### Vite Configuration
|
|
18
18
|
|
|
19
19
|
```ts
|
|
20
20
|
import { quasar, transformAssetUrls } from '@quasar/vite-plugin'
|
|
@@ -25,25 +25,89 @@ export default defineConfig({
|
|
|
25
25
|
})
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Register Quasar in your Vue app:
|
|
28
|
+
#### App Entry
|
|
31
29
|
|
|
32
30
|
```ts
|
|
33
31
|
import { createApp } from 'vue'
|
|
34
32
|
import { Quasar } from 'quasar'
|
|
33
|
+
import { createNonsuch, createQuasarConfig } from '@nonsuch/component-library'
|
|
34
|
+
import '@nonsuch/component-library/tokens.css'
|
|
35
35
|
import 'quasar/src/css/index.sass'
|
|
36
36
|
|
|
37
37
|
const app = createApp(App)
|
|
38
|
-
app.use(Quasar,
|
|
38
|
+
app.use(Quasar, createQuasarConfig()) // Token-aligned Quasar brand colours
|
|
39
|
+
app.use(createNonsuch()) // Locale + library setup
|
|
40
|
+
app.mount('#app')
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
That's it — components, tokens, locale (defaults to `en-CA`), and Quasar brand colours are all wired up.
|
|
44
|
+
|
|
45
|
+
#### Use Components
|
|
46
|
+
|
|
47
|
+
```vue
|
|
48
|
+
<script setup>
|
|
49
|
+
import { NsButton, NsInput, NsCard } from '@nonsuch/component-library'
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<template>
|
|
53
|
+
<NsCard title="Welcome">
|
|
54
|
+
<NsInput v-model="name" label="Your name" />
|
|
55
|
+
<template #actions>
|
|
56
|
+
<NsButton label="Submit" />
|
|
57
|
+
</template>
|
|
58
|
+
</NsCard>
|
|
59
|
+
</template>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Plugin Options
|
|
63
|
+
|
|
64
|
+
`createNonsuch()` accepts options for locale:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { createNonsuch, nsLocaleFrCA } from '@nonsuch/component-library'
|
|
68
|
+
|
|
69
|
+
app.use(createNonsuch({ locale: nsLocaleFrCA }))
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`createQuasarConfig()` accepts brand colour overrides and extra Quasar config:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { createQuasarConfig } from '@nonsuch/component-library'
|
|
76
|
+
|
|
77
|
+
app.use(Quasar, createQuasarConfig({
|
|
78
|
+
brand: { primary: '#1a73e8' },
|
|
79
|
+
plugins: { Notify: {} },
|
|
80
|
+
}))
|
|
39
81
|
```
|
|
40
82
|
|
|
41
|
-
|
|
83
|
+
### Dark Mode
|
|
42
84
|
|
|
43
85
|
```ts
|
|
44
|
-
import {
|
|
86
|
+
import { useNsDarkMode } from '@nonsuch/component-library'
|
|
87
|
+
|
|
88
|
+
const { isDark, toggle, useSystem } = useNsDarkMode()
|
|
45
89
|
```
|
|
46
90
|
|
|
91
|
+
The composable persists the user's choice to `localStorage` and syncs with `prefers-color-scheme`. Design tokens switch automatically via the `dark` class on `<html>`.
|
|
92
|
+
|
|
93
|
+
### NsThemeProvider
|
|
94
|
+
|
|
95
|
+
For section-level locale overrides without a plugin:
|
|
96
|
+
|
|
97
|
+
```vue
|
|
98
|
+
<script setup>
|
|
99
|
+
import { NsThemeProvider, nsLocaleFrCA } from '@nonsuch/component-library'
|
|
100
|
+
</script>
|
|
101
|
+
|
|
102
|
+
<template>
|
|
103
|
+
<NsThemeProvider :locale="nsLocaleFrCA">
|
|
104
|
+
<!-- All Ns components here use French strings -->
|
|
105
|
+
</NsThemeProvider>
|
|
106
|
+
</template>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Manual Setup (Advanced)
|
|
110
|
+
|
|
47
111
|
### Fonts (Optional)
|
|
48
112
|
|
|
49
113
|
The library ships [Fixel](https://fixel.macpaw.com/) as the Nonsuch brand font with Roboto as a fallback. Three integration options:
|
|
@@ -86,6 +150,77 @@ Or use Quasar components directly — they aren't re-exported through this libra
|
|
|
86
150
|
import { QInput, QSelect } from 'quasar'
|
|
87
151
|
```
|
|
88
152
|
|
|
153
|
+
### Translations (i18n)
|
|
154
|
+
|
|
155
|
+
The library ships its own locale system — **no dependency on vue-i18n**. Components that render user-visible text accept optional string props with built-in defaults from the active locale.
|
|
156
|
+
|
|
157
|
+
**Built-in locales:** `en-CA` (default) and `fr-CA`.
|
|
158
|
+
|
|
159
|
+
**Option 1: Use the defaults** — components use English (Canada) strings out of the box with no setup:
|
|
160
|
+
|
|
161
|
+
```vue
|
|
162
|
+
<NsButton>Add to cart</NsButton>
|
|
163
|
+
<!-- internal labels like loading text already default to English -->
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Option 2: Switch locale globally** — provide a locale pack at the app root:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { createApp } from 'vue'
|
|
170
|
+
import { provideNsLocale, nsLocaleFrCA } from '@nonsuch/component-library'
|
|
171
|
+
|
|
172
|
+
const app = createApp(App)
|
|
173
|
+
|
|
174
|
+
// Inside your root component's setup():
|
|
175
|
+
provideNsLocale(nsLocaleFrCA)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Option 3: Custom / partial locale** — supply your own translations by implementing the `NsLocaleMessages` interface:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import type { NsLocaleMessages } from '@nonsuch/component-library'
|
|
182
|
+
import { nsLocaleEnCA, provideNsLocale } from '@nonsuch/component-library'
|
|
183
|
+
|
|
184
|
+
const myLocale: NsLocaleMessages = {
|
|
185
|
+
...nsLocaleEnCA,
|
|
186
|
+
product: {
|
|
187
|
+
...nsLocaleEnCA.product,
|
|
188
|
+
addToCart: 'Add to bag', // override just what you need
|
|
189
|
+
},
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
provideNsLocale(myLocale)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Option 4: Override per-component** — pass a string prop directly to bypass the locale:
|
|
196
|
+
|
|
197
|
+
```vue
|
|
198
|
+
<!-- This label is always "Ajouter" regardless of the active locale -->
|
|
199
|
+
<NsButton label="Ajouter" />
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The locale interface covers four sections: `common`, `product`, `media`, and `validation`. See the full type in `NsLocaleMessages`.
|
|
203
|
+
|
|
204
|
+
### Design Tokens (Optional)
|
|
205
|
+
|
|
206
|
+
Import CSS custom properties for colours, typography, spacing, border-radius, shadows, and motion:
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import '@nonsuch/component-library/tokens.css'
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
All tokens use the `--ns-` prefix and support light/dark mode automatically. Current values are placeholders — token names are stable.
|
|
213
|
+
|
|
214
|
+
```css
|
|
215
|
+
.my-card {
|
|
216
|
+
border-radius: var(--ns-radius-md);
|
|
217
|
+
box-shadow: var(--ns-shadow-sm);
|
|
218
|
+
padding: var(--ns-space-4);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Dark mode activates via `class="dark"`, `data-theme="dark"`, Quasar's `.q-dark`, or `prefers-color-scheme: dark`.
|
|
223
|
+
|
|
89
224
|
## Development
|
|
90
225
|
|
|
91
226
|
```bash
|
|
@@ -110,13 +245,22 @@ pnpm build:storybook
|
|
|
110
245
|
|
|
111
246
|
```markdown
|
|
112
247
|
src/
|
|
113
|
-
index.ts
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
NsButton
|
|
118
|
-
|
|
119
|
-
|
|
248
|
+
index.ts # Library entry — exports all public API
|
|
249
|
+
plugin.ts # createNonsuch() Vue plugin
|
|
250
|
+
quasarConfig.ts # createQuasarConfig() helper
|
|
251
|
+
components/
|
|
252
|
+
NsButton/ # Styled QBtn wrapper
|
|
253
|
+
NsCard/ # Card with title/subtitle/actions slots
|
|
254
|
+
NsInput/ # Styled QInput wrapper
|
|
255
|
+
NsSkeleton/ # Loading skeleton with animation
|
|
256
|
+
NsThemeProvider/ # Renderless locale provider
|
|
257
|
+
composables/
|
|
258
|
+
useNsLocale.ts # Locale injection/provision
|
|
259
|
+
useNsDarkMode.ts # Dark mode with persistence
|
|
260
|
+
useNsDefaults.ts # Default value helper
|
|
261
|
+
locale/ # en-CA, fr-CA string packs
|
|
262
|
+
tokens/ # Design token CSS + TS helpers
|
|
263
|
+
fonts/ # Fixel font files + CSS
|
|
120
264
|
```
|
|
121
265
|
|
|
122
266
|
Each custom component lives in its own directory with co-located story and test files. The `Ns` prefix distinguishes library components from Quasar's `Q` prefix.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.ns-button[data-v-
|
|
1
|
+
.ns-button[data-v-7f6c2760]{font-family:var(--ns-font-family-text);font-weight:var(--ns-font-weight-medium);letter-spacing:var(--ns-letter-spacing-wide)}.ns-skeleton[data-v-62627927]{border-radius:var(--ns-radius-md)}.ns-input[data-v-7ebf3284],.ns-input[data-v-7ebf3284] .q-field__label{font-family:var(--ns-font-family-text)}.ns-input[data-v-7ebf3284] .q-field__control{border-radius:var(--ns-radius-md)}.ns-card[data-v-41ecea50]{border-radius:var(--ns-radius-lg);box-shadow:var(--ns-shadow-sm);font-family:var(--ns-font-family-text);transition:box-shadow var(--ns-duration-normal) var(--ns-easing-default)}.ns-card[data-v-41ecea50]:hover{box-shadow:var(--ns-shadow-md)}.ns-card--flat[data-v-41ecea50],.ns-card--flat[data-v-41ecea50]:hover{box-shadow:none}.ns-card__header[data-v-41ecea50]{font-family:var(--ns-font-family-display)}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { defineComponent as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
1
|
+
import Q from "quasar/src/components/btn/QBtn.js";
|
|
2
|
+
import { defineComponent as c, openBlock as s, createBlock as d, mergeProps as p, withCtx as u, renderSlot as i, createVNode as B, unref as T, provide as V, inject as q, createSlots as z, renderList as R, normalizeProps as D, guardReactiveProps as M, createElementVNode as O, toDisplayString as w, createElementBlock as F, createCommentVNode as v, computed as _, ref as C, onMounted as x, onUnmounted as j, readonly as I } from "vue";
|
|
3
|
+
import K from "quasar/src/components/spinner/QSpinnerDots.js";
|
|
4
|
+
import U from "quasar/src/components/skeleton/QSkeleton.js";
|
|
5
|
+
import Z from "quasar/src/components/input/QInput.js";
|
|
6
|
+
import $ from "quasar/src/components/card/QCardSection.js";
|
|
7
|
+
import G from "quasar/src/components/card/QCardActions.js";
|
|
8
|
+
import H from "quasar/src/components/card/QCard.js";
|
|
9
|
+
const Y = /* @__PURE__ */ c({
|
|
6
10
|
__name: "NsButton",
|
|
7
11
|
props: {
|
|
8
12
|
color: { default: "primary" },
|
|
@@ -13,7 +17,7 @@ const B = /* @__PURE__ */ s({
|
|
|
13
17
|
loading: { type: Boolean, default: !1 }
|
|
14
18
|
},
|
|
15
19
|
setup(e) {
|
|
16
|
-
return (
|
|
20
|
+
return (t, o) => (s(), d(Q, p(t.$attrs, {
|
|
17
21
|
color: e.color,
|
|
18
22
|
size: e.size,
|
|
19
23
|
unelevated: e.unelevated,
|
|
@@ -22,23 +26,23 @@ const B = /* @__PURE__ */ s({
|
|
|
22
26
|
loading: e.loading,
|
|
23
27
|
class: "ns-button"
|
|
24
28
|
}), {
|
|
25
|
-
loading:
|
|
26
|
-
i(
|
|
27
|
-
|
|
29
|
+
loading: u(() => [
|
|
30
|
+
i(t.$slots, "loading", {}, () => [
|
|
31
|
+
B(T(K), { color: "white" })
|
|
28
32
|
], !0)
|
|
29
33
|
]),
|
|
30
|
-
default:
|
|
31
|
-
i(
|
|
34
|
+
default: u(() => [
|
|
35
|
+
i(t.$slots, "default", {}, void 0, !0)
|
|
32
36
|
]),
|
|
33
37
|
_: 3
|
|
34
38
|
}, 16, ["color", "size", "unelevated", "no-caps", "rounded", "loading"]));
|
|
35
39
|
}
|
|
36
|
-
}),
|
|
37
|
-
const
|
|
38
|
-
for (const [n, r] of
|
|
39
|
-
|
|
40
|
-
return
|
|
41
|
-
},
|
|
40
|
+
}), g = (e, t) => {
|
|
41
|
+
const o = e.__vccOpts || e;
|
|
42
|
+
for (const [n, r] of t)
|
|
43
|
+
o[n] = r;
|
|
44
|
+
return o;
|
|
45
|
+
}, me = /* @__PURE__ */ g(Y, [["__scopeId", "data-v-7f6c2760"]]), J = /* @__PURE__ */ c({
|
|
42
46
|
__name: "NsSkeleton",
|
|
43
47
|
props: {
|
|
44
48
|
type: { default: "rect" },
|
|
@@ -49,7 +53,7 @@ const B = /* @__PURE__ */ s({
|
|
|
49
53
|
height: { default: void 0 }
|
|
50
54
|
},
|
|
51
55
|
setup(e) {
|
|
52
|
-
return (
|
|
56
|
+
return (t, o) => (s(), d(U, p(t.$attrs, {
|
|
53
57
|
type: e.type,
|
|
54
58
|
animation: e.animation,
|
|
55
59
|
square: e.square,
|
|
@@ -59,7 +63,7 @@ const B = /* @__PURE__ */ s({
|
|
|
59
63
|
class: "ns-skeleton"
|
|
60
64
|
}), null, 16, ["type", "animation", "square", "bordered", "width", "height"]));
|
|
61
65
|
}
|
|
62
|
-
}),
|
|
66
|
+
}), pe = /* @__PURE__ */ g(J, [["__scopeId", "data-v-62627927"]]), y = {
|
|
63
67
|
common: {
|
|
64
68
|
loading: "Loading…",
|
|
65
69
|
retry: "Retry",
|
|
@@ -95,7 +99,138 @@ const B = /* @__PURE__ */ s({
|
|
|
95
99
|
tooShort: "Too short",
|
|
96
100
|
tooLong: "Too long"
|
|
97
101
|
}
|
|
98
|
-
},
|
|
102
|
+
}, S = /* @__PURE__ */ Symbol("ns-locale");
|
|
103
|
+
function W(e) {
|
|
104
|
+
V(S, e);
|
|
105
|
+
}
|
|
106
|
+
function X() {
|
|
107
|
+
return q(S, y);
|
|
108
|
+
}
|
|
109
|
+
const ge = /* @__PURE__ */ c({
|
|
110
|
+
__name: "NsThemeProvider",
|
|
111
|
+
props: {
|
|
112
|
+
locale: { default: () => y }
|
|
113
|
+
},
|
|
114
|
+
setup(e) {
|
|
115
|
+
return W(e.locale), (o, n) => i(o.$slots, "default");
|
|
116
|
+
}
|
|
117
|
+
}), ee = /* @__PURE__ */ c({
|
|
118
|
+
__name: "NsInput",
|
|
119
|
+
props: {
|
|
120
|
+
label: { default: void 0 },
|
|
121
|
+
modelValue: { default: void 0 },
|
|
122
|
+
outlined: { type: Boolean, default: !0 },
|
|
123
|
+
dense: { type: Boolean, default: !1 },
|
|
124
|
+
rules: { default: void 0 }
|
|
125
|
+
},
|
|
126
|
+
emits: ["update:modelValue"],
|
|
127
|
+
setup(e) {
|
|
128
|
+
return (t, o) => (s(), d(Z, p(t.$attrs, {
|
|
129
|
+
"model-value": e.modelValue,
|
|
130
|
+
label: e.label,
|
|
131
|
+
outlined: e.outlined,
|
|
132
|
+
dense: e.dense,
|
|
133
|
+
rules: e.rules,
|
|
134
|
+
class: "ns-input",
|
|
135
|
+
"onUpdate:modelValue": o[0] || (o[0] = (n) => t.$emit("update:modelValue", n))
|
|
136
|
+
}), z({ _: 2 }, [
|
|
137
|
+
R(t.$slots, (n, r) => ({
|
|
138
|
+
name: r,
|
|
139
|
+
fn: u((l) => [
|
|
140
|
+
i(t.$slots, r, D(M(l ?? {})), void 0, !0)
|
|
141
|
+
])
|
|
142
|
+
}))
|
|
143
|
+
]), 1040, ["model-value", "label", "outlined", "dense", "rules"]));
|
|
144
|
+
}
|
|
145
|
+
}), ve = /* @__PURE__ */ g(ee, [["__scopeId", "data-v-7ebf3284"]]), te = { class: "text-h6" }, oe = {
|
|
146
|
+
key: 0,
|
|
147
|
+
class: "text-subtitle2 text-grey"
|
|
148
|
+
}, ne = /* @__PURE__ */ c({
|
|
149
|
+
__name: "NsCard",
|
|
150
|
+
props: {
|
|
151
|
+
title: { default: void 0 },
|
|
152
|
+
subtitle: { default: void 0 },
|
|
153
|
+
flat: { type: Boolean, default: !1 }
|
|
154
|
+
},
|
|
155
|
+
setup(e) {
|
|
156
|
+
return (t, o) => (s(), d(H, p(t.$attrs, {
|
|
157
|
+
class: ["ns-card", { "ns-card--flat": e.flat }]
|
|
158
|
+
}), {
|
|
159
|
+
default: u(() => [
|
|
160
|
+
e.title || t.$slots.header ? (s(), d($, {
|
|
161
|
+
key: 0,
|
|
162
|
+
class: "ns-card__header"
|
|
163
|
+
}, {
|
|
164
|
+
default: u(() => [
|
|
165
|
+
i(t.$slots, "header", {}, () => [
|
|
166
|
+
O("div", te, w(e.title), 1),
|
|
167
|
+
e.subtitle ? (s(), F("div", oe, w(e.subtitle), 1)) : v("", !0)
|
|
168
|
+
], !0)
|
|
169
|
+
]),
|
|
170
|
+
_: 3
|
|
171
|
+
})) : v("", !0),
|
|
172
|
+
B($, null, {
|
|
173
|
+
default: u(() => [
|
|
174
|
+
i(t.$slots, "default", {}, void 0, !0)
|
|
175
|
+
]),
|
|
176
|
+
_: 3
|
|
177
|
+
}),
|
|
178
|
+
t.$slots.actions ? (s(), d(G, {
|
|
179
|
+
key: 1,
|
|
180
|
+
align: "right"
|
|
181
|
+
}, {
|
|
182
|
+
default: u(() => [
|
|
183
|
+
i(t.$slots, "actions", {}, void 0, !0)
|
|
184
|
+
]),
|
|
185
|
+
_: 3
|
|
186
|
+
})) : v("", !0)
|
|
187
|
+
]),
|
|
188
|
+
_: 3
|
|
189
|
+
}, 16, ["class"]));
|
|
190
|
+
}
|
|
191
|
+
}), he = /* @__PURE__ */ g(ne, [["__scopeId", "data-v-41ecea50"]]);
|
|
192
|
+
function ye(e = {}) {
|
|
193
|
+
const { locale: t = y } = e;
|
|
194
|
+
return {
|
|
195
|
+
install(o) {
|
|
196
|
+
o.provide(S, t);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const re = {
|
|
201
|
+
primary: "#3b82f6",
|
|
202
|
+
// PLACEHOLDER — matches --ns-color-primary
|
|
203
|
+
secondary: "#8b5cf6",
|
|
204
|
+
// PLACEHOLDER — matches --ns-color-secondary
|
|
205
|
+
accent: "#f59e0b",
|
|
206
|
+
// PLACEHOLDER — matches --ns-color-accent
|
|
207
|
+
dark: "#1e293b",
|
|
208
|
+
// PLACEHOLDER — matches --ns-color-neutral-800
|
|
209
|
+
"dark-page": "#0f172a",
|
|
210
|
+
// PLACEHOLDER — matches --ns-color-neutral-900
|
|
211
|
+
positive: "#22c55e",
|
|
212
|
+
// PLACEHOLDER — matches --ns-color-success
|
|
213
|
+
negative: "#ef4444",
|
|
214
|
+
// PLACEHOLDER — matches --ns-color-error
|
|
215
|
+
info: "#3b82f6",
|
|
216
|
+
// PLACEHOLDER — matches --ns-color-info
|
|
217
|
+
warning: "#f59e0b"
|
|
218
|
+
// PLACEHOLDER — matches --ns-color-warning
|
|
219
|
+
};
|
|
220
|
+
function Se(e = {}) {
|
|
221
|
+
const { brand: t = {}, plugins: o = {}, ...n } = e;
|
|
222
|
+
return {
|
|
223
|
+
config: {
|
|
224
|
+
brand: {
|
|
225
|
+
...re,
|
|
226
|
+
...t
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
plugins: o,
|
|
230
|
+
...n
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
const ke = {
|
|
99
234
|
common: {
|
|
100
235
|
loading: "Chargement…",
|
|
101
236
|
retry: "Réessayer",
|
|
@@ -131,32 +266,89 @@ const B = /* @__PURE__ */ s({
|
|
|
131
266
|
tooShort: "Trop court",
|
|
132
267
|
tooLong: "Trop long"
|
|
133
268
|
}
|
|
134
|
-
}
|
|
135
|
-
function
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
function q() {
|
|
139
|
-
return S(f, N);
|
|
140
|
-
}
|
|
141
|
-
function O(e, o) {
|
|
142
|
-
const t = q();
|
|
143
|
-
return k(() => {
|
|
269
|
+
};
|
|
270
|
+
function be(e, t) {
|
|
271
|
+
const o = X();
|
|
272
|
+
return _(() => {
|
|
144
273
|
const n = e();
|
|
145
274
|
if (n != null) return n;
|
|
146
|
-
const r =
|
|
147
|
-
let
|
|
148
|
-
for (const
|
|
149
|
-
|
|
150
|
-
return
|
|
275
|
+
const r = t.split(".");
|
|
276
|
+
let l = o;
|
|
277
|
+
for (const f of r)
|
|
278
|
+
l = l[f];
|
|
279
|
+
return l;
|
|
151
280
|
});
|
|
152
281
|
}
|
|
282
|
+
const h = "ns-dark-mode";
|
|
283
|
+
function Ne() {
|
|
284
|
+
const e = C(!1), t = C("system");
|
|
285
|
+
let o = null, n = null;
|
|
286
|
+
function r(a) {
|
|
287
|
+
if (e.value = a, typeof document < "u") {
|
|
288
|
+
const m = document.documentElement;
|
|
289
|
+
m.classList.toggle("dark", a), m.setAttribute("data-theme", a ? "dark" : "light");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function l() {
|
|
293
|
+
return typeof window > "u" ? !1 : window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
294
|
+
}
|
|
295
|
+
function f() {
|
|
296
|
+
if (typeof localStorage > "u") return null;
|
|
297
|
+
const a = localStorage.getItem(h);
|
|
298
|
+
return a === "true" ? !0 : a === "false" ? !1 : null;
|
|
299
|
+
}
|
|
300
|
+
function k(a) {
|
|
301
|
+
typeof localStorage < "u" && localStorage.setItem(h, String(a));
|
|
302
|
+
}
|
|
303
|
+
function E() {
|
|
304
|
+
typeof localStorage < "u" && localStorage.removeItem(h);
|
|
305
|
+
}
|
|
306
|
+
function b() {
|
|
307
|
+
t.value = "user", k(!0), r(!0);
|
|
308
|
+
}
|
|
309
|
+
function N() {
|
|
310
|
+
t.value = "user", k(!1), r(!1);
|
|
311
|
+
}
|
|
312
|
+
function L() {
|
|
313
|
+
e.value ? N() : b();
|
|
314
|
+
}
|
|
315
|
+
function A() {
|
|
316
|
+
E(), t.value = "system", r(l());
|
|
317
|
+
}
|
|
318
|
+
function P() {
|
|
319
|
+
const a = f();
|
|
320
|
+
a !== null ? (t.value = "storage", r(a)) : (t.value = "system", r(l())), typeof window < "u" && (o = window.matchMedia("(prefers-color-scheme: dark)"), n = (m) => {
|
|
321
|
+
f() === null && (t.value = "system", r(m.matches));
|
|
322
|
+
}, o.addEventListener("change", n));
|
|
323
|
+
}
|
|
324
|
+
return x(P), j(() => {
|
|
325
|
+
o && n && o.removeEventListener("change", n);
|
|
326
|
+
}), {
|
|
327
|
+
isDark: I(e),
|
|
328
|
+
source: I(t),
|
|
329
|
+
enable: b,
|
|
330
|
+
disable: N,
|
|
331
|
+
toggle: L,
|
|
332
|
+
useSystem: A
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function we(e, t = document.documentElement) {
|
|
336
|
+
return getComputedStyle(t).getPropertyValue(e).trim();
|
|
337
|
+
}
|
|
153
338
|
export {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
339
|
+
me as NsButton,
|
|
340
|
+
he as NsCard,
|
|
341
|
+
ve as NsInput,
|
|
342
|
+
S as NsLocaleKey,
|
|
343
|
+
pe as NsSkeleton,
|
|
344
|
+
ge as NsThemeProvider,
|
|
345
|
+
ye as createNonsuch,
|
|
346
|
+
Se as createQuasarConfig,
|
|
347
|
+
we as getToken,
|
|
348
|
+
y as nsLocaleEnCA,
|
|
349
|
+
ke as nsLocaleFrCA,
|
|
350
|
+
W as provideNsLocale,
|
|
351
|
+
Ne as useNsDarkMode,
|
|
352
|
+
be as useNsDefault,
|
|
353
|
+
X as useNsLocale
|
|
162
354
|
};
|
package/fonts/global.css
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
/* Apply Fixel Text as the default body font */
|
|
16
16
|
body {
|
|
17
|
-
font-family: 'Fixel Text', 'Roboto', sans-serif;
|
|
17
|
+
font-family: var(--ns-font-family-text, 'Fixel Text', 'Roboto', sans-serif);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/* Apply Fixel Display to headings */
|
|
@@ -30,5 +30,5 @@ h6,
|
|
|
30
30
|
.text-h4,
|
|
31
31
|
.text-h5,
|
|
32
32
|
.text-h6 {
|
|
33
|
-
font-family: 'Fixel Display', 'Roboto', sans-serif;
|
|
33
|
+
font-family: var(--ns-font-family-display, 'Fixel Display', 'Roboto', sans-serif);
|
|
34
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nonsuch/component-library",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A Vue 3 component library built on Quasar with opinionated defaults and custom components.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
14
|
-
"fonts"
|
|
14
|
+
"fonts",
|
|
15
|
+
"src/tokens/tokens.css"
|
|
15
16
|
],
|
|
16
17
|
"main": "./dist/nonsuch-components.js",
|
|
17
18
|
"module": "./dist/nonsuch-components.js",
|
|
@@ -24,7 +25,8 @@
|
|
|
24
25
|
"./style.css": "./dist/style.css",
|
|
25
26
|
"./fonts.css": "./fonts/fonts.css",
|
|
26
27
|
"./fonts/global.css": "./fonts/global.css",
|
|
27
|
-
"./fonts/quasar-overrides": "./fonts/_quasar-overrides.sass"
|
|
28
|
+
"./fonts/quasar-overrides": "./fonts/_quasar-overrides.sass",
|
|
29
|
+
"./tokens.css": "./src/tokens/tokens.css"
|
|
28
30
|
},
|
|
29
31
|
"scripts": {
|
|
30
32
|
"dev": "storybook dev -p 6006",
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Nonsuch Design Tokens
|
|
3
|
+
*
|
|
4
|
+
* CSS custom properties for the Nonsuch component library.
|
|
5
|
+
* All tokens use the `--ns-` prefix to avoid collisions with
|
|
6
|
+
* Quasar's `--q-` namespace and app-level variables.
|
|
7
|
+
*
|
|
8
|
+
* Import in your app:
|
|
9
|
+
* import '@nonsuch/component-library/tokens.css'
|
|
10
|
+
*
|
|
11
|
+
* Current values are PLACEHOLDERS — they will be updated
|
|
12
|
+
* when brand designs are finalised. Token *names* are stable.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/* --------------------------------------------------------
|
|
16
|
+
* LIGHT MODE (default)
|
|
17
|
+
* ------------------------------------------------------ */
|
|
18
|
+
:root {
|
|
19
|
+
/* — Brand colours — */
|
|
20
|
+
--ns-color-primary: #3b82f6; /* PLACEHOLDER */
|
|
21
|
+
--ns-color-primary-hover: #2563eb; /* PLACEHOLDER */
|
|
22
|
+
--ns-color-secondary: #8b5cf6; /* PLACEHOLDER */
|
|
23
|
+
--ns-color-secondary-hover: #7c3aed; /* PLACEHOLDER */
|
|
24
|
+
--ns-color-accent: #f59e0b; /* PLACEHOLDER */
|
|
25
|
+
--ns-color-accent-hover: #d97706; /* PLACEHOLDER */
|
|
26
|
+
|
|
27
|
+
/* — Semantic colours — */
|
|
28
|
+
--ns-color-success: #22c55e; /* PLACEHOLDER */
|
|
29
|
+
--ns-color-warning: #f59e0b; /* PLACEHOLDER */
|
|
30
|
+
--ns-color-error: #ef4444; /* PLACEHOLDER */
|
|
31
|
+
--ns-color-info: #3b82f6; /* PLACEHOLDER */
|
|
32
|
+
|
|
33
|
+
/* — Surface / background — */
|
|
34
|
+
--ns-color-background: #ffffff; /* PLACEHOLDER */
|
|
35
|
+
--ns-color-surface: #ffffff; /* PLACEHOLDER */
|
|
36
|
+
--ns-color-surface-variant: #f8fafc; /* PLACEHOLDER */
|
|
37
|
+
|
|
38
|
+
/* — On-colours (text/icons on top of the corresponding colour) — */
|
|
39
|
+
--ns-color-on-primary: #ffffff; /* PLACEHOLDER */
|
|
40
|
+
--ns-color-on-secondary: #ffffff; /* PLACEHOLDER */
|
|
41
|
+
--ns-color-on-accent: #000000; /* PLACEHOLDER */
|
|
42
|
+
--ns-color-on-background: #0f172a; /* PLACEHOLDER */
|
|
43
|
+
--ns-color-on-surface: #0f172a; /* PLACEHOLDER */
|
|
44
|
+
|
|
45
|
+
/* — Neutral scale — */
|
|
46
|
+
--ns-color-neutral-50: #f8fafc; /* PLACEHOLDER */
|
|
47
|
+
--ns-color-neutral-100: #f1f5f9; /* PLACEHOLDER */
|
|
48
|
+
--ns-color-neutral-200: #e2e8f0; /* PLACEHOLDER */
|
|
49
|
+
--ns-color-neutral-300: #cbd5e1; /* PLACEHOLDER */
|
|
50
|
+
--ns-color-neutral-400: #94a3b8; /* PLACEHOLDER */
|
|
51
|
+
--ns-color-neutral-500: #64748b; /* PLACEHOLDER */
|
|
52
|
+
--ns-color-neutral-600: #475569; /* PLACEHOLDER */
|
|
53
|
+
--ns-color-neutral-700: #334155; /* PLACEHOLDER */
|
|
54
|
+
--ns-color-neutral-800: #1e293b; /* PLACEHOLDER */
|
|
55
|
+
--ns-color-neutral-900: #0f172a; /* PLACEHOLDER */
|
|
56
|
+
|
|
57
|
+
/* — Typography — */
|
|
58
|
+
--ns-font-family-text: 'Fixel Text', 'Roboto', sans-serif; /* PLACEHOLDER */
|
|
59
|
+
--ns-font-family-display: 'Fixel Display', 'Roboto', sans-serif; /* PLACEHOLDER */
|
|
60
|
+
|
|
61
|
+
--ns-font-size-xs: 0.75rem; /* 12px — PLACEHOLDER */
|
|
62
|
+
--ns-font-size-sm: 0.875rem; /* 14px — PLACEHOLDER */
|
|
63
|
+
--ns-font-size-md: 1rem; /* 16px — PLACEHOLDER */
|
|
64
|
+
--ns-font-size-lg: 1.125rem; /* 18px — PLACEHOLDER */
|
|
65
|
+
--ns-font-size-xl: 1.25rem; /* 20px — PLACEHOLDER */
|
|
66
|
+
--ns-font-size-2xl: 1.5rem; /* 24px — PLACEHOLDER */
|
|
67
|
+
--ns-font-size-3xl: 1.875rem; /* 30px — PLACEHOLDER */
|
|
68
|
+
|
|
69
|
+
--ns-font-weight-regular: 400; /* PLACEHOLDER */
|
|
70
|
+
--ns-font-weight-medium: 500; /* PLACEHOLDER */
|
|
71
|
+
--ns-font-weight-semibold: 600; /* PLACEHOLDER */
|
|
72
|
+
--ns-font-weight-bold: 700; /* PLACEHOLDER */
|
|
73
|
+
|
|
74
|
+
--ns-line-height-tight: 1.25; /* PLACEHOLDER */
|
|
75
|
+
--ns-line-height-normal: 1.5; /* PLACEHOLDER */
|
|
76
|
+
--ns-line-height-relaxed: 1.75; /* PLACEHOLDER */
|
|
77
|
+
|
|
78
|
+
--ns-letter-spacing-tight: -0.01em; /* PLACEHOLDER */
|
|
79
|
+
--ns-letter-spacing-normal: 0; /* PLACEHOLDER */
|
|
80
|
+
--ns-letter-spacing-wide: 0.02em; /* PLACEHOLDER */
|
|
81
|
+
|
|
82
|
+
/* — Spacing (4px grid) — */
|
|
83
|
+
--ns-space-1: 0.25rem; /* 4px */
|
|
84
|
+
--ns-space-2: 0.5rem; /* 8px */
|
|
85
|
+
--ns-space-3: 0.75rem; /* 12px */
|
|
86
|
+
--ns-space-4: 1rem; /* 16px */
|
|
87
|
+
--ns-space-5: 1.25rem; /* 20px */
|
|
88
|
+
--ns-space-6: 1.5rem; /* 24px */
|
|
89
|
+
--ns-space-8: 2rem; /* 32px */
|
|
90
|
+
--ns-space-10: 2.5rem; /* 40px */
|
|
91
|
+
--ns-space-12: 3rem; /* 48px */
|
|
92
|
+
--ns-space-16: 4rem; /* 64px */
|
|
93
|
+
|
|
94
|
+
/* — Border radius — */
|
|
95
|
+
--ns-radius-none: 0;
|
|
96
|
+
--ns-radius-sm: 0.25rem; /* 4px — PLACEHOLDER */
|
|
97
|
+
--ns-radius-md: 0.5rem; /* 8px — PLACEHOLDER */
|
|
98
|
+
--ns-radius-lg: 0.75rem; /* 12px — PLACEHOLDER */
|
|
99
|
+
--ns-radius-xl: 1rem; /* 16px — PLACEHOLDER */
|
|
100
|
+
--ns-radius-full: 9999px;
|
|
101
|
+
|
|
102
|
+
/* — Shadows / elevation — */
|
|
103
|
+
--ns-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); /* PLACEHOLDER */
|
|
104
|
+
--ns-shadow-md:
|
|
105
|
+
0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); /* PLACEHOLDER */
|
|
106
|
+
--ns-shadow-lg:
|
|
107
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); /* PLACEHOLDER */
|
|
108
|
+
--ns-shadow-xl:
|
|
109
|
+
0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); /* PLACEHOLDER */
|
|
110
|
+
|
|
111
|
+
/* — Motion / transitions — */
|
|
112
|
+
--ns-duration-fast: 100ms; /* PLACEHOLDER */
|
|
113
|
+
--ns-duration-normal: 200ms; /* PLACEHOLDER */
|
|
114
|
+
--ns-duration-slow: 400ms; /* PLACEHOLDER */
|
|
115
|
+
|
|
116
|
+
--ns-easing-default: cubic-bezier(0.4, 0, 0.2, 1); /* PLACEHOLDER */
|
|
117
|
+
--ns-easing-in: cubic-bezier(0.4, 0, 1, 1); /* PLACEHOLDER */
|
|
118
|
+
--ns-easing-out: cubic-bezier(0, 0, 0.2, 1); /* PLACEHOLDER */
|
|
119
|
+
--ns-easing-in-out: cubic-bezier(0.4, 0, 0.2, 1); /* PLACEHOLDER */
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* --------------------------------------------------------
|
|
123
|
+
* DARK MODE
|
|
124
|
+
*
|
|
125
|
+
* Activated by any of:
|
|
126
|
+
* <html class="dark">
|
|
127
|
+
* <html data-theme="dark">
|
|
128
|
+
* OS-level prefers-color-scheme: dark
|
|
129
|
+
*
|
|
130
|
+
* Only colour tokens change — typography, spacing, radius,
|
|
131
|
+
* and motion are shared between modes.
|
|
132
|
+
* ------------------------------------------------------ */
|
|
133
|
+
:root.dark,
|
|
134
|
+
[data-theme='dark'],
|
|
135
|
+
.q-dark {
|
|
136
|
+
/* — Brand colours (dark) — */
|
|
137
|
+
--ns-color-primary: #60a5fa; /* PLACEHOLDER */
|
|
138
|
+
--ns-color-primary-hover: #93c5fd; /* PLACEHOLDER */
|
|
139
|
+
--ns-color-secondary: #a78bfa; /* PLACEHOLDER */
|
|
140
|
+
--ns-color-secondary-hover: #c4b5fd; /* PLACEHOLDER */
|
|
141
|
+
--ns-color-accent: #fbbf24; /* PLACEHOLDER */
|
|
142
|
+
--ns-color-accent-hover: #fcd34d; /* PLACEHOLDER */
|
|
143
|
+
|
|
144
|
+
/* — Semantic colours (dark) — */
|
|
145
|
+
--ns-color-success: #4ade80; /* PLACEHOLDER */
|
|
146
|
+
--ns-color-warning: #fbbf24; /* PLACEHOLDER */
|
|
147
|
+
--ns-color-error: #f87171; /* PLACEHOLDER */
|
|
148
|
+
--ns-color-info: #60a5fa; /* PLACEHOLDER */
|
|
149
|
+
|
|
150
|
+
/* — Surface / background (dark) — */
|
|
151
|
+
--ns-color-background: #0f172a; /* PLACEHOLDER */
|
|
152
|
+
--ns-color-surface: #1e293b; /* PLACEHOLDER */
|
|
153
|
+
--ns-color-surface-variant: #334155; /* PLACEHOLDER */
|
|
154
|
+
|
|
155
|
+
/* — On-colours (dark) — */
|
|
156
|
+
--ns-color-on-primary: #0f172a; /* PLACEHOLDER */
|
|
157
|
+
--ns-color-on-secondary: #0f172a; /* PLACEHOLDER */
|
|
158
|
+
--ns-color-on-accent: #0f172a; /* PLACEHOLDER */
|
|
159
|
+
--ns-color-on-background: #f1f5f9; /* PLACEHOLDER */
|
|
160
|
+
--ns-color-on-surface: #f1f5f9; /* PLACEHOLDER */
|
|
161
|
+
|
|
162
|
+
/* — Neutral scale (dark — inverted) — */
|
|
163
|
+
--ns-color-neutral-50: #0f172a; /* PLACEHOLDER */
|
|
164
|
+
--ns-color-neutral-100: #1e293b; /* PLACEHOLDER */
|
|
165
|
+
--ns-color-neutral-200: #334155; /* PLACEHOLDER */
|
|
166
|
+
--ns-color-neutral-300: #475569; /* PLACEHOLDER */
|
|
167
|
+
--ns-color-neutral-400: #64748b; /* PLACEHOLDER */
|
|
168
|
+
--ns-color-neutral-500: #94a3b8; /* PLACEHOLDER */
|
|
169
|
+
--ns-color-neutral-600: #cbd5e1; /* PLACEHOLDER */
|
|
170
|
+
--ns-color-neutral-700: #e2e8f0; /* PLACEHOLDER */
|
|
171
|
+
--ns-color-neutral-800: #f1f5f9; /* PLACEHOLDER */
|
|
172
|
+
--ns-color-neutral-900: #f8fafc; /* PLACEHOLDER */
|
|
173
|
+
|
|
174
|
+
/* — Shadows (dark — lighter opacity looks better on dark bg) — */
|
|
175
|
+
--ns-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.3); /* PLACEHOLDER */
|
|
176
|
+
--ns-shadow-md:
|
|
177
|
+
0 4px 6px -1px rgb(0 0 0 / 0.4), 0 2px 4px -2px rgb(0 0 0 / 0.3); /* PLACEHOLDER */
|
|
178
|
+
--ns-shadow-lg:
|
|
179
|
+
0 10px 15px -3px rgb(0 0 0 / 0.4), 0 4px 6px -4px rgb(0 0 0 / 0.3); /* PLACEHOLDER */
|
|
180
|
+
--ns-shadow-xl:
|
|
181
|
+
0 20px 25px -5px rgb(0 0 0 / 0.4), 0 8px 10px -6px rgb(0 0 0 / 0.3); /* PLACEHOLDER */
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* --------------------------------------------------------
|
|
185
|
+
* prefers-color-scheme fallback
|
|
186
|
+
*
|
|
187
|
+
* Applies dark tokens when the OS is in dark mode and
|
|
188
|
+
* no explicit class/attribute override is set.
|
|
189
|
+
* ------------------------------------------------------ */
|
|
190
|
+
@media (prefers-color-scheme: dark) {
|
|
191
|
+
:root:not([data-theme='light']):not(.light) {
|
|
192
|
+
/* — Brand colours (dark) — */
|
|
193
|
+
--ns-color-primary: #60a5fa;
|
|
194
|
+
--ns-color-primary-hover: #93c5fd;
|
|
195
|
+
--ns-color-secondary: #a78bfa;
|
|
196
|
+
--ns-color-secondary-hover: #c4b5fd;
|
|
197
|
+
--ns-color-accent: #fbbf24;
|
|
198
|
+
--ns-color-accent-hover: #fcd34d;
|
|
199
|
+
|
|
200
|
+
/* — Semantic colours (dark) — */
|
|
201
|
+
--ns-color-success: #4ade80;
|
|
202
|
+
--ns-color-warning: #fbbf24;
|
|
203
|
+
--ns-color-error: #f87171;
|
|
204
|
+
--ns-color-info: #60a5fa;
|
|
205
|
+
|
|
206
|
+
/* — Surface / background (dark) — */
|
|
207
|
+
--ns-color-background: #0f172a;
|
|
208
|
+
--ns-color-surface: #1e293b;
|
|
209
|
+
--ns-color-surface-variant: #334155;
|
|
210
|
+
|
|
211
|
+
/* — On-colours (dark) — */
|
|
212
|
+
--ns-color-on-primary: #0f172a;
|
|
213
|
+
--ns-color-on-secondary: #0f172a;
|
|
214
|
+
--ns-color-on-accent: #0f172a;
|
|
215
|
+
--ns-color-on-background: #f1f5f9;
|
|
216
|
+
--ns-color-on-surface: #f1f5f9;
|
|
217
|
+
|
|
218
|
+
/* — Neutral scale (dark — inverted) — */
|
|
219
|
+
--ns-color-neutral-50: #0f172a;
|
|
220
|
+
--ns-color-neutral-100: #1e293b;
|
|
221
|
+
--ns-color-neutral-200: #334155;
|
|
222
|
+
--ns-color-neutral-300: #475569;
|
|
223
|
+
--ns-color-neutral-400: #64748b;
|
|
224
|
+
--ns-color-neutral-500: #94a3b8;
|
|
225
|
+
--ns-color-neutral-600: #cbd5e1;
|
|
226
|
+
--ns-color-neutral-700: #e2e8f0;
|
|
227
|
+
--ns-color-neutral-800: #f1f5f9;
|
|
228
|
+
--ns-color-neutral-900: #f8fafc;
|
|
229
|
+
|
|
230
|
+
/* — Shadows (dark) — */
|
|
231
|
+
--ns-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.3);
|
|
232
|
+
--ns-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.4), 0 2px 4px -2px rgb(0 0 0 / 0.3);
|
|
233
|
+
--ns-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.4), 0 4px 6px -4px rgb(0 0 0 / 0.3);
|
|
234
|
+
--ns-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.4), 0 8px 10px -6px rgb(0 0 0 / 0.3);
|
|
235
|
+
}
|
|
236
|
+
}
|