release: 0.60.9 (improvement/popover-selected-highlight)
This commit is contained in:
@@ -250,15 +250,20 @@ type ItemRole = "menuitem" | "menuitemradio" | "menuitemcheckbox" | "option";
|
||||
* focus-visible heuristic, so a `:focus-visible` highlight can stay invisible until the first arrow
|
||||
* key. (Since the Tailwind v4 migration `bg-accent/NN` works — v4 does the opacity modifier via
|
||||
* color-mix — so the recipe no longer needs a hand-written color-mix arbitrary value.) */
|
||||
// The roving-focus highlight, SPLIT by selection state (R9). A NON-selected row gets the familiar
|
||||
// accent fill + inset ring. A SELECTED/checked row gets ring-ONLY, so the consumer's own resting
|
||||
// selected paint (a bg-accent fill, text-accent, a checkbox) SURVIVES being highlighted instead of
|
||||
// being downgraded to a 35% tint or having its text recoloured (the R10-S0 review findings). The two
|
||||
// can't be merged onto one recipe: the fill and the selected paint both drive background/color on the
|
||||
// same element, so the highlight must yield to the selected state rather than overwrite it.
|
||||
// The roving-focus highlight. A hovered/roving row gets the SAME strong accent fill whether or not it
|
||||
// is selected — a checked row no longer reads as a weak ring-only afterthought (R10 weak-ring fix). The
|
||||
// selected state stays legible ON the fill because these menus mark "selected" with a CHILD element (a
|
||||
// checkmark / checkbox) that paints over the row tint; the selected row just gets a stronger ring
|
||||
// (ring-2, accent/80) than an unselected one (ring-1, accent/60) to keep the two apart.
|
||||
// EXCEPTION: a menu whose SELECTED item paints its OWN row background (a solid bg-accent — the
|
||||
// table-filter options) passes `keepSelectedPaint`, so the highlight yields to ring-only there; a fill
|
||||
// would downgrade that solid paint to a 35% tint (the R9 concern, now scoped to just that idiom).
|
||||
const HIGHLIGHT_UNSELECTED =
|
||||
"data-active:bg-accent/35 data-active:text-fg data-active:ring-1 data-active:ring-inset data-active:ring-accent/60";
|
||||
const HIGHLIGHT_SELECTED = "data-active:ring-2 data-active:ring-inset data-active:ring-accent/70";
|
||||
const HIGHLIGHT_SELECTED =
|
||||
"data-active:bg-accent/35 data-active:text-fg data-active:ring-2 data-active:ring-inset data-active:ring-accent/80";
|
||||
const HIGHLIGHT_SELECTED_RING_ONLY =
|
||||
"data-active:ring-2 data-active:ring-inset data-active:ring-accent/70";
|
||||
|
||||
export function PopoverItem({
|
||||
children,
|
||||
@@ -266,6 +271,7 @@ export function PopoverItem({
|
||||
role = "menuitem",
|
||||
checked,
|
||||
selected,
|
||||
keepSelectedPaint,
|
||||
disabled,
|
||||
className,
|
||||
/** Typeahead match string; defaults to the text child. Set explicitly when children aren't plain text. */
|
||||
@@ -277,6 +283,9 @@ export function PopoverItem({
|
||||
role?: ItemRole;
|
||||
checked?: boolean;
|
||||
selected?: boolean;
|
||||
/** Set when the SELECTED item paints its OWN row background (a solid bg-accent, not a child checkmark):
|
||||
* the active highlight then yields to ring-only so the fill doesn't downgrade that solid paint. */
|
||||
keepSelectedPaint?: boolean;
|
||||
disabled?: boolean;
|
||||
className?: string;
|
||||
label?: string;
|
||||
@@ -327,7 +336,13 @@ export function PopoverItem({
|
||||
tabIndex={focusActive ? 0 : -1}
|
||||
data-active={visualActive ? "true" : undefined}
|
||||
disabled={disabled}
|
||||
className={`outline-hidden ${checked || selected ? HIGHLIGHT_SELECTED : HIGHLIGHT_UNSELECTED}${className ? ` ${className}` : ""}`}
|
||||
className={`outline-hidden ${
|
||||
checked || selected
|
||||
? keepSelectedPaint
|
||||
? HIGHLIGHT_SELECTED_RING_ONLY
|
||||
: HIGHLIGHT_SELECTED
|
||||
: HIGHLIGHT_UNSELECTED
|
||||
}${className ? ` ${className}` : ""}`}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
|
||||
@@ -156,6 +156,7 @@ function FilterFunnel<T>({
|
||||
<PopoverItem
|
||||
role="menuitemradio"
|
||||
checked={!filterOn}
|
||||
keepSelectedPaint
|
||||
onSelect={() => onApply(col.key, "")}
|
||||
label={t("datatable.all")}
|
||||
className={`text-left text-xs px-2 py-1.5 rounded-md outline-hidden transition ${
|
||||
@@ -169,6 +170,7 @@ function FilterFunnel<T>({
|
||||
key={o.value}
|
||||
role="menuitemradio"
|
||||
checked={value === o.value}
|
||||
keepSelectedPaint
|
||||
onSelect={() => onApply(col.key, o.value)}
|
||||
label={o.label}
|
||||
className={`text-left text-xs px-2 py-1.5 rounded-md outline-hidden transition ${
|
||||
|
||||
@@ -14,6 +14,13 @@ export interface ReleaseEntry {
|
||||
}
|
||||
|
||||
export const RELEASE_NOTES: ReleaseEntry[] = [
|
||||
{
|
||||
version: "0.60.9",
|
||||
date: "2026-08-09",
|
||||
fixes: [
|
||||
"In dropdown menus, hovering an already-checked row now gives it the same vivid highlight as any other row, instead of only a faint outline.",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "0.60.8",
|
||||
date: "2026-08-09",
|
||||
|
||||
Reference in New Issue
Block a user