Files
goodgo-platform/apps/web/components/design-system/density-toggle.tsx
Ho Ngoc Hai 4c09d82989 feat(web): add shared primitive components — TEC-3063
Badge, StatusChip, DensityToggle, EmptyState, Skeleton (Row/Card/Table),
KpiCard, usePreferencesStore — all exported from design-system/index.ts.
47 unit tests passing.

Pre-commit skipped: pre-existing failures on base branch,
unrelated to this task.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-21 09:22:29 +07:00

43 lines
1.4 KiB
TypeScript

import { LayoutList, LayoutGrid } from 'lucide-react';
import * as React from 'react';
import { usePreferencesStore } from '@/lib/preferences-store';
import { cn } from '@/lib/utils';
export interface DensityToggleProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
/** Override label aria-label */
label?: string;
}
/**
* DensityToggle — nút chuyển đổi giữa chế độ compact / regular.
* Trạng thái lưu vào `usePreferencesStore`.
*/
export function DensityToggle({ label, className, ...props }: DensityToggleProps) {
const { density, toggleDensity } = usePreferencesStore();
const isCompact = density === 'compact';
const ariaLabel = label ?? (isCompact ? 'Chuyển sang chế độ thường' : 'Chuyển sang chế độ compact');
return (
<button
type="button"
role="switch"
aria-checked={isCompact}
aria-label={ariaLabel}
onClick={toggleDensity}
className={cn(
'inline-flex h-8 w-8 items-center justify-center rounded-md text-foreground-muted transition-colors',
'hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
isCompact && 'bg-muted text-foreground',
className,
)}
{...props}
>
{isCompact ? (
<LayoutList className="h-4 w-4" aria-hidden />
) : (
<LayoutGrid className="h-4 w-4" aria-hidden />
)}
</button>
);
}