@happyvertical/smrt-template-sveltekit 0.38.2 → 0.38.4
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 +2 -2
- package/template/README.md +82 -1
- package/template/package.json +7 -5
- package/template/src/routes/+layout.server.ts +69 -0
- package/template/src/routes/+layout.svelte +110 -0
- package/template/src/routes/+page.svelte +10 -3
- package/template/src/routes/settings/+page.svelte +41 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-template-sveltekit",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.4",
|
|
4
4
|
"description": "SvelteKit project template with SMRT framework integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"directory": "packages/template-sveltekit"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@happyvertical/smrt-core": "0.38.
|
|
32
|
+
"@happyvertical/smrt-core": "0.38.4"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"vitest": "^4.1.9"
|
package/template/README.md
CHANGED
|
@@ -39,8 +39,11 @@ A SvelteKit application with SMRT framework integration for rapid development of
|
|
|
39
39
|
│ │ └── tenancy.ts # Pluggable tenant resolver
|
|
40
40
|
│ └── routes/
|
|
41
41
|
│ ├── api/ # Auto-generated API routes (don't edit!)
|
|
42
|
+
│ ├── +layout.server.ts # Builds AdminShell tenant nav server-side (manifest → nav)
|
|
43
|
+
│ ├── +layout.svelte # WASD AdminShell chrome wrapping every page
|
|
44
|
+
│ ├── settings/ # ShellSettingsPanel (panel layout + hotkeys)
|
|
42
45
|
│ ├── +page.server.ts # Home page server load + demo mutation (reference pattern)
|
|
43
|
-
│ └── +page.svelte # Home page
|
|
46
|
+
│ └── +page.svelte # Home page (renders inside AdminShell)
|
|
44
47
|
├── smrt.config.ts # Root SMRT config
|
|
45
48
|
├── vite.config.ts # Vite + SMRT plugin config
|
|
46
49
|
└── svelte.config.js # SvelteKit config
|
|
@@ -226,6 +229,84 @@ same REST route segment as `depends`/`invalidate`). Add
|
|
|
226
229
|
`@happyvertical/smrt-web` and `@happyvertical/smrt-svelte` to the project's
|
|
227
230
|
dependencies before using this pattern.
|
|
228
231
|
|
|
232
|
+
## Workspace shell (AdminShell)
|
|
233
|
+
|
|
234
|
+
This template renders every page inside the **WASD AdminShell** — a four-edge
|
|
235
|
+
admin layout from `@happyvertical/smrt-svelte/workspace`. Each edge is a scope
|
|
236
|
+
(top = app, left = tenant, right = focus, bottom = system) toggled with
|
|
237
|
+
<kbd>W</kbd>/<kbd>A</kbd>/<kbd>S</kbd>/<kbd>D</kbd> (press <kbd>?</kbd> for the
|
|
238
|
+
shortcuts). It is wired in the root layout:
|
|
239
|
+
|
|
240
|
+
- `src/routes/+layout.server.ts` builds the left "tenant" nav **server-side**
|
|
241
|
+
with `tenantNavFromManifest()` from the SMRT manifest (`.smrt/manifest.json`)
|
|
242
|
+
and returns it as layout data — no client-side nav fetch.
|
|
243
|
+
- `src/routes/+layout.svelte` wraps `{@render children()}` in `<AdminShell>`
|
|
244
|
+
(inside `<ThemeProvider>` — see **Theming** below), feeding that nav to
|
|
245
|
+
`<TenantNav>`, a brand/app panel on top, and a couple of status chips on the
|
|
246
|
+
bottom.
|
|
247
|
+
- `src/routes/settings/+page.svelte` drops in `<ShellSettingsPanel>` so users
|
|
248
|
+
can toggle panels and remap the hotkeys; the choices persist in
|
|
249
|
+
`localStorage` under the shell's `storageKey`.
|
|
250
|
+
|
|
251
|
+
**The shell preserves the server-load pattern above.** AdminShell's public core
|
|
252
|
+
is SSR-safe: it renders statically on the server and only activates hotkeys /
|
|
253
|
+
`localStorage` after mount. The active page still renders inside the shell's
|
|
254
|
+
`<main>` and keeps its own `+page.server.ts` load and `invalidate()` refresh —
|
|
255
|
+
the shell is chrome around the page, not a replacement for its data flow. The
|
|
256
|
+
home page's `depends('smrt:items')` / `invalidate('smrt:items')` cycle works
|
|
257
|
+
unchanged.
|
|
258
|
+
|
|
259
|
+
### Theming
|
|
260
|
+
|
|
261
|
+
The layout wraps the shell in **`<ThemeProvider>`** from
|
|
262
|
+
`@happyvertical/smrt-ui/themes` — the standard SMRT theming wrapper (the same
|
|
263
|
+
pattern the reference `@happyvertical/smrt-content` app uses):
|
|
264
|
+
|
|
265
|
+
```svelte
|
|
266
|
+
<script lang="ts">
|
|
267
|
+
import { ThemeProvider } from '@happyvertical/smrt-ui/themes';
|
|
268
|
+
// @font-face rules for the SMRT type stack (Space Grotesk / Inter /
|
|
269
|
+
// JetBrains Mono woff2). ThemeProvider supplies the token *variables*;
|
|
270
|
+
// this loads the font *files*. Bundled — no CDN request.
|
|
271
|
+
import '@happyvertical/smrt-ui/themes/styles/fonts.css';
|
|
272
|
+
</script>
|
|
273
|
+
|
|
274
|
+
<ThemeProvider colorScheme="system" persist={true}>
|
|
275
|
+
<!-- AdminShell + every page render themed inside here -->
|
|
276
|
+
</ThemeProvider>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
- ThemeProvider injects the **entire `--smrt-*` token set** (colors, typography,
|
|
280
|
+
spacing, radius, elevation, motion, z-index) as an inline style it computes
|
|
281
|
+
during render — so the tokens are present in the SSR HTML with **no unstyled
|
|
282
|
+
flash**, and it re-resolves them on the client. You do **not** need to import
|
|
283
|
+
`styles/tokens.css` or `themes/styles/*.css` separately; the provider is the
|
|
284
|
+
runtime source of truth.
|
|
285
|
+
- `colorScheme="system"` follows the OS light/dark preference; `persist` saves a
|
|
286
|
+
user's explicit switch to `localStorage`. Switch presets/scheme at runtime
|
|
287
|
+
with `ThemeSwitcher` / `ColorSchemeToggle` (also from `.../themes`), or read
|
|
288
|
+
the current theme via the theme context.
|
|
289
|
+
- The one thing the provider does not carry is the font **files** — hence the
|
|
290
|
+
`themes/styles/fonts.css` import above. Drop it and the type stack degrades to
|
|
291
|
+
`system-ui` / `ui-monospace` automatically.
|
|
292
|
+
|
|
293
|
+
To pin a specific look instead of following the OS, set
|
|
294
|
+
`colorScheme="light"` (or `"dark"`) and `preset="material"` (or `"glass"` /
|
|
295
|
+
`"studio"` / `"smrt"`).
|
|
296
|
+
|
|
297
|
+
The status chips ship static (`Local`, `Ready`). To make them (and the focus
|
|
298
|
+
edge) live — job counts, dispatch depth, connection state — feed real values
|
|
299
|
+
through `systemFeed` (`@happyvertical/smrt-svelte/workspace/live`) or
|
|
300
|
+
`activityFeed` (`@happyvertical/smrt-svelte/web`).
|
|
301
|
+
|
|
302
|
+
- **Migration guide** (old `WorkspaceShell`/`RoleShell` → `AdminShell`, and why
|
|
303
|
+
adoption is additive):
|
|
304
|
+
[`@happyvertical/smrt-svelte` → `src/components/workspace/MIGRATION.md`](https://github.com/happyvertical/smrt/blob/main/packages/smrt-svelte/src/components/workspace/MIGRATION.md)
|
|
305
|
+
- **Four-scope demo** (all edges, focus tools, activities) and the live-feed
|
|
306
|
+
variants, in the smrt-svelte playground:
|
|
307
|
+
`playground/src/routes/admin-shell`, `admin-shell-activity-feed`, and
|
|
308
|
+
`admin-shell-system-feed`.
|
|
309
|
+
|
|
229
310
|
## Multi-tenancy
|
|
230
311
|
|
|
231
312
|
This template ships with multi-tenancy pre-wired. Out of the box you get:
|
package/template/package.json
CHANGED
|
@@ -12,16 +12,18 @@
|
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@sveltejs/adapter-auto": "^7.0.1",
|
|
15
|
-
"@sveltejs/kit": "^2.
|
|
15
|
+
"@sveltejs/kit": "^2.69.1",
|
|
16
16
|
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
17
17
|
"svelte": "^5.56.4",
|
|
18
18
|
"svelte-check": "^4.7.1",
|
|
19
19
|
"typescript": "^5.9.3",
|
|
20
|
-
"vite": "^8.1.
|
|
20
|
+
"vite": "^8.1.3"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@happyvertical/smrt-core": "^0.38.
|
|
24
|
-
"@happyvertical/smrt-
|
|
25
|
-
"@happyvertical/smrt-
|
|
23
|
+
"@happyvertical/smrt-core": "^0.38.4",
|
|
24
|
+
"@happyvertical/smrt-svelte": "^0.38.4",
|
|
25
|
+
"@happyvertical/smrt-tenancy": "^0.38.4",
|
|
26
|
+
"@happyvertical/smrt-ui": "^0.38.4",
|
|
27
|
+
"@happyvertical/smrt-users": "^0.38.4"
|
|
26
28
|
}
|
|
27
29
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Root layout server load — builds the AdminShell tenant navigation.
|
|
3
|
+
*
|
|
4
|
+
* The WASD AdminShell (`src/routes/+layout.svelte`) is the default chrome for
|
|
5
|
+
* this app. Its left "tenant" rail is driven by a nav tree derived from the
|
|
6
|
+
* SMRT manifest, and that tree is built HERE — server-side — rather than with a
|
|
7
|
+
* client-side fetch. This mirrors the home page's data pattern
|
|
8
|
+
* (`+page.server.ts`): data is produced during SSR, serialized into the initial
|
|
9
|
+
* HTML, and hydrated on the client with no duplicate request.
|
|
10
|
+
*
|
|
11
|
+
* `tenantNavFromManifest()` is a pure function (data in → data out). It reads
|
|
12
|
+
* the same generated manifest the runtime uses (`.smrt/manifest.json`, written
|
|
13
|
+
* by `smrtPlugin()` and already loaded by `src/lib/server/smrt.ts`), so the nav
|
|
14
|
+
* stays in sync with your `@smrt()` classes automatically instead of being
|
|
15
|
+
* hand-maintained.
|
|
16
|
+
*
|
|
17
|
+
* This load reads no URL/params and declares no `depends()`, so after its
|
|
18
|
+
* initial SSR run SvelteKit does not re-run it on client navigations — only on
|
|
19
|
+
* a full reload or `invalidateAll()`. The manifest-derived nav is therefore
|
|
20
|
+
* effectively static for the session, which is fine (the manifest is fixed at
|
|
21
|
+
* build time). It is independent of each page's own load, so the home page's
|
|
22
|
+
* `depends('smrt:items')` / `invalidate('smrt:items')` refresh flow is
|
|
23
|
+
* untouched by this file.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { existsSync } from 'node:fs';
|
|
27
|
+
import { join } from 'node:path';
|
|
28
|
+
|
|
29
|
+
import { loadManifestFromPathSync } from '@happyvertical/smrt-core/manifest';
|
|
30
|
+
import {
|
|
31
|
+
type ShellNavItem,
|
|
32
|
+
type SmrtManifestLike,
|
|
33
|
+
tenantNavFromManifest,
|
|
34
|
+
} from '@happyvertical/smrt-svelte/workspace';
|
|
35
|
+
import type { LayoutServerLoad } from './$types';
|
|
36
|
+
|
|
37
|
+
export const load: LayoutServerLoad = async () => {
|
|
38
|
+
// Same manifest file `src/lib/server/smrt.ts` seeds the registry from. Reading
|
|
39
|
+
// it here returns the parsed object we hand to the pure nav builder; if it is
|
|
40
|
+
// not generated yet (fresh checkout before the first `vite dev`/`vite build`)
|
|
41
|
+
// we fall back to an empty rail rather than failing the whole layout.
|
|
42
|
+
const manifestPath = join(process.cwd(), '.smrt', 'manifest.json');
|
|
43
|
+
|
|
44
|
+
let nav: ShellNavItem[] = [];
|
|
45
|
+
if (existsSync(manifestPath)) {
|
|
46
|
+
const manifest = loadManifestFromPathSync(manifestPath);
|
|
47
|
+
if (manifest) {
|
|
48
|
+
// `tenantNavFromManifest` reads a documented subset of the manifest
|
|
49
|
+
// (`SmrtManifestLike`). The core `SmartObjectManifest` carries richer
|
|
50
|
+
// field types (e.g. `ApiConfig` has no index signature), so narrow it to
|
|
51
|
+
// the structural shape the pure helper consumes.
|
|
52
|
+
//
|
|
53
|
+
// `basePath: ''` emits page-style hrefs (`/items`) for the developer to
|
|
54
|
+
// wire to their own list routes. `sectionHints` groups classes by
|
|
55
|
+
// package into readable section titles — extend it as you add packages.
|
|
56
|
+
// `NavSection[]` is structurally a superset of `ShellNavItem[]`, so it
|
|
57
|
+
// feeds straight into <TenantNav items={nav}>.
|
|
58
|
+
nav = tenantNavFromManifest(manifest as unknown as SmrtManifestLike, {
|
|
59
|
+
basePath: '',
|
|
60
|
+
sectionHints: {
|
|
61
|
+
'@happyvertical/smrt-content': 'Content',
|
|
62
|
+
'@happyvertical/smrt-users': 'Users',
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { nav };
|
|
69
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { page } from '$app/state';
|
|
3
|
+
import {
|
|
4
|
+
AdminShell,
|
|
5
|
+
AppScopePanel,
|
|
6
|
+
type ShellStatusChip,
|
|
7
|
+
SystemStatusChips,
|
|
8
|
+
TenantNav,
|
|
9
|
+
} from '@happyvertical/smrt-svelte/workspace';
|
|
10
|
+
import { ThemeProvider } from '@happyvertical/smrt-ui/themes';
|
|
11
|
+
// Self-hosted @font-face rules for the SMRT type stack (Space Grotesk /
|
|
12
|
+
// Inter / JetBrains Mono woff2). `<ThemeProvider>` supplies every `--smrt-*`
|
|
13
|
+
// token variable at runtime, but not the font FILES — this import loads them
|
|
14
|
+
// so `--smrt-font-family` renders as the real stack instead of falling back
|
|
15
|
+
// to system-ui. Bundled with the app; no CDN request.
|
|
16
|
+
import '@happyvertical/smrt-ui/themes/styles/fonts.css';
|
|
17
|
+
import type { LayoutProps } from './$types';
|
|
18
|
+
|
|
19
|
+
// `data.nav` is built server-side in `+layout.server.ts` from the SMRT
|
|
20
|
+
// manifest and hydrated here — no client-side nav fetch. `children` is the
|
|
21
|
+
// active page, which renders inside AdminShell's `<main>` and keeps its own
|
|
22
|
+
// server load + `invalidate` flow (see `+page.server.ts`).
|
|
23
|
+
let { data, children }: LayoutProps = $props();
|
|
24
|
+
|
|
25
|
+
// Both wrappers are SSR-safe. ThemeProvider emits its `--smrt-*` token
|
|
26
|
+
// variables as an inline style computed during render (no `window`), so the
|
|
27
|
+
// tokens are present in the server HTML with no unstyled flash; it only reads
|
|
28
|
+
// `matchMedia` after mount to resolve `colorScheme="system"`. AdminShell's
|
|
29
|
+
// public core likewise renders statically and only wires WASD hotkeys /
|
|
30
|
+
// localStorage persistence after mount. Nothing here reads `window` or
|
|
31
|
+
// `localStorage` at module or render time. `$app/state`'s `page` is populated
|
|
32
|
+
// on the server too, so `currentHref` is correct on first paint.
|
|
33
|
+
const currentHref = $derived(page.url.pathname);
|
|
34
|
+
|
|
35
|
+
// Minimal, static system chips. Full live wiring (job counts, dispatch
|
|
36
|
+
// depth, connection state) is a documented next step: feed real values
|
|
37
|
+
// through `systemFeed` (`@happyvertical/smrt-svelte/workspace/live`) or
|
|
38
|
+
// `activityFeed` (`@happyvertical/smrt-svelte/web`)
|
|
39
|
+
// — see the migration guide and the playground `admin-shell-system-feed`
|
|
40
|
+
// demo. Keeping these static here avoids loading the client engine on every
|
|
41
|
+
// page of the scaffold.
|
|
42
|
+
const statusChips: ShellStatusChip[] = [
|
|
43
|
+
{ id: 'env', label: 'Local', tone: 'info' },
|
|
44
|
+
{ id: 'connection', label: 'Ready', tone: 'success' },
|
|
45
|
+
];
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<!--
|
|
49
|
+
ThemeProvider is the standard SMRT theming wrapper (mirrors the reference app
|
|
50
|
+
`@happyvertical/smrt-content` → `src/routes/+layout.svelte`). It injects the
|
|
51
|
+
full `--smrt-*` token set the shell and pages consume, and `colorScheme="system"`
|
|
52
|
+
follows the OS light/dark preference at runtime; `persist` remembers a user's
|
|
53
|
+
explicit choice. Wrap it OUTERMOST so AdminShell and every page render themed.
|
|
54
|
+
-->
|
|
55
|
+
<ThemeProvider colorScheme="system" persist={true}>
|
|
56
|
+
<AdminShell title="SMRT App" subtitle="SvelteKit" storageKey="smrt-app-shell">
|
|
57
|
+
{#snippet appPanel()}
|
|
58
|
+
<AppScopePanel
|
|
59
|
+
appName="SMRT App"
|
|
60
|
+
tenantName="Local development"
|
|
61
|
+
environment="local"
|
|
62
|
+
showSettings={false}
|
|
63
|
+
>
|
|
64
|
+
{#snippet docs()}
|
|
65
|
+
<nav class="app-scope-links">
|
|
66
|
+
<a href="/settings">Shell settings</a>
|
|
67
|
+
</nav>
|
|
68
|
+
{/snippet}
|
|
69
|
+
</AppScopePanel>
|
|
70
|
+
{/snippet}
|
|
71
|
+
|
|
72
|
+
{#snippet tenantPanel()}
|
|
73
|
+
<TenantNav items={data.nav} {currentHref} />
|
|
74
|
+
{/snippet}
|
|
75
|
+
|
|
76
|
+
{#snippet systemBar()}
|
|
77
|
+
<div class="system-bar">
|
|
78
|
+
<SystemStatusChips chips={statusChips} />
|
|
79
|
+
<a class="system-bar__settings" href="/settings">Settings</a>
|
|
80
|
+
</div>
|
|
81
|
+
{/snippet}
|
|
82
|
+
|
|
83
|
+
{@render children()}
|
|
84
|
+
</AdminShell>
|
|
85
|
+
</ThemeProvider>
|
|
86
|
+
|
|
87
|
+
<style>
|
|
88
|
+
:global(body) {
|
|
89
|
+
margin: 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.app-scope-links {
|
|
93
|
+
display: grid;
|
|
94
|
+
gap: var(--smrt-spacing-1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.app-scope-links a,
|
|
98
|
+
.system-bar__settings {
|
|
99
|
+
color: var(--smrt-color-primary);
|
|
100
|
+
text-decoration: none;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.system-bar {
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: space-between;
|
|
107
|
+
gap: var(--smrt-spacing-3);
|
|
108
|
+
inline-size: 100%;
|
|
109
|
+
}
|
|
110
|
+
</style>
|
|
@@ -16,7 +16,14 @@
|
|
|
16
16
|
<title>SMRT SvelteKit App</title>
|
|
17
17
|
</svelte:head>
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
<!--
|
|
20
|
+
This page renders inside the root layout's <AdminShell> `<main>`
|
|
21
|
+
(`src/routes/+layout.svelte`). Its server load + `invalidate('smrt:items')`
|
|
22
|
+
refresh flow is unchanged by the shell — the shell is chrome around the
|
|
23
|
+
page, not a replacement for its data loading. A plain wrapper element (not a
|
|
24
|
+
second <main>) keeps the HTML valid.
|
|
25
|
+
-->
|
|
26
|
+
<div class="page">
|
|
20
27
|
<h1>Welcome to SMRT + SvelteKit</h1>
|
|
21
28
|
|
|
22
29
|
<section>
|
|
@@ -94,10 +101,10 @@
|
|
|
94
101
|
<li>API routes are auto-generated in <code>src/routes/api/</code></li>
|
|
95
102
|
</ul>
|
|
96
103
|
</section>
|
|
97
|
-
</
|
|
104
|
+
</div>
|
|
98
105
|
|
|
99
106
|
<style>
|
|
100
|
-
|
|
107
|
+
.page {
|
|
101
108
|
max-width: 800px;
|
|
102
109
|
margin: 0 auto;
|
|
103
110
|
padding: 2rem;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ShellSettingsPanel } from '@happyvertical/smrt-svelte/workspace';
|
|
3
|
+
|
|
4
|
+
// This page renders inside the root layout's <AdminShell>, so the shell
|
|
5
|
+
// context set by AdminShell is available to descendants — ShellSettingsPanel
|
|
6
|
+
// reads it via useAdminShell() with no extra wiring. It lets users toggle
|
|
7
|
+
// panel visibility and remap the WASD hotkeys; changes persist through the
|
|
8
|
+
// shell's `storageKey` (localStorage), applied client-side after mount.
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<svelte:head>
|
|
12
|
+
<title>Settings · SMRT App</title>
|
|
13
|
+
</svelte:head>
|
|
14
|
+
|
|
15
|
+
<section class="settings">
|
|
16
|
+
<header>
|
|
17
|
+
<h1>Settings</h1>
|
|
18
|
+
<p>Adjust the workspace shell — panel layout and keyboard shortcuts.</p>
|
|
19
|
+
</header>
|
|
20
|
+
|
|
21
|
+
<ShellSettingsPanel />
|
|
22
|
+
</section>
|
|
23
|
+
|
|
24
|
+
<style>
|
|
25
|
+
.settings {
|
|
26
|
+
display: grid;
|
|
27
|
+
gap: var(--smrt-spacing-6, 1.5rem);
|
|
28
|
+
max-width: 720px;
|
|
29
|
+
padding: var(--smrt-spacing-8, 2rem);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.settings header {
|
|
33
|
+
display: grid;
|
|
34
|
+
gap: var(--smrt-spacing-2, 0.5rem);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.settings h1,
|
|
38
|
+
.settings p {
|
|
39
|
+
margin: 0;
|
|
40
|
+
}
|
|
41
|
+
</style>
|