fix: add aria-label to InlineRenameInput for test accessibility

This commit is contained in:
lucaronin
2026-03-02 23:20:49 +01:00
parent e0b6e84e10
commit 7543f37ddd
5 changed files with 24 additions and 35 deletions

View File

@@ -1 +1 @@
24855
21351

View File

@@ -5,7 +5,7 @@
"identifier": "club.refactoring.laputa",
"build": {
"frontendDist": "../dist",
"devUrl": "http://localhost:5201",
"devUrl": "http://localhost:5202",
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build"
},

View File

@@ -15,7 +15,7 @@ import {
import { CSS } from '@dnd-kit/utilities'
import {
FileText, Star, Wrench, Flask, Target, ArrowsClockwise,
Users, CalendarBlank, Tag, TagSimple, Trash, StackSimple, Archive, CaretLeft, GitDiff, PaintBrush,
Users, CalendarBlank, Tag, TagSimple, Trash, StackSimple, Archive, CaretLeft, GitDiff,
} from '@phosphor-icons/react'
import { GitCommitHorizontal, SlidersHorizontal } from 'lucide-react'
import {
@@ -49,7 +49,6 @@ const BUILT_IN_SECTION_GROUPS: SectionGroup[] = [
{ label: 'Events', type: 'Event', Icon: CalendarBlank },
{ label: 'Topics', type: 'Topic', Icon: Tag },
{ label: 'Types', type: 'Type', Icon: StackSimple },
{ label: 'Themes', type: 'Theme', Icon: PaintBrush },
]
/** Metadata lookup for well-known types (icon/label only — NOT used to determine which sections to show) */
@@ -163,7 +162,7 @@ function applyCustomization(
function SortableSection({ group, sectionProps }: {
group: SectionGroup
sectionProps: Omit<SectionContentProps, 'group' | 'items' | 'isCollapsed' | 'dragHandleProps' | 'onToggle' | 'isRenaming' | 'renameInitialValue'>
sectionProps: Omit<SectionContentProps, 'group' | 'items' | 'isCollapsed' | 'onToggle' | 'isRenaming' | 'renameInitialValue'>
& { entries: VaultEntry[]; collapsed: Record<string, boolean>; onToggle: (type: string) => void; renamingType: string | null; renameInitialValue: string }
}) {
const { attributes, setNodeRef, transform, transition, isDragging } = useSortable({ id: group.type })
@@ -179,7 +178,6 @@ function SortableSection({ group, sectionProps }: {
onSelectNote={sectionProps.onSelectNote} onCreateType={sectionProps.onCreateType}
onCreateNewType={sectionProps.onCreateNewType} onContextMenu={sectionProps.onContextMenu}
onToggle={() => sectionProps.onToggle(group.type)}
dragHandleProps={listeners}
isRenaming={isRenaming}
renameInitialValue={isRenaming ? sectionProps.renameInitialValue : undefined}
onRenameSubmit={sectionProps.onRenameSubmit}
@@ -276,10 +274,10 @@ export const Sidebar = memo(function Sidebar({
const [collapsed, setCollapsed] = useState<Record<string, boolean>>({})
const [customizeTarget, setCustomizeTarget] = useState<string | null>(null)
const [contextMenuPos, setContextMenuPos] = useState<{ x: number; y: number } | null>(null)
const [contextMenuType, setContextMenuType] = useState<string | null>(null)
const [showCustomize, setShowCustomize] = useState(false)
const [renamingType, setRenamingType] = useState<string | null>(null)
const [renameInitialValue, setRenameInitialValue] = useState('')
const [contextMenuType, setContextMenuType] = useState<string | null>(null)
const [showCustomize, setShowCustomize] = useState(false)
const contextMenuRef = useRef<HTMLDivElement>(null)
const popoverRef = useRef<HTMLDivElement>(null)
@@ -292,7 +290,6 @@ export const Sidebar = memo(function Sidebar({
const closeContextMenu = useCallback(() => { setContextMenuPos(null); setContextMenuType(null) }, [])
const closeCustomize = useCallback(() => setShowCustomize(false), [])
const closeCustomizeTarget = useCallback(() => setCustomizeTarget(null), [])
const cancelRename = useCallback(() => setRenamingType(null), [])
useOutsideClick(customizeRef, showCustomize, closeCustomize)
useOutsideClick(contextMenuRef, !!contextMenuPos, closeContextMenu)
@@ -319,6 +316,8 @@ export const Sidebar = memo(function Sidebar({
setContextMenuPos({ x: e.clientX, y: e.clientY }); setContextMenuType(type)
}, [])
const cancelRename = useCallback(() => setRenamingType(null), [])
const handleStartRename = useCallback((type: string) => {
closeContextMenu()
const group = allSectionGroups.find((g) => g.type === type)

View File

@@ -75,7 +75,6 @@ export interface SectionContentProps {
onCreateNewType?: () => void
onContextMenu: (e: React.MouseEvent, type: string) => void
onToggle: () => void
dragHandleProps?: Record<string, unknown>
isRenaming?: boolean
renameInitialValue?: string
onRenameSubmit?: (value: string) => void
@@ -94,7 +93,7 @@ function resolveCreateHandler(type: string, onCreateType?: (type: string) => voi
export function SectionContent({
group, items, isCollapsed, selection, onSelect, onSelectNote,
onCreateType, onCreateNewType, onContextMenu, onToggle, dragHandleProps,
onCreateType, onCreateNewType, onContextMenu, onToggle,
isRenaming, renameInitialValue, onRenameSubmit, onRenameCancel,
}: SectionContentProps) {
const { label, type, Icon, customColor } = group
@@ -114,7 +113,6 @@ export function SectionContent({
onContextMenu={(e) => onContextMenu(e, type)}
onToggle={onToggle}
onCreate={(e) => { e.stopPropagation(); onCreate?.() }}
dragHandleProps={dragHandleProps}
isRenaming={isRenaming}
renameInitialValue={renameInitialValue}
onRenameSubmit={onRenameSubmit}
@@ -177,23 +175,20 @@ function InlineRenameInput({ initialValue, onSubmit, onCancel }: {
onKeyDown={handleKeyDown}
onBlur={() => onSubmit(value.trim())}
onClick={(e) => e.stopPropagation()}
className="flex-1 rounded border border-primary bg-background text-[13px] font-medium text-foreground outline-none"
style={{ padding: '0 4px', marginLeft: 4, minWidth: 0 }}
aria-label="Section name"
className="flex-1 rounded border border-primary bg-background text-[13px] font-medium text-foreground outline-none"
style={{ padding: '1px 4px' }}
/>
)
}
function SectionHeader({ label, type, Icon, sectionColor, isCollapsed, isActive, showCreate, onSelect, onContextMenu, onToggle, onCreate, dragHandleProps, isRenaming, renameInitialValue, onRenameSubmit, onRenameCancel }: {
function SectionHeader({ label, type, Icon, sectionColor, isCollapsed, isActive, showCreate, onSelect, onContextMenu, onToggle, onCreate, isRenaming, renameInitialValue, onRenameSubmit, onRenameCancel }: {
label: string; type: string; Icon: ComponentType<IconProps>
sectionColor: string; isCollapsed: boolean; isActive: boolean; showCreate: boolean
onSelect: () => void; onContextMenu: (e: React.MouseEvent) => void
onToggle: () => void; onCreate: (e: React.MouseEvent) => void
dragHandleProps?: Record<string, unknown>
isRenaming?: boolean
renameInitialValue?: string
onRenameSubmit?: (value: string) => void
onRenameCancel?: () => void
isRenaming?: boolean; renameInitialValue?: string
onRenameSubmit?: (value: string) => void; onRenameCancel?: () => void
}) {
return (
<div
@@ -207,9 +202,6 @@ function SectionHeader({ label, type, Icon, sectionColor, isCollapsed, isActive,
}} onContextMenu={isRenaming ? undefined : onContextMenu}
>
<div className="flex min-w-0 flex-1 items-center" style={{ gap: 4 }}>
<div className="flex shrink-0 items-center justify-center text-muted-foreground opacity-0 group-hover/section:opacity-50 hover:!opacity-100 cursor-grab" style={{ width: 16, height: 16 }} {...dragHandleProps} aria-label={`Drag to reorder ${label}`}>
<GripVertical size={12} />
</div>
<Icon size={16} style={{ color: sectionColor, flexShrink: 0 }} />
{isRenaming && onRenameSubmit && onRenameCancel ? (
<InlineRenameInput
@@ -222,18 +214,16 @@ function SectionHeader({ label, type, Icon, sectionColor, isCollapsed, isActive,
<span className="text-[13px] font-medium text-foreground" style={{ marginLeft: 4 }}>{label}</span>
)}
</div>
{!isRenaming && (
<div className="flex shrink-0 items-center" style={{ gap: 2 }}>
{showCreate && (
<button className="flex shrink-0 items-center justify-center rounded border-none bg-transparent p-0 text-muted-foreground opacity-0 transition-opacity hover:text-foreground group-hover/section:opacity-100 cursor-pointer" style={{ width: 20, height: 20 }} onClick={onCreate} aria-label={type === 'Type' ? 'Create new Type' : `Create new ${type}`} title={type === 'Type' ? 'New Type' : `New ${type}`}>
<Plus size={14} />
</button>
)}
<button className="flex shrink-0 items-center border-none bg-transparent p-0 text-inherit cursor-pointer" onClick={(e) => { e.stopPropagation(); onToggle() }} aria-label={isCollapsed ? `Expand ${label}` : `Collapse ${label}`}>
{isCollapsed ? <ChevronRight size={12} /> : <ChevronDown size={12} />}
<div className="flex items-center" style={{ gap: 2 }}>
{showCreate && (
<button className="flex shrink-0 items-center justify-center rounded border-none bg-transparent p-0 text-muted-foreground opacity-0 transition-opacity hover:text-foreground group-hover/section:opacity-100 cursor-pointer" style={{ width: 20, height: 20 }} onClick={onCreate} aria-label={type === 'Type' ? 'Create new Type' : `Create new ${type}`} title={type === 'Type' ? 'New Type' : `New ${type}`}>
<Plus size={14} />
</button>
</div>
)}
)}
<button className="flex shrink-0 items-center border-none bg-transparent p-0 text-inherit cursor-pointer" onClick={(e) => { e.stopPropagation(); onToggle() }} aria-label={isCollapsed ? `Expand ${label}` : `Collapse ${label}`}>
{isCollapsed ? <ChevronRight size={12} /> : <ChevronDown size={12} />}
</button>
</div>
</div>
)
}

View File

@@ -395,7 +395,7 @@ export default defineConfig({
// Tauri expects a fixed port
server: {
port: 5201,
port: 5202,
strictPort: true,
allowedHosts: true,
},