Add missing variants on TextField and Select
Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -48,6 +48,27 @@ export function Default() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function Variants() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
{(["classic", "surface", "soft", "ghost"] as const).map(variant => (
|
||||||
|
<div key={variant} className="w-40">
|
||||||
|
<Select>
|
||||||
|
<SelectTrigger variant={variant} placeholder={variant}>
|
||||||
|
{(value: string | null) => (value ? fruits[value] : null)}
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectPopup>
|
||||||
|
{Object.entries(fruits).map(([value, label]) => (
|
||||||
|
<SelectItem key={value} value={value}>{label}</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectPopup>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function Controlled() {
|
export function Controlled() {
|
||||||
const [value, setValue] = useState<string | null>(null);
|
const [value, setValue] = useState<string | null>(null);
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export type SelectTriggerProps
|
|||||||
& {
|
& {
|
||||||
className?: string;
|
className?: string;
|
||||||
size?: 1 | 2;
|
size?: 1 | 2;
|
||||||
|
// Surface treatment (defaults to "surface").
|
||||||
|
variant?: "classic" | "surface" | "soft" | "ghost";
|
||||||
// Shown when no value is selected.
|
// Shown when no value is selected.
|
||||||
placeholder?: ReactNode;
|
placeholder?: ReactNode;
|
||||||
// Renders the selected value; pass a function to map a value to its label.
|
// Renders the selected value; pass a function to map a value to its label.
|
||||||
@@ -32,8 +34,8 @@ export type SelectTriggerProps
|
|||||||
// The bordered surface button that opens the popup, showing the selected value
|
// The bordered surface button that opens the popup, showing the selected value
|
||||||
// (or placeholder) and a trailing chevron.
|
// (or placeholder) and a trailing chevron.
|
||||||
export function SelectTrigger(props: SelectTriggerProps) {
|
export function SelectTrigger(props: SelectTriggerProps) {
|
||||||
const { className, size, placeholder, children, ...rest } = props;
|
const { className, size, variant, placeholder, children, ...rest } = props;
|
||||||
const { trigger, value, icon } = selectTrigger({ size });
|
const { trigger, value, icon } = selectTrigger({ size, variant });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseSelect.Trigger className={trigger({ className })} {...rest}>
|
<BaseSelect.Trigger className={trigger({ className })} {...rest}>
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import { tv } from "tailwind-variants/lite";
|
|||||||
export const selectTrigger = tv({
|
export const selectTrigger = tv({
|
||||||
slots: {
|
slots: {
|
||||||
trigger: [
|
trigger: [
|
||||||
"flex w-full items-center justify-between gap-2 rounded-2 border border-sand-a7 bg-sand-1 text-2 text-sand-12",
|
"flex w-full items-center justify-between gap-2 rounded-2 text-2 text-sand-12",
|
||||||
"cursor-pointer outline-none transition-colors hover:bg-sand-2",
|
"cursor-pointer outline-none transition-colors",
|
||||||
"focus-visible:ring-2 focus-visible:ring-sand-8 focus-visible:ring-offset-1 focus-visible:ring-offset-sand-1",
|
"focus-visible:ring-2 focus-visible:ring-sand-8 focus-visible:ring-offset-1 focus-visible:ring-offset-sand-1",
|
||||||
"data-disabled:pointer-events-none data-disabled:opacity-50 data-placeholder:text-sand-a10",
|
"data-disabled:pointer-events-none data-disabled:opacity-50 data-placeholder:text-sand-a10",
|
||||||
],
|
],
|
||||||
@@ -33,9 +33,19 @@ export const selectTrigger = tv({
|
|||||||
1: { trigger: "h-7 px-2" },
|
1: { trigger: "h-7 px-2" },
|
||||||
2: { trigger: "h-8 px-3" },
|
2: { trigger: "h-8 px-3" },
|
||||||
},
|
},
|
||||||
|
// Surface treatment. Only the accent (gold) color ships, matching Figma;
|
||||||
|
// classic adds a recessed inset shadow (Figma can't express its gradient),
|
||||||
|
// soft drops the border for a tint, ghost is transparent until hover.
|
||||||
|
variant: {
|
||||||
|
classic: { trigger: "border border-sand-a7 bg-sand-1 inset-shadow-2 hover:bg-sand-2" },
|
||||||
|
surface: { trigger: "border border-sand-a7 bg-sand-1 hover:bg-sand-2" },
|
||||||
|
soft: { trigger: "bg-gold-3 hover:bg-gold-4" },
|
||||||
|
ghost: { trigger: "hover:bg-sand-2" },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
size: 2,
|
size: 2,
|
||||||
|
variant: "surface",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,16 @@ export function WithIcon() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function Variants() {
|
||||||
|
return (
|
||||||
|
<div className="flex w-60 flex-col gap-3">
|
||||||
|
<TextField variant="classic" icon={<MagnifyingGlassIcon />} placeholder="Classic" />
|
||||||
|
<TextField variant="surface" icon={<MagnifyingGlassIcon />} placeholder="Surface" />
|
||||||
|
<TextField variant="soft" icon={<MagnifyingGlassIcon />} placeholder="Soft" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function Controlled() {
|
export function Controlled() {
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export type TextFieldProps
|
|||||||
// Applied to the bordered container (the top-level element).
|
// Applied to the bordered container (the top-level element).
|
||||||
className?: string;
|
className?: string;
|
||||||
size?: 1 | 2;
|
size?: 1 | 2;
|
||||||
|
// Surface treatment (defaults to "surface").
|
||||||
|
variant?: "classic" | "surface" | "soft";
|
||||||
// Leading icon slot (e.g. a MagnifyingGlassIcon for search).
|
// Leading icon slot (e.g. a MagnifyingGlassIcon for search).
|
||||||
icon?: ReactNode;
|
icon?: ReactNode;
|
||||||
};
|
};
|
||||||
@@ -31,8 +33,8 @@ export type TextFieldProps
|
|||||||
// node; all native input props spread onto the inner control. Controlled with
|
// node; all native input props spread onto the inner control. Controlled with
|
||||||
// Base UI's `value` / `onValueChange` (or native `value` / `onChange`).
|
// Base UI's `value` / `onValueChange` (or native `value` / `onChange`).
|
||||||
export function TextField(props: TextFieldProps) {
|
export function TextField(props: TextFieldProps) {
|
||||||
const { className, size, icon, ...inputProps } = props;
|
const { className, size, variant, icon, ...inputProps } = props;
|
||||||
const { root, icon: iconSlot, input } = textField({ size });
|
const { root, icon: iconSlot, input } = textField({ size, variant });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={root({ className })}>
|
<div className={root({ className })}>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { tv } from "tailwind-variants/lite";
|
|||||||
export const textField = tv({
|
export const textField = tv({
|
||||||
slots: {
|
slots: {
|
||||||
root: [
|
root: [
|
||||||
"flex items-center gap-2 rounded-2 border border-sand-a5 bg-sand-1 text-2 text-sand-12 transition-colors",
|
"flex items-center gap-2 rounded-2 text-2 text-sand-12 transition-colors",
|
||||||
"focus-within:ring-2 focus-within:ring-sand-8 focus-within:ring-offset-1 focus-within:ring-offset-sand-1",
|
"focus-within:ring-2 focus-within:ring-sand-8 focus-within:ring-offset-1 focus-within:ring-offset-sand-1",
|
||||||
"has-[input:disabled]:pointer-events-none has-[input:disabled]:opacity-50",
|
"has-[input:disabled]:pointer-events-none has-[input:disabled]:opacity-50",
|
||||||
],
|
],
|
||||||
@@ -31,9 +31,17 @@ export const textField = tv({
|
|||||||
1: { root: "h-7 px-2" },
|
1: { root: "h-7 px-2" },
|
||||||
2: { root: "h-8 px-2" },
|
2: { root: "h-8 px-2" },
|
||||||
},
|
},
|
||||||
|
// Surface treatment. Only the accent (gold) color ships, matching Figma;
|
||||||
|
// classic adds a recessed inset shadow, soft drops the border for a tint.
|
||||||
|
variant: {
|
||||||
|
classic: { root: "border border-sand-a5 bg-sand-1 inset-shadow-2" },
|
||||||
|
surface: { root: "border border-sand-a5 bg-sand-1" },
|
||||||
|
soft: { root: "bg-gold-3" },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
size: 2,
|
size: 2,
|
||||||
|
variant: "surface",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user