diff --git a/apps/as/src/pages/dashboard/lib/national-as-map.module.css b/apps/as/src/pages/dashboard/lib/national-as-map.module.css index 459855e88..7dd85de3e 100644 --- a/apps/as/src/pages/dashboard/lib/national-as-map.module.css +++ b/apps/as/src/pages/dashboard/lib/national-as-map.module.css @@ -78,6 +78,15 @@ opacity: 1; } +.svgContainer :global(svg) :global(.basin:focus-visible) { + opacity: 1; +} + +.svgContainer :global(svg) :global(.basin:focus-visible) :global(path) { + stroke: #111827; + stroke-width: 2.5; +} + .svgContainer :global(svg) :global(.basin) :global(path), .svgContainer :global(svg) :global(.basin) :global(polygon), .svgContainer :global(svg) :global(.basin) :global(polyline) { diff --git a/apps/as/src/pages/dashboard/lib/use-national-as-map.ts b/apps/as/src/pages/dashboard/lib/use-national-as-map.ts index c46748ba2..60d12b752 100644 --- a/apps/as/src/pages/dashboard/lib/use-national-as-map.ts +++ b/apps/as/src/pages/dashboard/lib/use-national-as-map.ts @@ -265,20 +265,44 @@ export function useNationalAsMap(basinDocPrgrsList: BasinDocPrgrsResponseDto[] | }; groups.forEach((group) => { - addListener(group, "mouseenter", () => { + group.setAttribute("role", "button"); + group.setAttribute("tabindex", "0"); + group.setAttribute( + "aria-label", + `${resolveBasinName(group)} 행정지원 현황 보기`, + ); + + const activateGroup = () => { clearActive?.(); group.classList.add("active"); revealGroup(group); + }; + const clearGroupIfInactive = () => { + if (!group.matches(":hover") && document.activeElement !== group) { + clearActive?.(); + } + }; + + addListener(group, "mouseenter", () => { + activateGroup(); }); addListener(group, "mousemove", () => { if (group.classList.contains("active")) revealGroup(group); }); - addListener(group, "mouseleave", () => clearActive?.()); + addListener(group, "mouseleave", clearGroupIfInactive); + addListener(group, "focus", activateGroup); + addListener(group, "blur", clearGroupIfInactive); addListener(group, "click", (event) => { event.stopPropagation(); - clearActive?.(); - group.classList.add("active"); - revealGroup(group); + activateGroup(); + }); + addListener(group, "keydown", (event) => { + const keyboardEvent = event as KeyboardEvent; + if (keyboardEvent.key !== "Enter" && keyboardEvent.key !== " ") { + return; + } + keyboardEvent.preventDefault(); + activateGroup(); }); }); diff --git a/packages/common/components/src/ui/data-table/index.tsx b/packages/common/components/src/ui/data-table/index.tsx index 54e399474..9ed2f9b20 100644 --- a/packages/common/components/src/ui/data-table/index.tsx +++ b/packages/common/components/src/ui/data-table/index.tsx @@ -58,8 +58,16 @@ function DataTable({ onRowClick?.(row.original)} + onKeyDown={(event) => { + if (event.target !== event.currentTarget) return; + if (event.key !== "Enter" && event.key !== " ") return; + event.preventDefault(); + onRowClick?.(row.original); + }} + tabIndex={onRowClick ? 0 : undefined} className={cn( - onRowClick && "cursor-pointer hover:bg-accent", + onRowClick && + "cursor-pointer hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary", isSelectedRow && "!bg-primary-transparent", )} >