Skip to content

Commit 3b07d2e

Browse files
jaysin586claude
andcommitted
feat(chrome): add HeaderV2, FooterV2, ThemeToggleV2
Brutalist-mono variants of the global Header, Footer, and ThemeToggle that consumers can opt into without breaking the existing v1 components. All three exports sit alongside their v1 counterparts in the public API so adoption is a one-line import swap. Visual contract: - Hairline borders, no rounded corners, no shadows. - Monospace base (JetBrains Mono Variable) with small-caps chrome elements. - Single accent slash in the brand mark (config.name lowercased, first interior space promoted to a coloured "/"). - Three-cell hairline theme switch (light · dark · system) replaces the dropdown trigger for a one-glance switch. - Optional nav strip and version pill on HeaderV2; optional license, version, and back-to-top anchor on FooterV2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 59a8b3a commit 3b07d2e

4 files changed

Lines changed: 502 additions & 0 deletions

File tree

src/lib/components/FooterV2.svelte

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<script lang="ts">
2+
import { type Snippet } from 'svelte'
3+
import { MotionSpan } from '@humanspeak/svelte-motion'
4+
5+
/**
6+
* Brutalist-mono footer (v2).
7+
*
8+
* Drop-in compatible with the v1 `Footer` (`extra` snippet still supported)
9+
* but adds optional `license` and `version` metadata fields plus a built-in
10+
* back-to-top anchor. Layout collapses to a single centred row on narrow
11+
* viewports.
12+
*/
13+
const {
14+
extra,
15+
license = 'MIT',
16+
version,
17+
year = new Date().getFullYear()
18+
} = $props<{
19+
extra?: Snippet
20+
license?: string
21+
version?: string
22+
year?: number
23+
}>()
24+
</script>
25+
26+
<footer
27+
class="dk-footer-v2 border-t border-border bg-background text-foreground"
28+
>
29+
<div class="dk-footer-grid">
30+
<div class="dk-footer-cell dk-footer-meta">
31+
<span>{license}</span>
32+
{#if version}
33+
<span class="dk-footer-sep" aria-hidden="true">·</span>
34+
<span>v{version}</span>
35+
{/if}
36+
<span class="dk-footer-sep" aria-hidden="true">·</span>
37+
<span>{year}</span>
38+
</div>
39+
<div class="dk-footer-cell dk-footer-mid">
40+
<span>made with</span>
41+
<MotionSpan
42+
aria-label="Love"
43+
animate={{ scale: [1, 1.2, 1, 1.1, 1] }}
44+
transition={{
45+
duration: 1.2,
46+
repeat: Infinity,
47+
repeatDelay: 0.8,
48+
ease: 'easeInOut'
49+
}}
50+
style="transform-origin: center center; display: inline-block;"
51+
class="dk-footer-heart"
52+
>
53+
&#10084;&#65039;
54+
</MotionSpan>
55+
<span>by</span>
56+
<a
57+
href="https://humanspeak.com"
58+
target="_blank"
59+
rel="noopener noreferrer"
60+
class="dk-footer-brand"
61+
>
62+
humanspeak
63+
</a>
64+
{#if extra}
65+
<span class="dk-footer-sep" aria-hidden="true">·</span>
66+
{@render extra()}
67+
{/if}
68+
</div>
69+
<div class="dk-footer-cell dk-footer-end">
70+
<a href="#top" class="dk-footer-top">↩ to top</a>
71+
</div>
72+
</div>
73+
</footer>
74+
75+
<style>
76+
.dk-footer-v2 {
77+
font-family:
78+
'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace, monospace;
79+
font-size: 11px;
80+
letter-spacing: 0.06em;
81+
}
82+
.dk-footer-grid {
83+
display: grid;
84+
grid-template-columns: 1fr auto 1fr;
85+
align-items: center;
86+
gap: 16px;
87+
padding: 14px 24px;
88+
text-transform: lowercase;
89+
}
90+
.dk-footer-cell {
91+
display: inline-flex;
92+
align-items: center;
93+
gap: 6px;
94+
color: var(--color-text-muted, rgba(127, 127, 127, 0.9));
95+
}
96+
.dk-footer-meta {
97+
justify-content: flex-start;
98+
}
99+
.dk-footer-mid {
100+
justify-content: center;
101+
text-align: center;
102+
flex-wrap: wrap;
103+
}
104+
.dk-footer-end {
105+
justify-content: flex-end;
106+
}
107+
.dk-footer-sep {
108+
color: var(--color-text-muted, rgba(127, 127, 127, 0.6));
109+
}
110+
:global(.dk-footer-heart) {
111+
line-height: 1;
112+
}
113+
.dk-footer-brand {
114+
color: var(--color-brand-500, #54dbbc);
115+
text-decoration: none;
116+
font-weight: 500;
117+
transition: color 0.15s;
118+
}
119+
.dk-footer-brand:hover {
120+
color: var(--color-brand-600, #3aa088);
121+
text-decoration: underline;
122+
}
123+
.dk-footer-top {
124+
color: var(--color-text-muted, rgba(127, 127, 127, 0.9));
125+
text-decoration: none;
126+
transition: color 0.15s;
127+
}
128+
.dk-footer-top:hover {
129+
color: var(--color-text, currentColor);
130+
}
131+
@media (max-width: 640px) {
132+
.dk-footer-grid {
133+
grid-template-columns: 1fr;
134+
text-align: center;
135+
gap: 6px;
136+
}
137+
.dk-footer-meta,
138+
.dk-footer-mid,
139+
.dk-footer-end {
140+
justify-content: center;
141+
}
142+
}
143+
</style>

0 commit comments

Comments
 (0)