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
);
});