Skip to content

Commit 5d7b7c8

Browse files
committed
Simplify navbar theme picker and download action
1 parent 308f5b0 commit 5d7b7c8

6 files changed

Lines changed: 127 additions & 57 deletions

File tree

IMPLEMENTATION-NOTES.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,31 @@ Screenshots were visually reviewed; no-JavaScript fallback and reduced motion
212212
were checked by the source/regression suite. The prior keyboard-test-tool
213213
limitation remains; controls retain native select/radio semantics.
214214

215+
### Compact navbar actions — 2026-08-30
216+
217+
Starting from `308f5b00ffd2311ff6f1b47ab5b48f62cda74472`, the navbar's 160px-wide
218+
theme field becomes a small, code-native color-swatch icon in a 44px-square
219+
target. The actual native select still occupies the control, retains its
220+
accessible name and seven options, and receives pointer/keyboard focus. Its
221+
wrapper displays a visible focus ring. The native tooltip identifies the
222+
current theme and updates from either selector, restoration or cross-tab sync.
223+
224+
The navbar ISO link is now a quiet, theme-colored outline button, approximately
225+
129 × 36px on desktop instead of 158 × 45px. On phones it retains a 44px height
226+
and now displays the full "Get Omarchy" label. Hero and other page download
227+
buttons, destinations, theme palettes and saved-preference behavior are unchanged.
228+
Files changed: `index.html`, `assets/css/home.css`, `assets/css/home-themes.css`,
229+
`assets/js/modules/home.js`, `tests/home-themes.mjs` and this document.
230+
231+
Browser checks confirmed the icon's hit target is the native select, its focus
232+
ring is visible, changing the theme works, the tooltip follows both dropdown
233+
and swatch selection, and the mobile menu still opens/navigates/closes. Header
234+
layout checks at 320, 390, 768, 1024 and 1440px found no overlap or horizontal
235+
overflow. Desktop/mobile screenshots were reviewed against the oversized-field
236+
feedback. Only the existing localhost analytics warning appeared. Preflight,
237+
HTML validation, contrast/reduced-motion regressions, link policy and public
238+
packaging passed; no dependencies or separate image assets were added.
239+
215240
### Push-to-deploy automation — 2026-08-30
216241

217242
Starting from `f728d6ab0d47da60b49269affa7cced2d2bd94e7`, the existing validation

assets/css/home-themes.css

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -104,55 +104,79 @@ html[data-site-theme]:not([data-site-theme="sovereign"]) .home {
104104
}
105105

106106
.site-theme {
107+
align-items: center;
108+
background: transparent;
109+
border: 1px solid transparent;
110+
border-radius: 2px;
111+
display: grid;
112+
height: 2.75rem;
113+
justify-items: center;
107114
min-width: 0;
108115
position: relative;
109-
width: 10rem;
116+
width: 2.75rem;
110117
}
111118

112119
.site-theme[hidden] {
113120
display: none;
114121
}
115122

116123
.site-theme__label {
117-
color: var(--sm-muted);
118-
font-family: var(--sm-font-interface);
119-
font-size: 0.5rem;
120-
font-weight: 700;
121-
left: 0.65rem;
122-
letter-spacing: 0.1em;
123-
pointer-events: none;
124+
clip-path: inset(50%);
125+
height: 1px;
126+
overflow: hidden;
124127
position: absolute;
125-
text-transform: uppercase;
126-
top: 0.2rem;
128+
white-space: nowrap;
129+
width: 1px;
127130
}
128131

129132
.site-theme select {
130-
appearance: none;
131133
background: var(--sm-panel);
132-
border: 1px solid var(--sm-muted);
133-
border-radius: 2px;
134134
color: var(--sm-text);
135135
cursor: pointer;
136136
display: block;
137137
font-family: var(--sm-font-interface);
138-
font-size: 0.65rem;
139-
font-weight: 700;
140-
min-height: 2.8rem;
141-
padding: 0.9rem 1.6rem 0.25rem 0.65rem;
138+
font-size: 0.875rem;
139+
height: 100%;
140+
inset: 0;
141+
opacity: 0;
142+
position: absolute;
142143
width: 100%;
144+
z-index: 1;
143145
}
144146

