Files
community-rule/app/components/navigation/MenuItem/MenuItem.container.tsx
T
adilallo ca928e306b Match the 3 Nov color ramps and size-based strokes, and replace leftover palette hex with tokens.
Drop Cookies Settings from the footer, link the Home features that already have pages, and give leftover routes their own descriptions.
2026-11-05 15:37:55 -07:00

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;