50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
import type { HTMLAttributes, ReactNode } from "react";
|
|
import { cn } from "./cn.js";
|
|
|
|
export interface SettingsCardProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
|
|
eyebrow?: ReactNode;
|
|
title: ReactNode;
|
|
description?: ReactNode;
|
|
actions?: ReactNode;
|
|
align?: "start" | "center";
|
|
}
|
|
|
|
export function SettingsCard({ eyebrow, title, description, actions, children, align = "start", className, ...props }: SettingsCardProps) {
|
|
return (
|
|
<section className={cn("nodedc-settings-card", className)} data-align={align === "center" ? "center" : undefined} {...props}>
|
|
<header className="nodedc-settings-card__head">
|
|
<div className="nodedc-settings-card__titles">
|
|
{eyebrow ? <span>{eyebrow}</span> : null}
|
|
<h2>{title}</h2>
|
|
{description ? <p>{description}</p> : null}
|
|
</div>
|
|
{actions ? <div className="nodedc-settings-card__actions">{actions}</div> : null}
|
|
</header>
|
|
{align === "center" && (children === undefined || children === null || children === false) ? null : <div className="nodedc-settings-card__body">{children}</div>}
|
|
</section>
|
|
);
|
|
}
|
|
|
|
export interface SwitchProps {
|
|
checked: boolean;
|
|
label: string;
|
|
disabled?: boolean;
|
|
onChange: (checked: boolean) => void;
|
|
}
|
|
|
|
export function Switch({ checked, label, disabled = false, onChange }: SwitchProps) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
className="nodedc-switch"
|
|
role="switch"
|
|
aria-checked={checked}
|
|
disabled={disabled}
|
|
onClick={() => onChange(!checked)}
|
|
>
|
|
<span className="nodedc-switch__track" aria-hidden="true"><span /></span>
|
|
<span>{label}</span>
|
|
</button>
|
|
);
|
|
}
|