@axle-lang/ui 0.1.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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/app.css +337 -0
- package/dist/components/Seo.svelte +38 -0
- package/dist/components/Seo.svelte.d.ts +8 -0
- package/dist/components/atoms/Badge.svelte +11 -0
- package/dist/components/atoms/Badge.svelte.d.ts +8 -0
- package/dist/components/atoms/Button.svelte +32 -0
- package/dist/components/atoms/Button.svelte.d.ts +12 -0
- package/dist/components/atoms/Callout.svelte +11 -0
- package/dist/components/atoms/Callout.svelte.d.ts +8 -0
- package/dist/components/atoms/CodeChip.svelte +11 -0
- package/dist/components/atoms/CodeChip.svelte.d.ts +8 -0
- package/dist/components/atoms/Eyebrow.svelte +9 -0
- package/dist/components/atoms/Eyebrow.svelte.d.ts +8 -0
- package/dist/components/atoms/HandNote.svelte +15 -0
- package/dist/components/atoms/HandNote.svelte.d.ts +9 -0
- package/dist/components/atoms/Icon.svelte +40 -0
- package/dist/components/atoms/Icon.svelte.d.ts +11 -0
- package/dist/components/atoms/Kbd.svelte +11 -0
- package/dist/components/atoms/Kbd.svelte.d.ts +8 -0
- package/dist/components/atoms/Logo.svelte +18 -0
- package/dist/components/atoms/Logo.svelte.d.ts +6 -0
- package/dist/components/atoms/SearchButton.svelte +23 -0
- package/dist/components/atoms/SearchButton.svelte.d.ts +8 -0
- package/dist/components/atoms/Tag.svelte +21 -0
- package/dist/components/atoms/Tag.svelte.d.ts +10 -0
- package/dist/components/atoms/ThemeToggle.svelte +30 -0
- package/dist/components/atoms/ThemeToggle.svelte.d.ts +6 -0
- package/dist/components/code/Code.svelte +22 -0
- package/dist/components/code/Code.svelte.d.ts +9 -0
- package/dist/components/code/CodeWindow.svelte +42 -0
- package/dist/components/code/CodeWindow.svelte.d.ts +13 -0
- package/dist/components/code/CopyCommand.svelte +28 -0
- package/dist/components/code/CopyCommand.svelte.d.ts +7 -0
- package/dist/components/landing/BenchExplorer.svelte +157 -0
- package/dist/components/landing/BenchExplorer.svelte.d.ts +7 -0
- package/dist/components/landing/CTASection.svelte +12 -0
- package/dist/components/landing/CTASection.svelte.d.ts +11 -0
- package/dist/components/landing/ComparisonPanel.svelte +75 -0
- package/dist/components/landing/ComparisonPanel.svelte.d.ts +19 -0
- package/dist/components/landing/FeatureCard.svelte +19 -0
- package/dist/components/landing/FeatureCard.svelte.d.ts +10 -0
- package/dist/components/landing/FeatureGrid.svelte +26 -0
- package/dist/components/landing/FeatureGrid.svelte.d.ts +13 -0
- package/dist/components/landing/Hero.svelte +23 -0
- package/dist/components/landing/Hero.svelte.d.ts +14 -0
- package/dist/components/landing/RecipeDeck.svelte +137 -0
- package/dist/components/landing/RecipeDeck.svelte.d.ts +19 -0
- package/dist/components/layout/DocLayout.svelte +36 -0
- package/dist/components/layout/DocLayout.svelte.d.ts +21 -0
- package/dist/components/layout/PageShell.svelte +15 -0
- package/dist/components/layout/PageShell.svelte.d.ts +7 -0
- package/dist/components/molecules/Card.svelte +18 -0
- package/dist/components/molecules/Card.svelte.d.ts +9 -0
- package/dist/components/molecules/DataTable.svelte +43 -0
- package/dist/components/molecules/DataTable.svelte.d.ts +12 -0
- package/dist/components/molecules/PageHeading.svelte +23 -0
- package/dist/components/molecules/PageHeading.svelte.d.ts +10 -0
- package/dist/components/molecules/Section.svelte +20 -0
- package/dist/components/molecules/Section.svelte.d.ts +10 -0
- package/dist/components/molecules/SectionHeading.svelte +27 -0
- package/dist/components/molecules/SectionHeading.svelte.d.ts +10 -0
- package/dist/components/nav/DocHeader.svelte +44 -0
- package/dist/components/nav/DocHeader.svelte.d.ts +7 -0
- package/dist/components/nav/Footer.svelte +67 -0
- package/dist/components/nav/Footer.svelte.d.ts +3 -0
- package/dist/components/nav/Header.svelte +55 -0
- package/dist/components/nav/Header.svelte.d.ts +6 -0
- package/dist/components/nav/PrevNext.svelte +27 -0
- package/dist/components/nav/PrevNext.svelte.d.ts +13 -0
- package/dist/components/nav/RightRail.svelte +30 -0
- package/dist/components/nav/RightRail.svelte.d.ts +11 -0
- package/dist/components/nav/Sidebar.svelte +33 -0
- package/dist/components/nav/Sidebar.svelte.d.ts +18 -0
- package/dist/components/reference/MethodDetail.svelte +72 -0
- package/dist/components/reference/MethodDetail.svelte.d.ts +7 -0
- package/dist/components/reference/MethodSummary.svelte +41 -0
- package/dist/components/reference/MethodSummary.svelte.d.ts +8 -0
- package/dist/i18n/index.d.ts +47 -0
- package/dist/i18n/index.js +23 -0
- package/dist/i18n/messages/en.d.ts +43 -0
- package/dist/i18n/messages/en.js +50 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +54 -0
- package/dist/site/site.d.ts +45 -0
- package/dist/site/site.js +66 -0
- package/dist/utils/cn.d.ts +6 -0
- package/dist/utils/cn.js +9 -0
- package/dist/utils/icons.d.ts +26 -0
- package/dist/utils/icons.js +55 -0
- package/dist/utils/tokenizer.d.ts +12 -0
- package/dist/utils/tokenizer.js +181 -0
- package/dist/utils/types.d.ts +50 -0
- package/dist/utils/types.js +4 -0
- package/dist/utils/variants.d.ts +20 -0
- package/dist/utils/variants.js +50 -0
- package/package.json +77 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Axle Language
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @axle-lang/ui
|
|
2
|
+
|
|
3
|
+
The Axle **design system** — a content-agnostic Svelte 5 + Tailwind v4
|
|
4
|
+
component library, shared by the Axle landing and docs sites.
|
|
5
|
+
|
|
6
|
+
It holds presentation only: components, the design tokens
|
|
7
|
+
(`src/lib/app.css`), the syntax tokenizer, the small utils
|
|
8
|
+
(`cn` / `cva` variants / icons), the cross-domain routing helpers, and
|
|
9
|
+
the i18n **chrome** catalog (UI labels). It contains **no page content** —
|
|
10
|
+
prose, the stdlib reference and benchmarks are generated in the
|
|
11
|
+
[`axle`](https://github.com/axle-lang/axle) repo and injected by the apps
|
|
12
|
+
at build time.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
src/lib/
|
|
16
|
+
├── index.ts public barrel
|
|
17
|
+
├── app.css Tailwind v4 tokens (the single source of truth)
|
|
18
|
+
├── components/ atoms · molecules · code · nav · landing · layout · reference
|
|
19
|
+
├── i18n/ synchronous svelte-i18n setup + chrome catalog + K keys
|
|
20
|
+
├── site/ site.ts (buildSite / route / setSite / getSite) · version.ts
|
|
21
|
+
└── utils/ cn · variants (cva) · tokenizer · icons · types
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Consuming it
|
|
25
|
+
|
|
26
|
+
The package is **source-typed** and built with `@sveltejs/package` to
|
|
27
|
+
`dist/` (with `.d.ts`). Peer dependencies — `svelte`, `@sveltejs/kit`
|
|
28
|
+
(for the route-aware `Seo` / `Sidebar`), and `svelte-i18n` (one shared
|
|
29
|
+
locale store) — are provided by the consuming app.
|
|
30
|
+
|
|
31
|
+
Published to npm as a public package:
|
|
32
|
+
|
|
33
|
+
```jsonc
|
|
34
|
+
// in each app's package.json
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@axle-lang/ui": "^0.1.0"
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
import { Header, Footer, Seo, initI18n, setSite, buildSite, K } from '@axle-lang/ui';
|
|
42
|
+
import '@axle-lang/ui/app.css';
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
i18n labels are referenced through the `K` keys object (never raw string
|
|
46
|
+
literals): `$t(K.nav.guide)`.
|
|
47
|
+
|
|
48
|
+
## Develop
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm install
|
|
52
|
+
pnpm dev # the in-repo gallery (src/routes) — visual smoke test
|
|
53
|
+
pnpm check # svelte-check (TypeScript)
|
|
54
|
+
pnpm lint # prettier --check + eslint
|
|
55
|
+
pnpm package # build dist/ + publint
|
|
56
|
+
pnpm format
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Publishing
|
|
60
|
+
|
|
61
|
+
Published to **npmjs** under the `@axle-lang` scope (public).
|
|
62
|
+
|
|
63
|
+
- **Automated** (preferred): publishing a GitHub Release triggers
|
|
64
|
+
`.github/workflows/publish.yml`, which runs `pnpm publish` with the
|
|
65
|
+
`NPM_TOKEN` repo secret. `prepare` builds `dist/` before packing and
|
|
66
|
+
`publishConfig.access` makes the scoped package public.
|
|
67
|
+
- **Manual**: `npm login` then `pnpm publish`.
|
|
68
|
+
|
|
69
|
+
Bump the version first with `npm version patch|minor|major`, then push
|
|
70
|
+
`--follow-tags` and cut the Release. Requires the `@axle-lang` npm org.
|
package/dist/app.css
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/* =============================================================
|
|
2
|
+
Axle — Design System (Tailwind v4)
|
|
3
|
+
Single source of truth for tokens, fonts and primitives.
|
|
4
|
+
Import once in your app entry: @import "./app.css";
|
|
5
|
+
Works in mdbook (drop into theme/) and SvelteKit (src/app.css).
|
|
6
|
+
============================================================= */
|
|
7
|
+
|
|
8
|
+
@import 'tailwindcss';
|
|
9
|
+
|
|
10
|
+
/* Dark mode is class-based: add `dark` on <html> (or any ancestor). */
|
|
11
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
12
|
+
|
|
13
|
+
/* -------------------------------------------------------------
|
|
14
|
+
1. Fonts
|
|
15
|
+
Self-host for production; the CDN links below are a quick start.
|
|
16
|
+
------------------------------------------------------------- */
|
|
17
|
+
|
|
18
|
+
/* -------------------------------------------------------------
|
|
19
|
+
2. Raw token values (light is the default theme)
|
|
20
|
+
Edit these to retheme the whole system.
|
|
21
|
+
------------------------------------------------------------- */
|
|
22
|
+
:root {
|
|
23
|
+
/* Surfaces */
|
|
24
|
+
--canvas: #ffffff;
|
|
25
|
+
--surface: #faf9f7;
|
|
26
|
+
--surface2: #f1efea;
|
|
27
|
+
/* Text */
|
|
28
|
+
--fg: #15171c;
|
|
29
|
+
--muted: #5b626d;
|
|
30
|
+
--faint: #8b919c;
|
|
31
|
+
/* Lines & accent */
|
|
32
|
+
--line: #e9e6e0;
|
|
33
|
+
--accent: #ff5a1f;
|
|
34
|
+
--accent-soft: #fff1ea;
|
|
35
|
+
--ink-soft: #c2774a; /* handwritten annotation tone */
|
|
36
|
+
/* Code surface */
|
|
37
|
+
--code-strong: #0d1117;
|
|
38
|
+
|
|
39
|
+
/* Syntax (light) */
|
|
40
|
+
--sx-kw: #9333ea;
|
|
41
|
+
--sx-ty: #0e7490;
|
|
42
|
+
--sx-fn: #1d4ed8;
|
|
43
|
+
--sx-str: #15803d;
|
|
44
|
+
--sx-num: #b45309;
|
|
45
|
+
--sx-com: #9aa1ac;
|
|
46
|
+
--sx-p: #6b7280;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.dark {
|
|
50
|
+
--canvas: #0b0d11;
|
|
51
|
+
--surface: #0f1217;
|
|
52
|
+
--surface2: #161a21;
|
|
53
|
+
--fg: #e6e9ee;
|
|
54
|
+
--muted: #9aa2ae;
|
|
55
|
+
--faint: #69727f;
|
|
56
|
+
--line: #222831;
|
|
57
|
+
--accent: #ff6a33;
|
|
58
|
+
--accent-soft: #2a160d;
|
|
59
|
+
--ink-soft: #e0a071;
|
|
60
|
+
--code-strong: #080a0e;
|
|
61
|
+
|
|
62
|
+
--sx-kw: #c792ea;
|
|
63
|
+
--sx-ty: #5ccfe6;
|
|
64
|
+
--sx-fn: #82aaff;
|
|
65
|
+
--sx-str: #c3e88d;
|
|
66
|
+
--sx-num: #f78c6c;
|
|
67
|
+
--sx-com: #5c6675;
|
|
68
|
+
--sx-p: #8b94a3;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Code blocks always render on the dark surface, regardless of theme.
|
|
72
|
+
Add `.dark-code` to a code container to get the dark syntax palette. */
|
|
73
|
+
.dark-code {
|
|
74
|
+
--sx-kw: #c792ea;
|
|
75
|
+
--sx-ty: #5ccfe6;
|
|
76
|
+
--sx-fn: #82aaff;
|
|
77
|
+
--sx-str: #c3e88d;
|
|
78
|
+
--sx-num: #f78c6c;
|
|
79
|
+
--sx-com: #6b7587;
|
|
80
|
+
--sx-p: #8b94a3;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* -------------------------------------------------------------
|
|
84
|
+
3. Expose tokens to Tailwind utilities
|
|
85
|
+
Enables bg-canvas, text-fg, border-line, text-accent,
|
|
86
|
+
font-sans, font-mono, etc. — everywhere.
|
|
87
|
+
------------------------------------------------------------- */
|
|
88
|
+
@theme inline {
|
|
89
|
+
--color-canvas: var(--canvas);
|
|
90
|
+
--color-surface: var(--surface);
|
|
91
|
+
--color-surface2: var(--surface2);
|
|
92
|
+
--color-fg: var(--fg);
|
|
93
|
+
--color-muted: var(--muted);
|
|
94
|
+
--color-faint: var(--faint);
|
|
95
|
+
--color-line: var(--line);
|
|
96
|
+
--color-accent: var(--accent);
|
|
97
|
+
--color-accent-soft: var(--accent-soft);
|
|
98
|
+
--color-ink-soft: var(--ink-soft);
|
|
99
|
+
--color-codebg: var(--code-strong);
|
|
100
|
+
|
|
101
|
+
--font-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
|
|
102
|
+
--font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
|
|
103
|
+
--font-hand: 'Caveat', cursive;
|
|
104
|
+
|
|
105
|
+
/* Type scale used across docs + landing */
|
|
106
|
+
--text-display: clamp(36px, 5.2vw, 58px); /* hero h1 */
|
|
107
|
+
--text-h1: 34px; /* page title */
|
|
108
|
+
--text-h2: 22px; /* section */
|
|
109
|
+
--text-h3: 18px;
|
|
110
|
+
--text-body: 16px;
|
|
111
|
+
--text-sm: 13.5px;
|
|
112
|
+
|
|
113
|
+
/* Radii */
|
|
114
|
+
--radius-card: 12px; /* rounded-xl cards */
|
|
115
|
+
--radius-md: 8px;
|
|
116
|
+
|
|
117
|
+
/* Shadows */
|
|
118
|
+
--shadow-card: 0 1px 3px rgb(0 0 0 / 0.06);
|
|
119
|
+
--shadow-pop: 0 10px 30px rgb(0 0 0 / 0.12);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* -------------------------------------------------------------
|
|
123
|
+
4. Base resets
|
|
124
|
+
------------------------------------------------------------- */
|
|
125
|
+
@layer base {
|
|
126
|
+
html,
|
|
127
|
+
body {
|
|
128
|
+
margin: 0;
|
|
129
|
+
padding: 0;
|
|
130
|
+
}
|
|
131
|
+
body {
|
|
132
|
+
font-family: var(--font-sans);
|
|
133
|
+
background: var(--canvas);
|
|
134
|
+
color: var(--fg);
|
|
135
|
+
-webkit-font-smoothing: antialiased;
|
|
136
|
+
text-rendering: optimizeLegibility;
|
|
137
|
+
}
|
|
138
|
+
::selection {
|
|
139
|
+
background: var(--accent);
|
|
140
|
+
color: #fff;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* -------------------------------------------------------------
|
|
145
|
+
5. Component primitives
|
|
146
|
+
Reusable classes the Svelte components (and mdbook) lean on.
|
|
147
|
+
------------------------------------------------------------- */
|
|
148
|
+
@layer components {
|
|
149
|
+
/* Thin scrollbar used on code/overflow areas */
|
|
150
|
+
.axle-scroll::-webkit-scrollbar {
|
|
151
|
+
width: 9px;
|
|
152
|
+
height: 9px;
|
|
153
|
+
}
|
|
154
|
+
.axle-scroll::-webkit-scrollbar-thumb {
|
|
155
|
+
background: var(--line);
|
|
156
|
+
border-radius: 9px;
|
|
157
|
+
}
|
|
158
|
+
.axle-scroll::-webkit-scrollbar-track {
|
|
159
|
+
background: transparent;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* Syntax highlight token colors (pair with a tokenizer that
|
|
163
|
+
emits .t-kw / .t-ty / .t-fn / .t-str / .t-num / .t-com / .t-p) */
|
|
164
|
+
.t-kw {
|
|
165
|
+
color: var(--sx-kw);
|
|
166
|
+
font-weight: 500;
|
|
167
|
+
}
|
|
168
|
+
.t-ty {
|
|
169
|
+
color: var(--sx-ty);
|
|
170
|
+
}
|
|
171
|
+
.t-fn {
|
|
172
|
+
color: var(--sx-fn);
|
|
173
|
+
}
|
|
174
|
+
.t-str {
|
|
175
|
+
color: var(--sx-str);
|
|
176
|
+
}
|
|
177
|
+
.t-num {
|
|
178
|
+
color: var(--sx-num);
|
|
179
|
+
}
|
|
180
|
+
.t-com {
|
|
181
|
+
color: var(--sx-com);
|
|
182
|
+
font-style: italic;
|
|
183
|
+
}
|
|
184
|
+
.t-p {
|
|
185
|
+
color: var(--sx-p);
|
|
186
|
+
}
|
|
187
|
+
.dark-code pre code {
|
|
188
|
+
color: #c3cad6;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* Handwritten annotation + thin hand-drawn underline */
|
|
192
|
+
.ink {
|
|
193
|
+
font-family: var(--font-hand);
|
|
194
|
+
color: var(--accent);
|
|
195
|
+
line-height: 1;
|
|
196
|
+
}
|
|
197
|
+
.note {
|
|
198
|
+
font-family: var(--font-hand);
|
|
199
|
+
color: var(--ink-soft);
|
|
200
|
+
line-height: 1.4;
|
|
201
|
+
}
|
|
202
|
+
.uline {
|
|
203
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 10' preserveAspectRatio='none'%3E%3Cpath d='M2 6 C 22 2, 42 9, 62 5 S 102 2, 118 6' fill='none' stroke='%23c2774a' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
|
|
204
|
+
background-repeat: no-repeat;
|
|
205
|
+
background-position: 0 100%;
|
|
206
|
+
background-size: 100% 0.34em;
|
|
207
|
+
padding-bottom: 0.16em;
|
|
208
|
+
}
|
|
209
|
+
.dark .uline {
|
|
210
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 10' preserveAspectRatio='none'%3E%3Cpath d='M2 6 C 22 2, 42 9, 62 5 S 102 2, 118 6' fill='none' stroke='%23e0a071' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* Marker swipe highlight (used on the hero word) */
|
|
214
|
+
.mark {
|
|
215
|
+
background: linear-gradient(120deg, var(--accent-soft) 0%, var(--accent-soft) 100%);
|
|
216
|
+
background-repeat: no-repeat;
|
|
217
|
+
background-position: 0 88%;
|
|
218
|
+
background-size: 100% 38%;
|
|
219
|
+
border-radius: 1px;
|
|
220
|
+
}
|
|
221
|
+
.dark .mark {
|
|
222
|
+
background-image: linear-gradient(
|
|
223
|
+
120deg,
|
|
224
|
+
color-mix(in oklch, var(--accent) 32%, transparent) 0%,
|
|
225
|
+
color-mix(in oklch, var(--accent) 32%, transparent) 100%
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* --- Buttons --- */
|
|
230
|
+
.btn {
|
|
231
|
+
display: inline-flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
gap: 0.375rem;
|
|
234
|
+
height: 2.75rem;
|
|
235
|
+
padding-inline: 1.25rem;
|
|
236
|
+
border-radius: var(--radius-md);
|
|
237
|
+
font-size: 14px;
|
|
238
|
+
font-weight: 500;
|
|
239
|
+
cursor: pointer;
|
|
240
|
+
transition:
|
|
241
|
+
opacity 0.15s,
|
|
242
|
+
background-color 0.15s,
|
|
243
|
+
border-color 0.15s;
|
|
244
|
+
}
|
|
245
|
+
.btn-primary {
|
|
246
|
+
background: var(--accent);
|
|
247
|
+
color: #fff;
|
|
248
|
+
}
|
|
249
|
+
.btn-primary:hover {
|
|
250
|
+
opacity: 0.9;
|
|
251
|
+
}
|
|
252
|
+
.btn-secondary {
|
|
253
|
+
background: var(--canvas);
|
|
254
|
+
color: var(--fg);
|
|
255
|
+
border: 1px solid var(--line);
|
|
256
|
+
}
|
|
257
|
+
.btn-secondary:hover {
|
|
258
|
+
background: var(--surface);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* --- Card --- */
|
|
262
|
+
.card {
|
|
263
|
+
background: var(--canvas);
|
|
264
|
+
border: 1px solid var(--line);
|
|
265
|
+
border-radius: var(--radius-card);
|
|
266
|
+
}
|
|
267
|
+
.card-muted {
|
|
268
|
+
background: var(--surface);
|
|
269
|
+
border: 1px solid var(--line);
|
|
270
|
+
border-radius: var(--radius-card);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* --- Inline code chip --- */
|
|
274
|
+
.code-chip {
|
|
275
|
+
font-family: var(--font-mono);
|
|
276
|
+
font-size: 12px;
|
|
277
|
+
border: 1px solid var(--line);
|
|
278
|
+
background: var(--surface);
|
|
279
|
+
color: var(--muted);
|
|
280
|
+
border-radius: var(--radius-md);
|
|
281
|
+
padding: 0.25rem 0.5rem;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* --- Callout (info/note banner) --- */
|
|
285
|
+
.callout {
|
|
286
|
+
display: flex;
|
|
287
|
+
gap: 0.75rem;
|
|
288
|
+
border-left: 2px solid var(--accent);
|
|
289
|
+
background: var(--accent-soft);
|
|
290
|
+
border-radius: var(--radius-card);
|
|
291
|
+
padding: 1rem 1.25rem;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* --- Eyebrow / kicker label --- */
|
|
295
|
+
.eyebrow {
|
|
296
|
+
font-size: 12px;
|
|
297
|
+
font-weight: 600;
|
|
298
|
+
letter-spacing: 0.14em;
|
|
299
|
+
text-transform: uppercase;
|
|
300
|
+
color: var(--accent);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* -------------------------------------------------------------
|
|
305
|
+
6. Keyframes
|
|
306
|
+
------------------------------------------------------------- */
|
|
307
|
+
@keyframes axle-blink {
|
|
308
|
+
0%,
|
|
309
|
+
49% {
|
|
310
|
+
opacity: 1;
|
|
311
|
+
}
|
|
312
|
+
50%,
|
|
313
|
+
100% {
|
|
314
|
+
opacity: 0;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
@keyframes axle-deck-in {
|
|
318
|
+
0% {
|
|
319
|
+
opacity: 0.4;
|
|
320
|
+
transform: translateY(6px);
|
|
321
|
+
}
|
|
322
|
+
100% {
|
|
323
|
+
opacity: 1;
|
|
324
|
+
transform: none;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
@keyframes axle-prog {
|
|
328
|
+
0% {
|
|
329
|
+
width: 0;
|
|
330
|
+
}
|
|
331
|
+
100% {
|
|
332
|
+
width: 100%;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
.cursor-blink {
|
|
336
|
+
animation: axle-blink 1.05s steps(1) infinite;
|
|
337
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Per-page SEO head: title, description, canonical, Open Graph, Twitter.
|
|
3
|
+
// Canonical/OG URL is built from the site origin (injected via setSite)
|
|
4
|
+
// + the current path.
|
|
5
|
+
import { page } from '$app/state';
|
|
6
|
+
import { getSite } from '../site/site.js';
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
title = '',
|
|
10
|
+
description = '',
|
|
11
|
+
image = ''
|
|
12
|
+
}: { title?: string; description?: string; image?: string } = $props();
|
|
13
|
+
|
|
14
|
+
const { origin = '' } = getSite();
|
|
15
|
+
const url = $derived(origin + page.url.pathname);
|
|
16
|
+
const fullTitle = $derived(
|
|
17
|
+
!title ? 'Axle' : title.startsWith('Axle') ? title : `${title} · Axle`
|
|
18
|
+
);
|
|
19
|
+
const card = $derived(image ? 'summary_large_image' : 'summary');
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<svelte:head>
|
|
23
|
+
<title>{fullTitle}</title>
|
|
24
|
+
{#if description}<meta name="description" content={description} />{/if}
|
|
25
|
+
<link rel="canonical" href={url} />
|
|
26
|
+
|
|
27
|
+
<meta property="og:type" content="website" />
|
|
28
|
+
<meta property="og:site_name" content="Axle" />
|
|
29
|
+
<meta property="og:title" content={fullTitle} />
|
|
30
|
+
{#if description}<meta property="og:description" content={description} />{/if}
|
|
31
|
+
<meta property="og:url" content={url} />
|
|
32
|
+
{#if image}<meta property="og:image" content={image} />{/if}
|
|
33
|
+
|
|
34
|
+
<meta name="twitter:card" content={card} />
|
|
35
|
+
<meta name="twitter:title" content={fullTitle} />
|
|
36
|
+
{#if description}<meta name="twitter:description" content={description} />{/if}
|
|
37
|
+
{#if image}<meta name="twitter:image" content={image} />{/if}
|
|
38
|
+
</svelte:head>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
/** Pill badge, e.g. version tag. */
|
|
4
|
+
let { class: klass = '', children }: { class?: string; children?: Snippet } = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<span
|
|
8
|
+
class="inline-flex items-center rounded-full border border-line px-2 py-0.5 text-[11px] font-medium text-muted whitespace-nowrap {klass}"
|
|
9
|
+
>
|
|
10
|
+
{@render children?.()}
|
|
11
|
+
</span>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import { button } from '../../utils/variants.js';
|
|
4
|
+
import { cn } from '../../utils/cn.js';
|
|
5
|
+
/**
|
|
6
|
+
* Button / link. Renders <a> when `href` is set, otherwise <button>.
|
|
7
|
+
*/
|
|
8
|
+
let {
|
|
9
|
+
variant = 'primary',
|
|
10
|
+
href,
|
|
11
|
+
onclick,
|
|
12
|
+
size = 'md',
|
|
13
|
+
class: klass = '',
|
|
14
|
+
children,
|
|
15
|
+
...rest
|
|
16
|
+
}: {
|
|
17
|
+
variant?: 'primary' | 'secondary';
|
|
18
|
+
href?: string;
|
|
19
|
+
onclick?: (e: MouseEvent) => void;
|
|
20
|
+
size?: 'sm' | 'md';
|
|
21
|
+
class?: string;
|
|
22
|
+
children?: Snippet;
|
|
23
|
+
} = $props();
|
|
24
|
+
|
|
25
|
+
const cls = $derived(cn(button({ variant, size }), klass));
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
{#if href}
|
|
29
|
+
<a {href} class={cls} {...rest}>{@render children?.()}</a>
|
|
30
|
+
{:else}
|
|
31
|
+
<button type="button" {onclick} class={cls} {...rest}>{@render children?.()}</button>
|
|
32
|
+
{/if}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
variant?: 'primary' | 'secondary';
|
|
4
|
+
href?: string;
|
|
5
|
+
onclick?: (e: MouseEvent) => void;
|
|
6
|
+
size?: 'sm' | 'md';
|
|
7
|
+
class?: string;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
};
|
|
10
|
+
declare const Button: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type Button = ReturnType<typeof Button>;
|
|
12
|
+
export default Button;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import Icon from './Icon.svelte';
|
|
4
|
+
/** Info / note banner with accent left border. */
|
|
5
|
+
let { class: klass = '', children }: { class?: string; children?: Snippet } = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class="flex gap-3 rounded-xl border-l-2 border-accent bg-accent-soft px-5 py-4 {klass}">
|
|
9
|
+
<span class="text-accent mt-0.5 shrink-0"><Icon name="info" size={18} /></span>
|
|
10
|
+
<p class="text-[14px] leading-relaxed text-fg">{@render children?.()}</p>
|
|
11
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
/** Inline monospace code chip. */
|
|
4
|
+
let { class: klass = '', children }: { class?: string; children?: Snippet } = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<code
|
|
8
|
+
class="font-mono text-[12px] rounded-md border border-line bg-surface px-2 py-1 text-muted {klass}"
|
|
9
|
+
>
|
|
10
|
+
{@render children?.()}
|
|
11
|
+
</code>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
/** Uppercase accent kicker label. */
|
|
4
|
+
let { class: klass = '', children }: { class?: string; children?: Snippet } = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="text-[12px] font-semibold tracking-[0.14em] text-accent uppercase {klass}">
|
|
8
|
+
{@render children?.()}
|
|
9
|
+
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
/**
|
|
4
|
+
* Handwritten margin note. Wrap the keyword to underline in {#snippet} or
|
|
5
|
+
* pass plain text; set `underline` to the substring you want hand-underlined.
|
|
6
|
+
* Simplest usage: <HandNote>Because comfortable code should never cost you <span class="uline">performance</span>.</HandNote>
|
|
7
|
+
*/
|
|
8
|
+
let {
|
|
9
|
+
size = 21,
|
|
10
|
+
class: klass = '',
|
|
11
|
+
children
|
|
12
|
+
}: { size?: number; class?: string; children?: Snippet } = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<span class="note leading-[1.4] {klass}" style="font-size:{size}px">{@render children?.()}</span>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
size?: number;
|
|
4
|
+
class?: string;
|
|
5
|
+
children?: Snippet;
|
|
6
|
+
};
|
|
7
|
+
declare const HandNote: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type HandNote = ReturnType<typeof HandNote>;
|
|
9
|
+
export default HandNote;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { icons } from '../../utils/icons.js';
|
|
3
|
+
import type { IconName } from '../../utils/icons.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Atomic icon. Pass either a known `name` (see lib/icons.js) or raw `paths`.
|
|
7
|
+
*/
|
|
8
|
+
let {
|
|
9
|
+
name,
|
|
10
|
+
paths,
|
|
11
|
+
size = 16,
|
|
12
|
+
stroke = 1.7,
|
|
13
|
+
class: klass = ''
|
|
14
|
+
}: {
|
|
15
|
+
name?: IconName;
|
|
16
|
+
paths?: string[];
|
|
17
|
+
size?: number;
|
|
18
|
+
stroke?: number;
|
|
19
|
+
class?: string;
|
|
20
|
+
} = $props();
|
|
21
|
+
|
|
22
|
+
const d = $derived(paths ?? (name ? icons[name] : undefined) ?? []);
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<svg
|
|
26
|
+
width={size}
|
|
27
|
+
height={size}
|
|
28
|
+
viewBox="0 0 24 24"
|
|
29
|
+
fill="none"
|
|
30
|
+
stroke="currentColor"
|
|
31
|
+
stroke-width={stroke}
|
|
32
|
+
stroke-linecap="round"
|
|
33
|
+
stroke-linejoin="round"
|
|
34
|
+
class={klass}
|
|
35
|
+
aria-hidden="true"
|
|
36
|
+
>
|
|
37
|
+
{#each d as p}
|
|
38
|
+
<path d={p} />
|
|
39
|
+
{/each}
|
|
40
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IconName } from '../../utils/icons.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
name?: IconName;
|
|
4
|
+
paths?: string[];
|
|
5
|
+
size?: number;
|
|
6
|
+
stroke?: number;
|
|
7
|
+
class?: string;
|
|
8
|
+
};
|
|
9
|
+
declare const Icon: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
10
|
+
type Icon = ReturnType<typeof Icon>;
|
|
11
|
+
export default Icon;
|