refactor(dev): dogfood framework CSS in theme adapter panel
Replace all inline styles in theme-adapter.js with framework classes. The panel now uses its own tokens (var(--bg-1), var(--fg-0), etc.) so it visually adapts when you change theme colors — true dogfooding. New framework components added to fill gaps: - popover.css — fixed-position floating panel (.popover, .popover-br) - chip.css + chip.cljc — selectable preset buttons (.chip, .chip-active) - swatch.css — color preview strips (.swatch-row, .swatch) - button.css — icon-only buttons (.btn-icon, .btn-icon-round) - card.css — sectioned card variant (.card-flush, .card-section) - utilities.css — text/flex helpers (.text-xs, .font-semibold, .flex-1, etc.) Theme adapter JS shrunk from 340 to 250 lines by removing the 60-line inline style object and applyStyle() helper.
This commit is contained in:
@@ -78,6 +78,24 @@ a.btn-link {
|
||||
line-height: var(--size-6);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
padding: var(--size-2);
|
||||
line-height: 1;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.btn-icon.btn-sm {
|
||||
padding: var(--size-1);
|
||||
}
|
||||
|
||||
.btn-icon.btn-lg {
|
||||
padding: var(--size-3);
|
||||
}
|
||||
|
||||
.btn-icon-round {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
|
||||
@@ -11,6 +11,19 @@
|
||||
padding: var(--size-6);
|
||||
}
|
||||
|
||||
.card-flush {
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.card-section {
|
||||
padding: var(--size-3) var(--size-4);
|
||||
}
|
||||
|
||||
.card-section + .card-section {
|
||||
border-top: var(--border-0);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
54
src/ui/chip.cljc
Normal file
54
src/ui/chip.cljc
Normal file
@@ -0,0 +1,54 @@
|
||||
(ns ui.chip
|
||||
(:require [clojure.string :as str]))
|
||||
|
||||
#?(:squint (defn- kw-name [s] s)
|
||||
:cljs (defn- kw-name [s] (name s))
|
||||
:clj (defn- kw-name [s] (name s)))
|
||||
|
||||
(defn chip-class-list
|
||||
"Returns a vector of CSS class strings for a chip."
|
||||
[{:keys [active]}]
|
||||
(cond-> ["chip"]
|
||||
active (conj "chip-active")))
|
||||
|
||||
(defn chip-classes
|
||||
"Returns a space-joined class string."
|
||||
[opts]
|
||||
(str/join " " (chip-class-list opts)))
|
||||
|
||||
(defn chip
|
||||
"A small selectable button for tags, filters, presets.
|
||||
Props: :active, :dot-color, :on-click, :class, :attrs"
|
||||
[{:keys [active dot-color on-click class attrs] :as _props} & children]
|
||||
#?(:squint
|
||||
(let [classes (cond-> (chip-classes {:active active})
|
||||
class (str " " class))
|
||||
base-attrs (cond-> (merge {:class classes} attrs)
|
||||
on-click (assoc :on-click on-click))
|
||||
dot (when dot-color
|
||||
[:span {:class "chip-dot" :style {"background" dot-color}}])]
|
||||
(cond-> [:button base-attrs]
|
||||
dot (conj dot)
|
||||
true (into children)))
|
||||
|
||||
:cljs
|
||||
(let [cls (chip-class-list {:active active})
|
||||
classes (cond-> cls class (conj class))
|
||||
base-attrs (cond-> (merge {:class classes} attrs)
|
||||
on-click (assoc :on {:click on-click}))
|
||||
dot (when dot-color
|
||||
[:span {:class ["chip-dot"] :style {:background dot-color}}])]
|
||||
(cond-> [:button base-attrs]
|
||||
dot (conj dot)
|
||||
true (into children)))
|
||||
|
||||
:clj
|
||||
(let [classes (cond-> (chip-classes {:active active})
|
||||
class (str " " class))
|
||||
base-attrs (merge {:class classes} attrs)
|
||||
dot (when dot-color
|
||||
[:span {:class "chip-dot"
|
||||
:style (str "background:" dot-color)}])]
|
||||
(cond-> [:button base-attrs]
|
||||
dot (conj dot)
|
||||
true (into children)))))
|
||||
37
src/ui/chip.css
Normal file
37
src/ui/chip.css
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ── Chip ───────────────────────────────────────────────────────── */
|
||||
/* Small selectable buttons for tags, filters, presets. */
|
||||
|
||||
.chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--size-1);
|
||||
padding: var(--size-1) var(--size-2);
|
||||
font-size: var(--font-xs);
|
||||
font-weight: 500;
|
||||
line-height: var(--size-4);
|
||||
border: var(--border-0);
|
||||
border-radius: var(--radius-sm);
|
||||
background: transparent;
|
||||
color: var(--fg-1);
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
|
||||
}
|
||||
|
||||
.chip:hover:not(.chip-active) {
|
||||
background: var(--bg-2);
|
||||
}
|
||||
|
||||
.chip-active {
|
||||
background: var(--accent);
|
||||
border-color: var(--accent);
|
||||
color: var(--fg-on-accent);
|
||||
}
|
||||
|
||||
.chip-dot {
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 9999px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
12
src/ui/popover.css
Normal file
12
src/ui/popover.css
Normal file
@@ -0,0 +1,12 @@
|
||||
/* ── Popover ────────────────────────────────────────────────────── */
|
||||
/* Fixed-position floating panel. Combine with a corner class. */
|
||||
|
||||
.popover {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.popover-br { bottom: var(--size-4); right: var(--size-4); }
|
||||
.popover-bl { bottom: var(--size-4); left: var(--size-4); }
|
||||
.popover-tr { top: var(--size-4); right: var(--size-4); }
|
||||
.popover-tl { top: var(--size-4); left: var(--size-4); }
|
||||
13
src/ui/swatch.css
Normal file
13
src/ui/swatch.css
Normal file
@@ -0,0 +1,13 @@
|
||||
/* ── Swatch ─────────────────────────────────────────────────────── */
|
||||
/* Color preview strip — a row of small colored boxes. */
|
||||
|
||||
.swatch-row {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.swatch {
|
||||
flex: 1;
|
||||
height: var(--size-4);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
@@ -37,6 +37,19 @@
|
||||
.mb-6 { margin-bottom: var(--size-6); }
|
||||
.p-4 { padding: var(--size-4); }
|
||||
|
||||
.flex-1 { flex: 1; min-width: 0; }
|
||||
.shrink-0 { flex-shrink: 0; }
|
||||
.flex-row { flex-direction: row; }
|
||||
.flex-wrap { flex-wrap: wrap; }
|
||||
|
||||
.text-xs { font-size: var(--font-xs); }
|
||||
.text-sm { font-size: var(--font-sm); }
|
||||
.text-right { text-align: right; }
|
||||
.font-semibold { font-weight: 600; }
|
||||
.font-mono { font-family: ui-monospace, 'JetBrains Mono', monospace; }
|
||||
.uppercase { text-transform: uppercase; }
|
||||
.tracking-wide { letter-spacing: 0.05em; }
|
||||
|
||||
.w-full { width: 100%; }
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
|
||||
Reference in New Issue
Block a user