145-
.site-theme::after {
146-
border-bottom: 1.5px solid var(--sm-cyan);
147-
border-right: 1.5px solid var(--sm-cyan);
148-
content: '';
149-
height: 0.4rem;
147+
.site-theme__icon {
148+
height: 1.5rem;
150149
pointer-events: none;
151-
position: absolute;
152-
right: 0.65rem;
153-
top: 1.15rem;
154-
transform: rotate(45deg);
155-
width: 0.4rem;
150+
width: 1.5rem;
151+
}
152+
153+
.site-theme__swatch--cyan {
154+
fill: var(--sm-cyan);
155+
}
156+
157+
.site-theme__swatch--gold {
158+
fill: var(--sm-gold);
159+
}
160+
161+
.site-theme__swatch--magenta {
162+
fill: var(--sm-magenta);
163+
}
164+
165+
.site-theme__swatch--outline {
166+
fill: none;
167+
stroke: var(--sm-muted);
168+
stroke-width: 1.5;
169+
}
170+
171+
.site-theme:hover,
172+
.site-theme:has(select:focus-visible) {
173+
background: var(--sm-panel);
174+
border-color: var(--sm-line-strong);
175+
}
176+
177+
.site-theme:has(select:focus-visible) {
178+
outline: 2px solid var(--sm-cyan);
179+
outline-offset: 3px;
156180
}
157181

158182
.home .sm-button {
@@ -170,16 +194,6 @@ html[data-site-theme]:not([data-site-theme="sovereign"]) .home {
170194
@media (max-width: 39.99rem) {
171195
.site-nav:has(.site-theme:not([hidden])) {
172196
gap: 0.5rem;
173-
grid-template-columns: auto minmax(0, 1fr) auto auto;
174-
}
175-
176-
.site-theme {
177-
justify-self: end;
178-
max-width: 10rem;
179-
width: 100%;
180-
}
181-
182-
.site-theme select {
183-
font-size: 0.6rem;
197+
grid-template-columns: 1fr auto auto auto;
184198
}
185199
}

assets/css/home.css

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,7 @@ html:has(.home) {
233233
transform: scaleX(1);
234234
}
235235

236-
.site-menu,
237-
.site-nav__cta-short {
236+
.site-menu {
238237
display: none;
239238
}
240239

@@ -279,9 +278,27 @@ html:has(.home) {
279278
color: var(--sm-cyan-soft) !important;
280279
}
281280

282-
.site-nav__cta {
283-
min-height: 2.8rem;
284-
padding: 0.75rem 1rem;
281+
.home .site-nav__cta {
282+
background: transparent;
283+
border-color: color-mix(in srgb, var(--sm-gold) 55%, var(--sm-void));
284+
color: var(--sm-gold);
285+
font-size: 0.65rem;
286+
gap: 0.55rem;
287+
letter-spacing: 0.08em;
288+
min-height: 2.25rem;
289+
padding: 0.55rem 0.85rem;
290+
}
291+
292+
.home .site-nav__cta:hover,
293+
.home .site-nav__cta:focus-visible {
294+
background: color-mix(in srgb, var(--sm-gold) 9%, var(--sm-void));
295+
border-color: var(--sm-gold);
296+
color: var(--sm-gold-soft);
297+
}
298+
299+
.site-nav__cta svg {
300+
height: 0.85rem;
301+
width: 0.85rem;
285302
}
286303

287304
.hero {
@@ -1546,18 +1563,16 @@ html:has(.home) {
15461563
width: 1.75rem;
15471564
}
15481565

1549-
.site-nav__cta {
1550-
min-height: 2.6rem;
1551-
padding: 0.65rem 0.9rem;
1552-
}
1553-
1554-
.site-nav__cta svg,
1555-
.site-nav__cta-long {
1556-
display: none;
1566+
.home .site-nav__cta {
1567+
font-size: 0.6rem;
1568+
gap: 0.45rem;
1569+
min-height: 2.75rem;
1570+
padding: 0.55rem 0.65rem;
15571571
}
15581572

1559-
.site-nav__cta-short {
1560-
display: inline;
1573+
.site-nav__cta svg {
1574+
height: 0.75rem;
1575+
width: 0.75rem;
15611576
}
15621577

15631578
.site-menu > nav {

assets/js/modules/home.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ function setupThemePreview() {
115115
image.src = theme.image;
116116
image.alt = theme.alt;
117117
controls.forEach((input) => { input.checked = input.value === selected; });
118-
if (select instanceof HTMLSelectElement) select.value = selected;
118+
if (select instanceof HTMLSelectElement) {
119+
select.value = selected;
120+
select.title = `Theme: ${selected === 'sovereign' ? 'Sovereign (original)' : theme.name}`;
121+
}
119122
if (status != null) {
120123
status.textContent = selected === 'sovereign'
121124
? 'Original site palette · Tokyo Night desktop preview.'

index.html

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,13 @@
6363

6464
<label class="site-theme" hidden>
6565
<span class="site-theme__label">Theme</span>
66-
<select name="site-theme" aria-label="Site color theme" data-site-theme-select>
66+
<svg class="site-theme__icon" viewBox="0 0 24 24" aria-hidden="true">
67+
<rect class="site-theme__swatch--cyan" x="3" y="3" width="7" height="7" rx="1"/>
68+
<rect class="site-theme__swatch--gold" x="14" y="3" width="7" height="7" rx="1"/>
69+
<rect class="site-theme__swatch--magenta" x="3" y="14" width="7" height="7" rx="1"/>
70+
<rect class="site-theme__swatch--outline" x="14" y="14" width="7" height="7" rx="1"/>
71+
</svg>
72+
<select name="site-theme" aria-label="Site color theme" title="Theme: Sovereign (original)" data-site-theme-select>
6773
<option value="sovereign" selected>Sovereign</option>
6874
<option value="tokyo-night">Tokyo Night</option>
6975
<option value="catppuccin">Catppuccin</option>
@@ -74,9 +80,8 @@
7480
</select>
7581
</label>
7682

77-
<a class="sm-button sm-button--primary site-nav__cta" href="https://iso.omarchy.org/omarchy-4.0.1.iso" aria-label="Download the current Omarchy ISO">
83+
<a class="sm-button site-nav__cta" href="https://iso.omarchy.org/omarchy-4.0.1.iso" aria-label="Download the current Omarchy ISO">
7884
<span class="site-nav__cta-long">Get Omarchy</span>
79-
<span class="site-nav__cta-short" aria-hidden="true">Get</span>
8085
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 17 17 7M9 7h8v8"/></svg>
8186
</a>
8287

tests/home-themes.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ const dropdown = html.match(/<select\b[^>]*data-site-theme-select[^>]*>([\s\S]*?
1818
assert.deepEqual([...dropdown.matchAll(/<option value="([^"]+)"/g)].map((match) => match[1]), ['sovereign', ...expected]);
1919
assert.match(dropdown, /<option value="sovereign" selected>/);
2020
assert.match(html, /<label class="site-theme" hidden>/, 'Do not expose a nonfunctional dropdown without JavaScript');
21+
assert.match(html, /<select[^>]*aria-label="Site color theme"[^>]*title="Theme: Sovereign \(original\)"/);
22+
assert.match(html, /<svg class="site-theme__icon"[^>]*aria-hidden="true"/);
23+
assert.match(palettes, /\.site-theme:has\(select:focus-visible\)/, 'The icon wrapper must expose native select focus');
2124
assert.match(html, /data-theme-status aria-live="polite"/);
25+
assert.match(html, /class="sm-button site-nav__cta"/, 'Only the navbar CTA uses the compact outline treatment');
26+
assert.match(html, /class="sm-button sm-button--primary" href="https:\/\/iso\.omarchy\.org\//, 'The hero keeps its larger filled download button');
2227

2328
class Element {
2429
dataset = {};
@@ -81,6 +86,7 @@ const { image, status, preview, body, select, inputs, storage, events, context }
8186
assert.deepEqual(Object.keys(context.themes), expected, 'Markup and module choices must stay synchronized');
8287
assert.equal(body.dataset.siteTheme, 'sovereign');
8388
assert.equal(select.value, 'sovereign');
89+
assert.equal(select.title, 'Theme: Sovereign (original)');
8490
assert.equal(select.label.hidden, false);
8591
assert.equal(inputs.some((input) => input.checked), false);
8692
assert.equal(storage.size, 0, 'Do not write a preference before a user chooses one');
@@ -100,6 +106,7 @@ for (const input of inputs) {
100106
assert.equal(preview.dataset.themePreview, input.value);
101107
assert.equal(body.dataset.siteTheme, input.value);
102108
assert.equal(select.value, input.value);
109+
assert.equal(select.title, `Theme: ${theme.name}`);
103110
assert.equal(storage.get('omarchy-sovereign-theme'), input.value);
104111
assert.equal(image.src, theme.image);
105112
assert.equal(image.alt, theme.alt);
@@ -122,6 +129,7 @@ for (const value of expected) {
122129

123130
select.value = 'sovereign';
124131
select.change();
132+
assert.equal(select.title, 'Theme: Sovereign (original)');
125133
assert.equal(body.dataset.siteTheme, 'sovereign');
126134
assert.equal(inputs.some((input) => input.checked), false);
127135
assert.equal(preview.dataset.themePreview, 'tokyo-night');

0 commit comments

Comments
 (0)