Drop Cookies Settings from the footer, link the Home features that already have pages, and give leftover routes their own descriptions.
130 lines
4.4 KiB
TypeScript
130 lines
4.4 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* Figma: "Utility / Menu Item" (see registry)
|
|
*/
|
|
|
|
import { memo } from "react";
|
|
import MenuItemView from "./MenuItem.view";
|
|
import type { MenuItemProps } from "./MenuItem.types";
|
|
|
|
const MenuItemContainer = memo<MenuItemProps>(
|
|
({
|
|
href = "#",
|
|
buttonOnClick,
|
|
children,
|
|
state: stateProp,
|
|
mode: modeProp,
|
|
icon: _icon = false,
|
|
size: sizeProp = "X Small",
|
|
className = "",
|
|
disabled = false,
|
|
reducedPadding = false,
|
|
ariaLabel,
|
|
...props
|
|
}) => {
|
|
const state = stateProp ?? "default";
|
|
const mode = modeProp ?? "default";
|
|
const size = sizeProp ?? "X Small";
|
|
|
|
// Size styles based on Figma specifications
|
|
const sizeStyles: Record<
|
|
"X Small" | "Small" | "Medium" | "Large" | "X Large",
|
|
string
|
|
> = {
|
|
"X Small": reducedPadding
|
|
? "px-[var(--space-100)] py-[var(--space-050)]"
|
|
: "px-[var(--space-100)] py-[var(--space-050)]",
|
|
Small: "px-[var(--space-100)] py-[var(--space-050)]",
|
|
Medium: reducedPadding
|
|
? "px-[var(--space-050)] py-[var(--space-200)] h-[32px]"
|
|
: "px-[var(--space-200)] py-[var(--space-200)] h-[32px]",
|
|
Large:
|
|
"px-[var(--space-400)] py-[var(--space-400)] h-[44px]",
|
|
"X Large":
|
|
"px-[var(--space-400)] py-[var(--space-400)] h-[44px]",
|
|
};
|
|
|
|
// Text styles based on Figma specifications
|
|
const textStyles: Record<
|
|
"X Small" | "Small" | "Medium" | "Large" | "X Large",
|
|
string
|
|
> = {
|
|
"X Small":
|
|
"text-xx-small-label",
|
|
Small: "text-x-small-label",
|
|
Medium: "text-x-small-label",
|
|
Large: "text-medium-label",
|
|
"X Large":
|
|
"text-x-large-label",
|
|
};
|
|
|
|
// State styles for Default mode (yellow text on dark background)
|
|
const defaultModeStyles: Record<"default" | "hover" | "selected", string> =
|
|
{
|
|
default:
|
|
"bg-transparent text-[var(--color-content-default-brand-primary)] hover:bg-[var(--color-gray-800)] hover:text-[var(--color-content-default-brand-primary)]",
|
|
hover:
|
|
"bg-[var(--color-gray-800)] text-[var(--color-content-default-brand-primary)]",
|
|
selected:
|
|
"border border-[var(--color-border-default-brand-primary)] text-[var(--color-content-default-brand-primary)] bg-transparent hover:bg-[var(--color-gray-800)]",
|
|
};
|
|
|
|
// State styles for Inverse mode (black text on yellow HeaderTab / inverse surfaces)
|
|
const inverseModeStyles: Record<"default" | "hover" | "selected", string> =
|
|
{
|
|
default:
|
|
"bg-transparent text-[var(--color-content-invert-primary)] hover:bg-[var(--color-surface-invert-brand-secondary)] hover:text-[var(--color-content-invert-primary)]",
|
|
hover:
|
|
"bg-[var(--color-surface-invert-brand-secondary)] text-[var(--color-content-invert-primary)]",
|
|
selected:
|
|
"border border-[var(--color-border-default-primary)] text-[var(--color-content-invert-primary)] bg-transparent hover:bg-[var(--color-surface-invert-brand-secondary)]",
|
|
};
|
|
|
|
// Get state styles based on mode
|
|
const stateStyles =
|
|
mode === "inverse" ? inverseModeStyles : defaultModeStyles;
|
|
|
|
// Base styles
|
|
const baseStyles = `inline-flex items-center whitespace-nowrap ${sizeStyles[size]} ${textStyles[size]} rounded-[var(--radius-full)] transition-all duration-200 ease-in-out cursor-pointer`;
|
|
|
|
// Interactive styles
|
|
const interactiveStyles =
|
|
"active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed disabled:active:scale-100";
|
|
|
|
// Disabled styles
|
|
const disabledStyles = disabled
|
|
? "bg-[var(--color-surface-default-tertiary)] text-[var(--color-content-default-tertiary)]"
|
|
: "";
|
|
|
|
// Combine all styles
|
|
const combinedStyles = `${baseStyles} ${stateStyles[state]} ${interactiveStyles} ${disabledStyles} ${className}`;
|
|
|
|
const accessibilityProps = {
|
|
...(ariaLabel && { "aria-label": ariaLabel }),
|
|
...(disabled && { "aria-disabled": true }),
|
|
...(state === "selected" && { "aria-current": "page" as const }),
|
|
role: "menuitem" as const,
|
|
tabIndex: disabled ? -1 : 0,
|
|
...props,
|
|
};
|
|
|
|
return (
|
|
<MenuItemView
|
|
href={href}
|
|
buttonOnClick={buttonOnClick}
|
|
disabled={disabled}
|
|
className={className}
|
|
combinedStyles={combinedStyles}
|
|
accessibilityProps={accessibilityProps}
|
|
>
|
|
{children}
|
|
</MenuItemView>
|
|
);
|
|
},
|
|
);
|
|
|
|
MenuItemContainer.displayName = "MenuItem";
|
|
|
|
export default MenuItemContainer;
|