55 lines
2.0 KiB
TypeScript
55 lines
2.0 KiB
TypeScript
import type { MouseEvent, ReactNode } from "react";
|
||
import { cn } from "@/lib/utils";
|
||
|
||
interface Props {
|
||
children: ReactNode;
|
||
/**
|
||
* Click handler. Receives the underlying React mouse event so we can
|
||
* call `e.stopPropagation()` before invoking the caller's logic — see
|
||
* the JSDoc on the component for why this matters when a DrillableCell
|
||
* is nested inside a row-level click handler.
|
||
*/
|
||
onClick: (e: MouseEvent<HTMLButtonElement>) => void;
|
||
disabled?: boolean;
|
||
/** Optional aria-label; defaults to the visible text content. */
|
||
ariaLabel?: string;
|
||
}
|
||
|
||
/**
|
||
* Wrap any clickable cell with hover-reveal affordance:
|
||
* cursor: pointer + accent background tint + trailing "›" chevron,
|
||
* applied via the `drillable` class on hover (see `src/index.css`
|
||
* in Task 1.4).
|
||
*
|
||
* Renders as a <button> (disabled when `disabled`) so it gets keyboard
|
||
* activation (Enter/Space) and the standard disabled-button semantics.
|
||
* The `drillable` affordance class is omitted when disabled.
|
||
*
|
||
* Calls `e.stopPropagation()` on the button click before invoking the
|
||
* caller's handler. This prevents the click from bubbling to a
|
||
* row-level `onClick` (e.g. Claims' `<TableRow onClick={() => open(c.id)}>`),
|
||
* which would otherwise re-fire `buildUrl()` on the now-navigated URL
|
||
* and corrupt history. Precedent: `src/components/inbox/Lane.tsx:41`.
|
||
*/
|
||
export function DrillableCell({ children, onClick, disabled, ariaLabel }: Props) {
|
||
return (
|
||
<button
|
||
type="button"
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onClick(e);
|
||
}}
|
||
disabled={disabled}
|
||
aria-label={ariaLabel}
|
||
className={cn(
|
||
!disabled && "drillable",
|
||
"inline-flex items-center gap-0 rounded-sm border-0 bg-transparent p-0 text-left",
|
||
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
||
disabled && "text-muted-foreground cursor-not-allowed",
|
||
)}
|
||
>
|
||
{children}
|
||
</button>
|
||
);
|
||
}
|