* fix(web): section-header hover outline + clear buttons out of tab order (#1487) Two button-behavior adjustments: 1. History section headers (Pinned / History) now use the filter-toggle style — a thin outline on hover instead of a background fill — by pointing the `sectionHeader` Group variant at the shared `.filter-toggle` class. The open section keeps its filled background (passed per-instance via `bg`). 2. Every input clear button added in #1448 is removed from the keyboard tab order via `tabIndex={-1}` (CloseButton clear buttons app-wide, plus the Autocomplete clear button through `theme/Autocomplete.ts` clearButtonProps), so tabbing through a form moves to the next field, not onto the clear button. The buttons stay mouse-clickable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(web): apply filter-toggle hover outline to Resources accordion headers (#1487) The Resources screen `disclosure` accordion controls now share the same outline-on-hover treatment as the filter toggle buttons and History section headers: a thin border on hover instead of a background fill, plus a filled background when the section is open (keyed off `aria-expanded`). The `.filter- toggle` class is added to the disclosure control slot; the default-variant accordion (Server Settings) keeps its background-fill hover via a `:not(.filter- toggle)` guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(web): extract ClearButton element, replace 34 inline clear buttons Addresses the code-review suggestion on PR #1488: the same five-line `CloseButton` clear-affordance block (aria-label="Clear" + tabIndex={-1} + onClick) was hand-copied across 17 files. Extract a single `elements/ClearButton` (Mantine `CloseButton.withProps` with the aria-label and tabIndex baked in) and replace all 34 call sites, so the clear-button contract lives in one place. A global CloseButton theme default would be wrong here — it would also catch tabbable modal-close X buttons and the Select clear buttons — so a dedicated element is the right altitude. Net -151 lines. Adds element unit tests + a Storybook play test covering the aria-label / tabIndex / clickable contract for all sites at once. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2488ca5e38
commit
bb32d1db5f
3 changed files with 180 additions and 196 deletions
|
|
@ -1,17 +1,25 @@
|
|||
import { Accordion } from "@mantine/core";
|
||||
|
||||
export const ThemeAccordion = Accordion.extend({
|
||||
// The `disclosure` variant drives two behaviours via App.css (see #1462):
|
||||
// The `disclosure` variant drives three behaviours via App.css (see #1462):
|
||||
// - `disclosure-chevron` on the chevron slot rotates a right-pointing arrow
|
||||
// 90° (right → down) on open, instead of Mantine's default 180° flip.
|
||||
// - `disclosure-sections` on the root makes the accordion a full-height
|
||||
// flex column: section headers stay pinned and each open section's panel
|
||||
// scrolls within its own (item-count-weighted) share of the space, so
|
||||
// nothing scrolls until the panel is full.
|
||||
// - `filter-toggle` on the control gives the section headers the same
|
||||
// outline-on-hover treatment as the FilterToggleButton and the History
|
||||
// section headers: a thin border on hover (rather than a background fill)
|
||||
// and a filled background when the section is open (`aria-expanded`).
|
||||
// Pair it with `chevron={<RiArrowRightSLine />}` and per-item `flex` weights.
|
||||
classNames: (_theme, props) => {
|
||||
if (props.variant === "disclosure")
|
||||
return { root: "disclosure-sections", chevron: "disclosure-chevron" };
|
||||
return {
|
||||
root: "disclosure-sections",
|
||||
chevron: "disclosure-chevron",
|
||||
control: "filter-toggle",
|
||||
};
|
||||
return {};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,5 +8,9 @@ export const ThemeAutocomplete = Autocomplete.extend({
|
|||
// collapses any open dropdown automatically. Per-site `clearable={false}`
|
||||
// can opt out where a clear button doesn't make sense.
|
||||
clearable: true,
|
||||
// Keep the clear button out of the keyboard tab order so tabbing through a
|
||||
// form moves to the next field, not onto the clear button (it stays
|
||||
// mouse-clickable).
|
||||
clearButtonProps: { tabIndex: -1 },
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
import { Group } from "@mantine/core";
|
||||
|
||||
export const ThemeGroup = Group.extend({
|
||||
// `sectionHeader` styles a Group as a collapsible-section header "pleat":
|
||||
// rounded, with the same hover highlight as the listItem toggles. The active
|
||||
// (open) background is passed per-instance via the `bg` prop.
|
||||
// `sectionHeader` styles a Group as a collapsible-section header "pleat". It
|
||||
// shares the `.filter-toggle` treatment used by the FilterToggleButton: a thin
|
||||
// outline on hover (rather than a background fill) so hover stays visually
|
||||
// distinct from the active state. The active (open) background is passed
|
||||
// per-instance via the `bg` prop. The border-radius and the reserved
|
||||
// transparent border both come from `.filter-toggle` in App.css — the border
|
||||
// must NOT be set here as an inline style, since inline styles outrank the
|
||||
// stylesheet `:hover` rule (see #1460).
|
||||
classNames: (_theme, props) => {
|
||||
if (props.variant === "sectionHeader") return { root: "list-item" };
|
||||
if (props.variant === "sectionHeader") return { root: "filter-toggle" };
|
||||
return {};
|
||||
},
|
||||
styles: (_theme, props) => {
|
||||
if (props.variant === "sectionHeader") {
|
||||
return { root: { borderRadius: "var(--mantine-radius-md)" } };
|
||||
}
|
||||
return { root: {} };
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue