wip: select

main
Juan Olvera 9 months ago
parent 91d26fb0af
commit c396bc69fb

@ -735,14 +735,6 @@ select {
right: 0px;
}
.right-4 {
right: 1rem;
}
.top-4 {
top: 1rem;
}
.top-1\/2 {
top: 50%;
}
@ -751,30 +743,14 @@ select {
left: 50%;
}
.top-1 {
top: 0.25rem;
}
.right-2 {
right: 0.5rem;
}
.right-1 {
right: 0.25rem;
}
.top-2 {
top: 0.5rem;
.top-3 {
top: 0.75rem;
}
.right-3 {
right: 0.75rem;
}
.top-3 {
top: 0.75rem;
}
.isolate {
isolation: isolate;
}
@ -795,6 +771,10 @@ select {
margin-top: 0.5rem;
}
.ml-2 {
margin-left: 0.5rem;
}
.box-border {
box-sizing: border-box;
}
@ -811,10 +791,6 @@ select {
display: inline-flex;
}
.grid {
display: grid;
}
.h-full {
height: 100%;
}
@ -823,24 +799,32 @@ select {
height: 2px;
}
.w-full {
width: 100%;
.h-10 {
height: 2.5rem;
}
.w-96 {
width: 24rem;
.max-h-96 {
max-height: 24rem;
}
.w-56 {
width: 14rem;
}
.w-full {
width: 100%;
}
.w-96 {
width: 24rem;
}
.min-w-0 {
min-width: 0px;
}
.max-w-lg {
max-width: 32rem;
.min-w-\[8rem\] {
min-width: 8rem;
}
.-translate-x-2\/4 {
@ -853,28 +837,28 @@ select {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-x-\[-50\%\] {
.-translate-x-1\/2 {
--tw-translate-x: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-y-\[-50\%\] {
.-translate-y-1\/2 {
--tw-translate-y: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.-translate-x-1\/2 {
--tw-translate-x: -50%;
.transform {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.-translate-y-1\/2 {
--tw-translate-y: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
.cursor-default {
cursor: default;
}
.transform {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
.select-none {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.items-center {
@ -889,10 +873,6 @@ select {
justify-content: space-between;
}
.gap-4 {
gap: 1rem;
}
.gap-x-2 {
-moz-column-gap: 0.5rem;
column-gap: 0.5rem;
@ -934,30 +914,26 @@ select {
border-radius: 0.5rem;
}
.rounded-sm {
border-radius: 0.125rem;
.rounded-full {
border-radius: 9999px;
}
.rounded-md {
border-radius: 0.375rem;
}
.rounded-full {
border-radius: 9999px;
}
.border-2 {
border-width: 2px;
}
.border {
border-width: 1px;
}
.border-0 {
border-width: 0px;
}
.border {
border-width: 1px;
}
.border-mono-border {
--tw-border-opacity: 1;
border-color: rgb(209 213 219 / var(--tw-border-opacity));
@ -988,10 +964,6 @@ select {
background-color: rgb(209 213 219 / var(--tw-bg-opacity));
}
.bg-black\/80 {
background-color: rgb(0 0 0 / 0.8);
}
.bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
@ -1005,14 +977,14 @@ select {
--tw-bg-opacity: 0.5;
}
.p-0 {
padding: 0px;
}
.p-1 {
padding: 0.25rem;
}
.p-0 {
padding: 0px;
}
.p-2 {
padding: 0.5rem;
}
@ -1102,6 +1074,14 @@ select {
padding-right: 0.75rem;
}
.pr-2 {
padding-right: 0.5rem;
}
.pl-8 {
padding-left: 2rem;
}
.text-left {
text-align: left;
}
@ -1162,13 +1142,9 @@ select {
opacity: 0;
}
.opacity-70 {
opacity: 0.7;
}
.shadow-lg {
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
.shadow-md {
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
@ -1177,14 +1153,18 @@ select {
outline-offset: 2px;
}
.transition-opacity {
transition-property: opacity;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
@keyframes enter {
from {
opacity: var(--tw-enter-opacity, 1);
transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0) scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0));
}
}
.duration-200 {
transition-duration: 200ms;
@keyframes exit {
to {
opacity: var(--tw-exit-opacity, 1);
transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0) scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0));
}
}
html {
@ -1211,8 +1191,14 @@ html {
background-color: rgb(63 63 70 / var(--tw-bg-opacity));
}
.hover\:opacity-100:hover {
opacity: 1;
.hover\:bg-mono-hover:hover {
--tw-bg-opacity: 1;
background-color: rgb(156 163 175 / var(--tw-bg-opacity));
}
.hover\:bg-mono-primary:hover {
--tw-bg-opacity: 1;
background-color: rgb(39 39 42 / var(--tw-bg-opacity));
}
.focus\:border-mono-primary:focus {
@ -1256,10 +1242,22 @@ html {
--tw-ring-offset-width: 2px;
}
.disabled\:pointer-events-none:disabled {
.disabled\:cursor-not-allowed:disabled {
cursor: not-allowed;
}
.disabled\:opacity-50:disabled {
opacity: 0.5;
}
.data-\[disabled\]\:pointer-events-none[data-disabled] {
pointer-events: none;
}
.data-\[disabled\]\:text-mono-text\/50[data-disabled] {
color: rgb(107 114 128 / 0.5);
}
.data-\[disabled\]\:opacity-50[data-disabled] {
opacity: 0.5;
}
@ -1268,16 +1266,56 @@ html {
outline-style: solid;
}
.data-\[focus\]\:outline-2[data-focus] {
outline-width: 2px;
.data-\[state\=open\]\:animate-in[data-state=open] {
animation-name: enter;
animation-duration: 150ms;
--tw-enter-opacity: initial;
--tw-enter-scale: initial;
--tw-enter-rotate: initial;
--tw-enter-translate-x: initial;
--tw-enter-translate-y: initial;
}
.data-\[focus\]\:outline-offset-2[data-focus] {
outline-offset: 2px;
.data-\[state\=closed\]\:animate-out[data-state=closed] {
animation-name: exit;
animation-duration: 150ms;
--tw-exit-opacity: initial;
--tw-exit-scale: initial;
--tw-exit-rotate: initial;
--tw-exit-translate-x: initial;
--tw-exit-translate-y: initial;
}
.data-\[state\=closed\]\:fade-out-0[data-state=closed] {
--tw-exit-opacity: 0;
}
.data-\[state\=open\]\:fade-in-0[data-state=open] {
--tw-enter-opacity: 0;
}
.data-\[state\=closed\]\:zoom-out-95[data-state=closed] {
--tw-exit-scale: .95;
}
.data-\[state\=open\]\:zoom-in-95[data-state=open] {
--tw-enter-scale: .95;
}
.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom] {
--tw-enter-translate-y: -0.5rem;
}
.data-\[focus\]\:outline-blue-500[data-focus] {
outline-color: #3b82f6;
.data-\[side\=left\]\:slide-in-from-right-2[data-side=left] {
--tw-enter-translate-x: 0.5rem;
}
.data-\[side\=right\]\:slide-in-from-left-2[data-side=right] {
--tw-enter-translate-x: -0.5rem;
}
.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top] {
--tw-enter-translate-y: 0.5rem;
}
@media (prefers-reduced-motion: no-preference) {
@ -1293,10 +1331,6 @@ html {
}
@media (min-width: 640px) {
.sm\:rounded-lg {
border-radius: 0.5rem;
}
.sm\:px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;

34
package-lock.json generated

@ -11,6 +11,7 @@
"dependencies": {
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.4",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-primitive": "^1.0.3",
"@radix-ui/react-select": "^2.0.0",
@ -60,6 +61,7 @@
"storybook": "^7.6.7",
"tailwind-merge": "^1.11.0",
"tailwindcss": "^3.2.4",
"tailwindcss-animate": "^1.0.7",
"ts-jest": "^29.0.5",
"tsup": "^6.5.0",
"typescript": "^5.1.6",
@ -4259,6 +4261,29 @@
"react": "^16.8 || ^17.0 || ^18.0"
}
},
"node_modules/@radix-ui/react-label": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
"integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-primitive": "1.0.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-menu": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.4.tgz",
@ -24263,6 +24288,15 @@
"postcss": "^8.0.9"
}
},
"node_modules/tailwindcss-animate": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
"integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
"dev": true,
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders"
}
},
"node_modules/tailwindcss/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",

@ -71,6 +71,7 @@
"storybook": "^7.6.7",
"tailwind-merge": "^1.11.0",
"tailwindcss": "^3.2.4",
"tailwindcss-animate": "^1.0.7",
"ts-jest": "^29.0.5",
"tsup": "^6.5.0",
"typescript": "^5.1.6",
@ -79,6 +80,7 @@
"dependencies": {
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.4",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-primitive": "^1.0.3",
"@radix-ui/react-select": "^2.0.0",

@ -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 $ 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 = () => {
return <div>Select</div>;
};
const Select = React.forwardRef<T.SelectElement, T.SelectProps>(
({ 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,
};

@ -28,6 +28,9 @@ module.exports = {
"mono-text": {
DEFAULT: colors.gray["500"],
},
"mono-hover": {
DEFAULT: colors.gray[400],
},
"mono-rounded": {
DEFAULT: defaultTheme.borderRadius["lg"],
},
@ -38,5 +41,5 @@ module.exports = {
},
},
},
plugins: [require("@tailwindcss/forms")],
plugins: [require("@tailwindcss/forms"), require("tailwindcss-animate")],
};

Loading…
Cancel
Save