import * as stylex from "@stylexjs/stylex"; import { type ButtonHTMLAttributes, type DetailedHTMLProps, type PropsWithChildren, type ReactElement, memo, } from "react"; import { color, controlWeight, font, fontSize, size } from "./tokens.stylex"; import ToggleSliderInput from "./ToggleSliderInput"; const CAN_HOVER = "@media (hover: hover)"; const styles = stylex.create({ list: { width: "100%", padding: "0", margin: "0", display: "flex", flexDirection: "column", }, noBorder: { borderStyle: "none", }, item: { backgroundColor: color.gray500, borderBottomWidth: { default: "0px", ":not(:last-child)": "1px", }, borderBottomStyle: { default: "none", ":not(:last-child)": "solid", }, borderBottomColor: { default: "transparent", ":not(:last-child)": color.gray400, }, }, text: { padding: size.px4, }, heading: { backgroundColor: color.transparent, }, critical: { color: color.red150, }, stack: { display: "flex", flexDirection: "column", gap: size.px4, width: "100%", }, labelContent: { flex: "1", }, buttonColumns: { display: "flex", gap: size.px4, width: "100%", }, buttonBase: { fontFamily: font.main, fontSize: fontSize.body, fontWeight: controlWeight.button, // TODO: color padding: size.px4, display: "flex", alignItems: "center", gap: size.px4, cursor: "pointer", backgroundColor: { default: color.gray500, ":active": color.gray400, [CAN_HOVER]: { ":hover": color.gray400, }, }, }, icon: { display: "flex", fontSize: "120%", // TODO: ASK-UX proportional icon size? }, columnButton: { flexDirection: "column", flex: "1", cursor: "pointer", backgroundColor: { default: color.gray500, ":active": color.gray400, [CAN_HOVER]: { ":hover": color.gray400, }, }, }, largeIcon: { display: "flex", fontSize: "150%", // TODO: ASK-UX proportional icon size? }, disabled: {}, }); export type DrawerListProps = PropsWithChildren; /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export const DrawerList = memo(function DrawerList({ children, }: DrawerListProps) { return
{children}
; }); export type DrawerListItemProps = PropsWithChildren; /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export const DrawerListItem = memo(function DrawerListItem({ children, }: DrawerListItemProps) { return (
{children}
); }); export interface DrawerListTextItemProps extends PropsWithChildren { heading?: boolean; } /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export const DrawerListTextItem = memo(function DrawerListTextItem({ heading, children, }: DrawerListTextItemProps) { return (
{children}
); }); type NativeButtonProps = DetailedHTMLProps< ButtonHTMLAttributes, HTMLButtonElement >; /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export interface DrawerListButtonItemProps extends PropsWithChildren { type?: NativeButtonProps["type"]; role?: NativeButtonProps["role"]; icon?: ReactElement; onClick?: () => void; critical?: boolean; // TODO: // disabled // title } /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export const DrawerListButtonItem = memo(function DrawerListTextItem({ type, role, icon, onClick, critical, children, }: DrawerListButtonItemProps) { return ( ); }); export type DrawerStackProps = PropsWithChildren; /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export const DrawerStack = memo(function DrawerStack({ children, }: DrawerStackProps) { return
{children}
; }); export type DrawerButtonColumnProps = PropsWithChildren; /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export const DrawerButtonColumn = memo(function DrawerButtonColumn({ children, }: DrawerButtonColumnProps) { return
{children}
; }); export interface DrawerButtonProps { icon?: ReactElement; type?: NativeButtonProps["type"]; role?: NativeButtonProps["role"]; onClick?: () => void; critical?: boolean; text: string; } /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export const DrawerButton = memo(function DrawerButton({ icon, type, role, onClick, critical, text, }: DrawerButtonProps) { return ( ); }); type NativeInputProps = DetailedHTMLProps< ButtonHTMLAttributes, HTMLInputElement >; export interface DrawerListToggleSwitchItemProps { label: string; name?: NativeInputProps["name"]; icon?: ReactElement; disabled?: NativeInputProps["disabled"]; defaultChecked?: boolean; /** `value` and `onChange` are optional because we want to be able to use the control in an uncontrolled manner as well (for example, in forms) */ value?: boolean; onChange?: (value: boolean) => void; } /** * @remarks The drawer components are meant to be used in a for mobile only. * Do not use them in other contexts. Especially not on desktop. */ export const DrawerListToggleSwitchItem = memo(function DrawerListToggleItem({ label, name, icon, disabled, defaultChecked, value, onChange, }: DrawerListToggleSwitchItemProps) { return ( // biome-ignore lint/a11y/noLabelWithoutControl: is inside ToggleSliderInput ); });