Drop Cookies Settings from the footer, link the Home features that already have pages, and give leftover routes their own descriptions.
139 lines
4.0 KiB
TypeScript
139 lines
4.0 KiB
TypeScript
"use client";
|
|
|
|
import { memo } from "react";
|
|
import { useComponentId } from "../../../hooks";
|
|
import { CheckboxView } from "./Checkbox.view";
|
|
import type { CheckboxProps } from "./Checkbox.types";
|
|
|
|
/**
|
|
* Figma: "Control / Checkbox". Single boolean checkbox with
|
|
* optional label, supporting standard and inverse modes.
|
|
*/
|
|
const CheckboxContainer = memo<CheckboxProps>(
|
|
({
|
|
checked = false,
|
|
mode: modeProp = "standard",
|
|
state: stateProp = "default",
|
|
disabled = false,
|
|
label,
|
|
className = "",
|
|
onChange,
|
|
id,
|
|
name,
|
|
value,
|
|
ariaLabel,
|
|
...props
|
|
}) => {
|
|
const mode = modeProp;
|
|
const state = stateProp;
|
|
|
|
const isInverse = mode === "inverse";
|
|
const isStandard = mode === "standard";
|
|
|
|
// Generate unique ID for accessibility if not provided
|
|
const { id: checkboxId, labelId } = useComponentId("checkbox", id);
|
|
|
|
// Base box styles per Figma
|
|
const baseBox = `
|
|
flex
|
|
items-center
|
|
justify-center
|
|
shrink-0
|
|
w-[24px]
|
|
h-[24px]
|
|
rounded-[4px]
|
|
transition-all
|
|
duration-200
|
|
ease-in-out
|
|
`
|
|
.trim()
|
|
.replace(/\s+/g, " ");
|
|
|
|
// Get box styles based on state and checked status per Figma designs
|
|
const getBoxStyles = (): string => {
|
|
// Standard mode styles
|
|
if (isStandard) {
|
|
// Default state: tertiary border, with hover and focus states via CSS
|
|
// Hover changes border to brand primary color
|
|
// Focus removes border and shows shadow (double ring: 2px white inner, 4px dark outer)
|
|
return `${baseBox} bg-[var(--color-surface-default-primary)] border border-solid border-[var(--color-border-default-control)] hover:border-[var(--color-border-default-brand-primary)] focus:border-transparent focus:shadow-[var(--shadow-focus-invert)] focus:outline-none`;
|
|
}
|
|
|
|
// Inverse mode styles per Figma
|
|
if (isInverse) {
|
|
// Inverse: transparent background, white border
|
|
// Hover changes border to brand primary color
|
|
// Focus shows shadow (2px dark inner, 4px white outer) - note: reversed from standard
|
|
return `${baseBox} bg-transparent border border-solid border-[var(--color-border-invert-primary)] hover:border-[var(--color-border-default-brand-primary)] focus:shadow-[var(--shadow-focus-default)] focus:outline-none`;
|
|
}
|
|
|
|
return baseBox;
|
|
};
|
|
|
|
const combinedBoxStyles = getBoxStyles();
|
|
|
|
// Checkmark color per Figma
|
|
const checkGlyphColor = checked
|
|
? isStandard
|
|
? "var(--color-content-default-brand-primary)"
|
|
: "var(--color-content-invert-primary)"
|
|
: "transparent";
|
|
|
|
// Label color
|
|
const labelColor = isInverse
|
|
? "var(--color-content-invert-primary)"
|
|
: "var(--color-content-default-primary)";
|
|
|
|
const handleToggle = (e: React.MouseEvent | React.KeyboardEvent) => {
|
|
if (disabled) return;
|
|
onChange?.({
|
|
checked: !checked,
|
|
value,
|
|
event: e,
|
|
});
|
|
};
|
|
|
|
const accessibilityProps = {
|
|
role: "checkbox" as const,
|
|
"aria-checked": checked,
|
|
...(disabled && { "aria-disabled": true, tabIndex: -1 }),
|
|
...(!disabled && { tabIndex: 0 }),
|
|
...(ariaLabel && { "aria-label": ariaLabel }),
|
|
...(label && !ariaLabel && { "aria-labelledby": labelId }),
|
|
id: checkboxId,
|
|
...props,
|
|
};
|
|
|
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
if (e.key === " " || e.key === "Enter") {
|
|
e.preventDefault();
|
|
handleToggle(e);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<CheckboxView
|
|
labelId={labelId}
|
|
checked={checked}
|
|
mode={mode}
|
|
state={state}
|
|
disabled={disabled}
|
|
label={label}
|
|
name={name}
|
|
value={value}
|
|
className={className}
|
|
combinedBoxStyles={combinedBoxStyles}
|
|
checkGlyphColor={checkGlyphColor}
|
|
labelColor={labelColor}
|
|
accessibilityProps={accessibilityProps}
|
|
onToggle={handleToggle}
|
|
onKeyDown={handleKeyDown}
|
|
/>
|
|
);
|
|
},
|
|
);
|
|
|
|
CheckboxContainer.displayName = "Checkbox";
|
|
|
|
export default CheckboxContainer;
|