wip: select
parent
91d26fb0af
commit
c396bc69fb
@ -0,0 +1,29 @@
|
|||||||
|
import React from "react";
|
||||||
|
import type { Meta, StoryObj } from "@storybook/react";
|
||||||
|
import { Select, SelectItem } from "./Select";
|
||||||
|
|
||||||
|
const meta: Meta<typeof Select> = {
|
||||||
|
title: "UI/Select",
|
||||||
|
component: Select,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof Select>;
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{ label: "Banana", value: "banana" },
|
||||||
|
{ label: "Apple", value: "apple" },
|
||||||
|
{ label: "Pear", value: "pear" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
render: () => (
|
||||||
|
<Select placeholder="Select a fruit" tabIndex={0}>
|
||||||
|
{options.map((option) => (
|
||||||
|
<SelectItem key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
),
|
||||||
|
};
|
@ -0,0 +1,79 @@
|
|||||||
|
import { cva } from "class-variance-authority";
|
||||||
|
|
||||||
|
const base = [
|
||||||
|
"inline-flex",
|
||||||
|
"items-center",
|
||||||
|
"justify-between",
|
||||||
|
"border-2",
|
||||||
|
"border-mono-border",
|
||||||
|
"py-1.5",
|
||||||
|
"px-2",
|
||||||
|
"rounded-lg",
|
||||||
|
"focus:outline-none",
|
||||||
|
"focus:border-mono-primary",
|
||||||
|
];
|
||||||
|
|
||||||
|
const viewport = ["p-1"];
|
||||||
|
|
||||||
|
const content = [
|
||||||
|
"relative",
|
||||||
|
"max-h-96",
|
||||||
|
"min-w-[8rem]",
|
||||||
|
"py-1.5",
|
||||||
|
"px-2",
|
||||||
|
"border-2",
|
||||||
|
"border-mono-border",
|
||||||
|
"overflow-hidden",
|
||||||
|
"rounded-lg",
|
||||||
|
"bg-white",
|
||||||
|
|
||||||
|
// Animation
|
||||||
|
"data-[state=open]:animate-in",
|
||||||
|
"data-[state=closed]:animate-out",
|
||||||
|
"data-[state=closed]:fade-out-0",
|
||||||
|
"data-[state=open]:fade-in-0",
|
||||||
|
"data-[state=closed]:zoom-out-95",
|
||||||
|
"data-[state=open]:zoom-in-95",
|
||||||
|
"data-[side=bottom]:slide-in-from-top-2",
|
||||||
|
"data-[side=left]:slide-in-from-right-2",
|
||||||
|
"data-[side=right]:slide-in-from-left-2",
|
||||||
|
"data-[side=top]:slide-in-from-bottom-2",
|
||||||
|
];
|
||||||
|
|
||||||
|
const scroll = [
|
||||||
|
"flex",
|
||||||
|
"cursor-default",
|
||||||
|
"items-center",
|
||||||
|
"justify-center",
|
||||||
|
"py-1",
|
||||||
|
];
|
||||||
|
|
||||||
|
const indicator = [
|
||||||
|
"absolute",
|
||||||
|
"left-0",
|
||||||
|
"inline-flex",
|
||||||
|
"items-center",
|
||||||
|
"justify-center",
|
||||||
|
];
|
||||||
|
|
||||||
|
const selectStyles = cva(base);
|
||||||
|
|
||||||
|
const item = [
|
||||||
|
"relative",
|
||||||
|
"flex",
|
||||||
|
"w-full",
|
||||||
|
"cursor-default",
|
||||||
|
"select-none",
|
||||||
|
"items-center",
|
||||||
|
"py-1.5",
|
||||||
|
"pr-2",
|
||||||
|
"pl-8",
|
||||||
|
"data-[disabled]:pointer-events-none",
|
||||||
|
"data-[disabled]:text-mono-text/50",
|
||||||
|
"focus:outline-none",
|
||||||
|
"focus:border-mono-primary",
|
||||||
|
];
|
||||||
|
|
||||||
|
const itemStyles = cva(item);
|
||||||
|
|
||||||
|
export { selectStyles, itemStyles, viewport, content, indicator, scroll };
|
@ -1,8 +1,62 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as $ from "@radix-ui/react-select";
|
import * as $ from "@radix-ui/react-select";
|
||||||
|
import { Label } from "@radix-ui/react-label";
|
||||||
|
import { FaCheck, FaChevronDown, FaChevronUp } from "react-icons/fa";
|
||||||
|
import * as T from "./Select.types";
|
||||||
|
import * as styles from "./Select.styles";
|
||||||
|
import { cx } from "../../utils";
|
||||||
|
import { Box } from "../Box";
|
||||||
|
|
||||||
const Select = () => {
|
const Select = React.forwardRef<T.SelectElement, T.SelectProps>(
|
||||||
return <div>Select</div>;
|
({ children, className, ...props }, ref) => {
|
||||||
};
|
const classes = cx([styles.selectStyles()], className);
|
||||||
|
console.log("classes", classes);
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Label htmlFor={"select"}>Select</Label>
|
||||||
|
<Box>
|
||||||
|
<$.Root>
|
||||||
|
<$.Trigger id="select" {...props} className={classes} ref={ref}>
|
||||||
|
<$.Value placeholder={props.placeholder} />
|
||||||
|
<$.Icon className={cx(["ml-2"])} asChild>
|
||||||
|
<FaChevronDown />
|
||||||
|
</$.Icon>
|
||||||
|
</$.Trigger>
|
||||||
|
<$.Portal>
|
||||||
|
<$.Content className={cx([styles.content])} position="popper">
|
||||||
|
<$.ScrollUpButton className={cx([styles.scroll])}>
|
||||||
|
<FaChevronUp />
|
||||||
|
</$.ScrollUpButton>
|
||||||
|
|
||||||
export { Select };
|
<$.Viewport className={cx([styles.viewport])}>
|
||||||
|
{children}
|
||||||
|
</$.Viewport>
|
||||||
|
|
||||||
|
<$.ScrollDownButton className={cx([styles.scroll])}>
|
||||||
|
<FaChevronDown />
|
||||||
|
</$.ScrollDownButton>
|
||||||
|
<$.Arrow />
|
||||||
|
</$.Content>
|
||||||
|
</$.Portal>
|
||||||
|
</$.Root>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const SelectItem = React.forwardRef<T.SelectItemElement, T.SelectItemProps>(
|
||||||
|
({ children, className, ...props }, forwardedRef) => {
|
||||||
|
const classes = cx([styles.itemStyles()], className);
|
||||||
|
return (
|
||||||
|
<$.Item {...props} ref={forwardedRef}>
|
||||||
|
<$.ItemText>{children}</$.ItemText>
|
||||||
|
<$.ItemIndicator className={cx([styles.indicator])}>
|
||||||
|
<FaCheck />
|
||||||
|
</$.ItemIndicator>{" "}
|
||||||
|
</$.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export { Select, SelectItem };
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import * as $ from "@radix-ui/react-select";
|
||||||
|
import { VariantProps } from "class-variance-authority";
|
||||||
|
import { selectStyles } from "./Select.styles";
|
||||||
|
|
||||||
|
type SelectOption = {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SelectSection = {
|
||||||
|
label: string;
|
||||||
|
value: SelectOption[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type SelectElement = React.ElementRef<typeof $.Trigger>;
|
||||||
|
|
||||||
|
type SelectProps = React.ComponentPropsWithoutRef<typeof $.Trigger> &
|
||||||
|
VariantProps<typeof selectStyles> & {};
|
||||||
|
|
||||||
|
type SelectItemElement = React.ElementRef<typeof $.Item>;
|
||||||
|
|
||||||
|
type SelectItemProps = React.ComponentPropsWithoutRef<typeof $.Item> & {};
|
||||||
|
|
||||||
|
export {
|
||||||
|
SelectOption,
|
||||||
|
SelectSection,
|
||||||
|
SelectElement,
|
||||||
|
SelectProps,
|
||||||
|
SelectItemElement,
|
||||||
|
SelectItemProps,
|
||||||
|
};
|
Loading…
Reference in New Issue