From d85a11d0c3d1caabea7c5a0938682142cd12251d Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Tue, 27 Aug 2024 00:21:25 -0400 Subject: [PATCH 01/12] feat: initialize ShadCN Select --- package.json | 1 + src/components/ui/select.tsx | 158 +++++++++++++++++++++++++++++++++++ yarn.lock | 39 ++++++++- 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 src/components/ui/select.tsx diff --git a/package.json b/package.json index 07c8b8bd59a..ef5c1e13d7f 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@radix-ui/react-portal": "^1.1.1", "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-radio-group": "^1.2.0", + "@radix-ui/react-select": "^2.1.1", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx new file mode 100644 index 00000000000..3509423cccc --- /dev/null +++ b/src/components/ui/select.tsx @@ -0,0 +1,158 @@ +import * as React from "react" +import { LuCheck, LuChevronDown, LuChevronUp } from "react-icons/lu" +import * as SelectPrimitive from "@radix-ui/react-select" + +import { cn } from "@/lib/utils/cn" + +const Select = SelectPrimitive.Root + +const SelectGroup = SelectPrimitive.Group + +const SelectValue = SelectPrimitive.Value + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className + )} + {...props} + > + {children} + + + + +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)) +SelectContent.displayName = SelectPrimitive.Content.displayName + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + + {children} + +)) +SelectItem.displayName = SelectPrimitive.Item.displayName + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName + +export { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectScrollDownButton, + SelectScrollUpButton, + SelectSeparator, + SelectTrigger, + SelectValue, +} diff --git a/yarn.lock b/yarn.lock index b095fbe0d12..23d4f5ad33b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4118,6 +4118,11 @@ "@opentelemetry/instrumentation" "^0.49 || ^0.50 || ^0.51 || ^0.52.0" "@opentelemetry/sdk-trace-base" "^1.22" +"@radix-ui/number@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46" + integrity sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ== + "@radix-ui/primitive@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" @@ -4473,6 +4478,33 @@ "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" +"@radix-ui/react-select@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-2.1.1.tgz#df05cb0b29d3deaef83b505917c4042e0e418a9f" + integrity sha512-8iRDfyLtzxlprOo9IicnzvpsO1wNCkuwzzCM+Z5Rb5tNOpCdMvcc2AkzX0Fz+Tz9v6NJ5B/7EEgyZveo4FBRfQ== + dependencies: + "@radix-ui/number" "1.1.0" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.7" + "@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" @@ -13097,7 +13129,7 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -"prettier-fallback@npm:prettier@^3", prettier@^3.1.1: +"prettier-fallback@npm:prettier@^3": version "3.3.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== @@ -13112,6 +13144,11 @@ prettier@^2.0.5, prettier@^2.8.8: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +prettier@^3.1.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" + integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== + prettier@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" From 7545dc7488fd4b7d79011a4c0e0cafba08a3b275 Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Tue, 27 Aug 2024 00:54:53 -0400 Subject: [PATCH 02/12] feat(ui/Select): initilize story file --- src/components/ui/{select.tsx => Select.tsx} | 27 ++------ .../ui/__stories__/Select.stories.tsx | 64 +++++++++++++++++++ 2 files changed, 68 insertions(+), 23 deletions(-) rename src/components/ui/{select.tsx => Select.tsx} (85%) create mode 100644 src/components/ui/__stories__/Select.stories.tsx diff --git a/src/components/ui/select.tsx b/src/components/ui/Select.tsx similarity index 85% rename from src/components/ui/select.tsx rename to src/components/ui/Select.tsx index 3509423cccc..0c2613808b0 100644 --- a/src/components/ui/select.tsx +++ b/src/components/ui/Select.tsx @@ -1,5 +1,5 @@ import * as React from "react" -import { LuCheck, LuChevronDown, LuChevronUp } from "react-icons/lu" +import { FaChevronDown, FaChevronUp } from "react-icons/fa" import * as SelectPrimitive from "@radix-ui/react-select" import { cn } from "@/lib/utils/cn" @@ -24,7 +24,7 @@ const SelectTrigger = React.forwardRef< > {children} - + )) @@ -42,7 +42,7 @@ const SelectScrollUpButton = React.forwardRef< )} {...props} > - + )) SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName @@ -59,7 +59,7 @@ const SelectScrollDownButton = React.forwardRef< )} {...props} > - + )) SelectScrollDownButton.displayName = @@ -121,29 +121,11 @@ const SelectItem = React.forwardRef< )} {...props} > - - - - - - {children} )) SelectItem.displayName = SelectPrimitive.Item.displayName -const SelectSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -SelectSeparator.displayName = SelectPrimitive.Separator.displayName - export { Select, SelectContent, @@ -152,7 +134,6 @@ export { SelectLabel, SelectScrollDownButton, SelectScrollUpButton, - SelectSeparator, SelectTrigger, SelectValue, } diff --git a/src/components/ui/__stories__/Select.stories.tsx b/src/components/ui/__stories__/Select.stories.tsx new file mode 100644 index 00000000000..df97178e185 --- /dev/null +++ b/src/components/ui/__stories__/Select.stories.tsx @@ -0,0 +1,64 @@ +import { SelectItem } from "@radix-ui/react-select" +import type { Meta, StoryObj } from "@storybook/react/*" + +import { + Select, + SelectContent, + SelectGroup, + SelectLabel, + SelectTrigger, + SelectValue, +} from "../Select" + +const meta = { + title: "Atoms / Form / ShadCn Dropdown", + component: Select, + parameters: { + // TODO: Remove this when this story file becomes the primary one + chromatic: { disableSnapshot: true }, + }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +} satisfies Meta + +export default meta + +export const Dropdown: StoryObj = { + render: () => ( + + ), +} From 36fb3cd9c32e53929046eb9a5ab508c0849109cf Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Thu, 29 Aug 2024 01:00:14 -0400 Subject: [PATCH 03/12] refactor(ui/Select): migrate react-select to use tailwind --- package.json | 2 +- src/components/ui/Select.tsx | 139 ----------- src/components/ui/Select/context.ts | 13 + src/components/ui/Select/index.tsx | 70 ++++++ src/components/ui/Select/innerComponents.tsx | 231 ++++++++++++++++++ .../ui/__stories__/Select.stories.tsx | 74 +++--- yarn.lock | 44 +--- 7 files changed, 358 insertions(+), 215 deletions(-) delete mode 100644 src/components/ui/Select.tsx create mode 100644 src/components/ui/Select/context.ts create mode 100644 src/components/ui/Select/index.tsx create mode 100644 src/components/ui/Select/innerComponents.tsx diff --git a/package.json b/package.json index ef5c1e13d7f..c3111ff471b 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "@radix-ui/react-portal": "^1.1.1", "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-radio-group": "^1.2.0", - "@radix-ui/react-select": "^2.1.1", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", @@ -84,6 +83,7 @@ "reading-time": "^1.5.0", "remark-gfm": "^3.0.1", "tailwind-merge": "^2.3.0", + "tailwind-variants": "^0.2.1", "tailwindcss-animate": "^1.0.7", "usehooks-ts": "^3.1.0", "yaml-loader": "^0.8.0" diff --git a/src/components/ui/Select.tsx b/src/components/ui/Select.tsx deleted file mode 100644 index 0c2613808b0..00000000000 --- a/src/components/ui/Select.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import * as React from "react" -import { FaChevronDown, FaChevronUp } from "react-icons/fa" -import * as SelectPrimitive from "@radix-ui/react-select" - -import { cn } from "@/lib/utils/cn" - -const Select = SelectPrimitive.Root - -const SelectGroup = SelectPrimitive.Group - -const SelectValue = SelectPrimitive.Value - -const SelectTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - span]:line-clamp-1", - className - )} - {...props} - > - {children} - - - - -)) -SelectTrigger.displayName = SelectPrimitive.Trigger.displayName - -const SelectScrollUpButton = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)) -SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName - -const SelectScrollDownButton = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)) -SelectScrollDownButton.displayName = - SelectPrimitive.ScrollDownButton.displayName - -const SelectContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, position = "popper", ...props }, ref) => ( - - - - - {children} - - - - -)) -SelectContent.displayName = SelectPrimitive.Content.displayName - -const SelectLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -SelectLabel.displayName = SelectPrimitive.Label.displayName - -const SelectItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - {children} - -)) -SelectItem.displayName = SelectPrimitive.Item.displayName - -export { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectLabel, - SelectScrollDownButton, - SelectScrollUpButton, - SelectTrigger, - SelectValue, -} diff --git a/src/components/ui/Select/context.ts b/src/components/ui/Select/context.ts new file mode 100644 index 00000000000..e579cdcf622 --- /dev/null +++ b/src/components/ui/Select/context.ts @@ -0,0 +1,13 @@ +import { createStylesContext, type SystemStyleObject } from "@chakra-ui/react" + +import { reactSelectAnatomyKeys } from "./innerComponents" + +const [ReactSelectStylesProvider, useReactSelectStyles] = + createStylesContext("ReactSelect") + +export const SelectStylesProvider = ReactSelectStylesProvider + +export const useSelectStyles = useReactSelectStyles as () => Record< + (typeof reactSelectAnatomyKeys)[number], + SystemStyleObject +> diff --git a/src/components/ui/Select/index.tsx b/src/components/ui/Select/index.tsx new file mode 100644 index 00000000000..452c3fba10e --- /dev/null +++ b/src/components/ui/Select/index.tsx @@ -0,0 +1,70 @@ +import ReactSelect, { ActionMeta, GroupBase, Props } from "react-select" + +import { + components, + SelectStylesContext, + type SelectVariants, + selectVariants, +} from "./innerComponents" + +/** + * Type for onChange handler in the `Select` component + * + * Specifically declared for single selects. + * + * @see https://react-select.com/typescript#onchange + * + * @typeParam Option - The object type in the array + * @param newValue - The object returned from the payload + * @param actionMeta - The set of actions that can be run on change + */ +export type SelectOnChange