Restore the sub-option indent on filter toggle rows

Tailwind v4 emits px-2 as padding-inline, which outranks the physical pl-6
override, so the indented row rendered flush with its siblings. Split the
base padding so the indent actually applies.

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Neil
2026-08-04 00:53:39 -07:00
co-authored by Orca
parent 4de70b0add
commit d7d55c893b
2 changed files with 65 additions and 2 deletions
@@ -0,0 +1,61 @@
// @vitest-environment happy-dom
/**
* Guards the sub-option indent: Tailwind v4 emits `px-*` as `padding-inline`,
* which outranks a physical `pl-*` override and silently flattens the nesting.
*/
import { act } from 'react'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { FilterToggleRow } from './FilterToggleRow'
let container: HTMLDivElement
let root: Root
function renderRow(indented: boolean): HTMLElement {
act(() => {
root.render(
<FilterToggleRow
icon={null}
label="Row"
checked={false}
onChange={vi.fn()}
indented={indented}
/>
)
})
const row = container.querySelector('[role="switch"]')
if (!(row instanceof HTMLElement)) {
throw new Error('FilterToggleRow did not render a switch')
}
return row
}
function paddingClasses(row: HTMLElement): string[] {
return row.className.split(/\s+/).filter((cls) => /^p[xlr]?-/.test(cls))
}
beforeEach(() => {
container = document.createElement('div')
document.body.appendChild(container)
root = createRoot(container)
})
afterEach(() => {
act(() => root.unmount())
container.remove()
})
describe('FilterToggleRow', () => {
it('indents a sub-option past the row above it', () => {
const indented = paddingClasses(renderRow(true))
const flat = paddingClasses(renderRow(false))
expect(indented).toContain('pl-7')
expect(flat).toContain('pl-2')
})
it('never pairs the indent with a padding-inline utility that would outrank it', () => {
expect(paddingClasses(renderRow(true)).filter((cls) => cls.startsWith('px-'))).toEqual([])
})
})
@@ -34,8 +34,10 @@ export function FilterToggleRow({
aria-label={ariaLabel}
onClick={() => onChange(!checked)}
className={cn(
'flex w-full items-center justify-between gap-2 rounded-[5px] px-2 py-1.5 text-[12px] font-medium hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
indented && 'pl-6'
// Why pl-* and not px-2 + pl-6: Tailwind v4 emits px as padding-inline,
// which outranks a physical pl-6 override and flattens the indent.
'flex w-full items-center justify-between gap-2 rounded-[5px] py-1.5 pr-2 text-[12px] font-medium hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
indented ? 'pl-7' : 'pl-2'
)}
>
<span