feat: add focus-visible rings and refactor accordion chevron
Add global :focus-visible outline style and migrate form components from :focus box-shadow to :focus-visible outline. Refactor accordion chevron from CSS ::after pseudo-element to explicit span element.
This commit is contained in:
@@ -26,7 +26,9 @@
|
|||||||
base-attrs (cond-> (merge {:class classes} attrs)
|
base-attrs (cond-> (merge {:class classes} attrs)
|
||||||
open (assoc :open true))]
|
open (assoc :open true))]
|
||||||
[:details base-attrs
|
[:details base-attrs
|
||||||
[:summary {:class "accordion-trigger"} title]
|
[:summary {:class "accordion-trigger"}
|
||||||
|
[:span {:class "accordion-trigger-text"} title]
|
||||||
|
[:span {:class "accordion-chevron" :aria-hidden "true"}]]
|
||||||
(into [:div {:class "accordion-content"}] children)])
|
(into [:div {:class "accordion-content"}] children)])
|
||||||
|
|
||||||
:cljs
|
:cljs
|
||||||
@@ -35,7 +37,9 @@
|
|||||||
base-attrs (cond-> (merge {:class classes} attrs)
|
base-attrs (cond-> (merge {:class classes} attrs)
|
||||||
open (assoc :open true))]
|
open (assoc :open true))]
|
||||||
[:details base-attrs
|
[:details base-attrs
|
||||||
[:summary {:class ["accordion-trigger"]} title]
|
[:summary {:class ["accordion-trigger"]}
|
||||||
|
[:span {:class ["accordion-trigger-text"]} title]
|
||||||
|
[:span {:class ["accordion-chevron"] :aria-hidden "true"}]]
|
||||||
(into [:div {:class ["accordion-content"]}] children)])
|
(into [:div {:class ["accordion-content"]}] children)])
|
||||||
|
|
||||||
:clj
|
:clj
|
||||||
@@ -44,5 +48,7 @@
|
|||||||
base-attrs (cond-> (merge {:class classes} attrs)
|
base-attrs (cond-> (merge {:class classes} attrs)
|
||||||
open (assoc :open true))]
|
open (assoc :open true))]
|
||||||
[:details base-attrs
|
[:details base-attrs
|
||||||
[:summary {:class "accordion-trigger"} title]
|
[:summary {:class "accordion-trigger"}
|
||||||
|
[:span {:class "accordion-trigger-text"} title]
|
||||||
|
[:span {:class "accordion-chevron" :aria-hidden "true"}]]
|
||||||
(into [:div {:class "accordion-content"}] children)])))
|
(into [:div {:class "accordion-content"}] children)])))
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.accordion-trigger:focus-visible {
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
.accordion + .accordion {
|
.accordion + .accordion {
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
@@ -25,7 +29,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: var(--size-2);
|
gap: var(--size-2);
|
||||||
width: 100%;
|
|
||||||
padding: var(--size-4);
|
padding: var(--size-4);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
@@ -50,15 +53,20 @@
|
|||||||
background: var(--bg-1);
|
background: var(--bg-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-trigger::after {
|
.accordion-trigger-text {
|
||||||
content: "";
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-chevron {
|
||||||
|
display: block;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background-color: currentColor;
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
||||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
background-size: contain;
|
||||||
mask-size: contain;
|
background-repeat: no-repeat;
|
||||||
mask-repeat: no-repeat;
|
background-position: center;
|
||||||
transition: transform 150ms ease;
|
transition: transform 150ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +74,7 @@
|
|||||||
border-bottom: var(--border-0);
|
border-bottom: var(--border-0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion[open] > .accordion-trigger::after {
|
.accordion[open] > .accordion-trigger .accordion-chevron {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,17 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
background: var(--bg-0);
|
background: var(--bg-0);
|
||||||
color: var(--fg-0);
|
color: var(--fg-0);
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus-visible {
|
||||||
|
outline: 2px solid var(--accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus:not(:focus-visible) {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
}")
|
}")
|
||||||
|
|
||||||
(defn collect-component-css
|
(defn collect-component-css
|
||||||
|
|||||||
@@ -23,10 +23,10 @@
|
|||||||
border-color: var(--danger);
|
border-color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field--error .form-input:focus,
|
.form-field--error .form-input:focus-visible,
|
||||||
.form-field--error .form-textarea:focus,
|
.form-field--error .form-textarea:focus-visible,
|
||||||
.form-field--error .form-select:focus {
|
.form-field--error .form-select:focus-visible {
|
||||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 20%, transparent);
|
outline-color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Label ─────────────────────────────────────────────────────── */
|
/* ── Label ─────────────────────────────────────────────────────── */
|
||||||
@@ -60,12 +60,11 @@
|
|||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input:focus,
|
.form-input:focus-visible,
|
||||||
.form-textarea:focus,
|
.form-textarea:focus-visible,
|
||||||
.form-select:focus {
|
.form-select:focus-visible {
|
||||||
outline: none;
|
|
||||||
border-color: var(--accent);
|
border-color: var(--accent);
|
||||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
|
outline-offset: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input:disabled,
|
.form-input:disabled,
|
||||||
@@ -81,9 +80,9 @@
|
|||||||
border-color: var(--danger);
|
border-color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input--error:focus,
|
.form-input--error:focus-visible,
|
||||||
.form-textarea--error:focus {
|
.form-textarea--error:focus-visible {
|
||||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 20%, transparent);
|
outline-color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Textarea ──────────────────────────────────────────────────── */
|
/* ── Textarea ──────────────────────────────────────────────────── */
|
||||||
@@ -148,10 +147,9 @@
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-checkbox:focus,
|
.form-checkbox:focus-visible,
|
||||||
.form-radio:focus {
|
.form-radio:focus-visible {
|
||||||
outline: none;
|
outline-offset: 0;
|
||||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-checkbox:disabled,
|
.form-checkbox:disabled,
|
||||||
|
|||||||
Reference in New Issue
Block a user