From 7797d109994c9c31a17d19c1bc53d4d29834ff91 Mon Sep 17 00:00:00 2001 From: xun082 <2042204285@qq.com> Date: Sun, 21 Jul 2024 11:06:23 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=F0=9F=94=A8=20improve=20code=20struct?= =?UTF-8?q?ure=20and=20add=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edit/(main)/(router)/settings/page.tsx | 164 ++++++--------- src/components/ui/select/index.stories.tsx | 136 ++++++++++++ src/components/ui/select/index.tsx | 196 +++++++++--------- src/components/ui/tooltip/index.stories.tsx | 124 +++++++++++ src/components/ui/tooltip/index.tsx | 34 +-- 5 files changed, 447 insertions(+), 207 deletions(-) create mode 100644 src/components/ui/select/index.stories.tsx create mode 100644 src/components/ui/tooltip/index.stories.tsx diff --git a/src/app/edit/(main)/(router)/settings/page.tsx b/src/app/edit/(main)/(router)/settings/page.tsx index e4587ca..e5d2389 100644 --- a/src/app/edit/(main)/(router)/settings/page.tsx +++ b/src/app/edit/(main)/(router)/settings/page.tsx @@ -1,37 +1,59 @@ +'use client'; + import { FC, ReactNode } from 'react'; import { PiWarningCircleBold, PiCodeThin } from 'react-icons/pi'; import { VscPreview } from 'react-icons/vsc'; import { - Select, - SelectContent, - SelectItem, + SelectRoot, SelectTrigger, SelectValue, + SelectContent, + SelectItem, } from '@/components/ui/select'; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; +import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from '@/components/ui/tooltip'; import { Menu, MenuItem } from '@/components/menu'; -const Settings: FC = () => { - const titleStyle = 'my-2 font-bold'; +const titleStyle = 'my-2 font-bold'; +const textStyle = 'flex items-center text-sm text-gray-400 my-1'; + +const selectOptions = [ + { text: 'Edit(auto)', id: 0 }, + { text: 'Save', id: 1 }, + { text: 'KeyStroke', id: 2 }, +]; - return ( +interface SettingOption { + text: string; + id: number; + icon: ReactNode; +} + +const editorSettingOptions: SettingOption[] = [ + { text: 'User settings', id: 0, icon: }, + { text: 'Workspace settings', id: 1, icon: }, + { text: 'User snippets', id: 2, icon: }, + { text: 'Workspace snippets', id: 3, icon: }, +]; + +const Settings: FC = () => ( +
Settings
WEBCONTAINERS
-
+
Compile trigger - - - + + + - - -

Controls when edited files are synced tothe WebContainers filesystem.

-
-
-
+ + + +

Controls when edited files are synced to the WebContainers filesystem.

+
+
@@ -40,85 +62,37 @@ const Settings: FC = () => {
- ); -}; - -const CompileSelector: FC = () => { - const selectOptions = [ - { - text: 'Edit(auto)', - id: 0, - }, - { - text: 'Save', - id: 1, - }, - { - text: 'KeyStroke', - id: 2, - }, - ]; +
+); - return ( - - ); -}; +const CompileSelector: FC = () => ( + + + + + + {selectOptions.map((option) => ( + + {option.text} + + ))} + + +); -const EditorSettings: FC = () => { - interface settingOption { - text: string; - id: number; - icon: ReactNode; - } - - const editorSettingOptions: Array = [ - { - text: 'User settings', - id: 0, - icon: , - }, - { - text: 'Workspace settings', - id: 1, - icon: , - }, - { - text: 'User snippets', - id: 2, - icon: , - }, - { - text: 'Workspace snippets', - id: 3, - icon: , - }, - ]; - - return ( -
- - {editorSettingOptions.map((option) => ( - -
- {option.icon} - {option.text} -
-
- ))} -
-
- ); -}; +const EditorSettings: FC = () => ( +
+ + {editorSettingOptions.map((option) => ( + +
+ {option.icon} + {option.text} +
+
+ ))} +
+
+); export default Settings; diff --git a/src/components/ui/select/index.stories.tsx b/src/components/ui/select/index.stories.tsx new file mode 100644 index 0000000..e9dd311 --- /dev/null +++ b/src/components/ui/select/index.stories.tsx @@ -0,0 +1,136 @@ +import * as React from 'react'; +import { Meta, StoryFn } from '@storybook/react'; + +import { + SelectRoot, + SelectTrigger, + SelectValue, + SelectContent, + SelectScrollUpButton, + SelectScrollDownButton, + SelectItem, + SelectSeparator, + SelectGroup, + SelectLabel, +} from './index'; + +export default { + title: 'Components/Select', + component: SelectRoot, +} as Meta; + +const Template: StoryFn = (args) => ( + + + + + + + Option 1 + Option 2 + Option 3 + + + +); + +export const Default = Template.bind({}); +Default.args = { + defaultValue: 'option1', +}; + +export const WithSeparator: StoryFn = () => ( + + + + + + + Option 1 + + Option 2 + Option 3 + + + +); + +export const WithLabel: StoryFn = () => ( + + + + + + + Options + Option 1 + Option 2 + Option 3 + + + +); + +export const ScrollButtons: StoryFn = () => ( + + + + + + + Option 1 + Option 2 + Option 3 + + + +); + +export const DisabledOptions: StoryFn = () => ( + + + + + + Option 1 + + Option 2 (Disabled) + + Option 3 + + +); + +export const CustomStyles: StoryFn = () => ( + + + + + + Option 1 + Option 2 + Option 3 + + +); + +export const GroupedOptions: StoryFn = () => ( + + + + + + + Group 1 + Option 1 + Option 2 + + + + Group 2 + Option 1 + Option 2 + + + +); diff --git a/src/components/ui/select/index.tsx b/src/components/ui/select/index.tsx index ad31b0d..5da75b0 100644 --- a/src/components/ui/select/index.tsx +++ b/src/components/ui/select/index.tsx @@ -6,139 +6,139 @@ import { Check, ChevronDown, ChevronUp } from 'lucide-react'; import { cn } from '@/utils'; -const Select = SelectPrimitive.Root; +const baseClasses = { + trigger: + 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1', + scrollButton: 'flex cursor-default items-center justify-center py-1', + content: + 'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md 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', + contentPopper: + 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', + viewport: 'p-1', + viewportPopper: + 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]', + label: 'py-1.5 pl-8 pr-2 text-sm font-semibold', + item: 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', + itemIndicator: 'absolute left-2 flex h-3.5 w-3.5 items-center justify-center', + separator: '-mx-1 my-1 h-px bg-muted', +}; + +const SelectRoot = 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; +>(function SelectTrigger({ className, children, ...props }, ref) { + return ( + + {children} + + + + + ); +}); const SelectScrollUpButton = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)); -SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; +>(function SelectScrollUpButton({ className, ...props }, ref) { + return ( + + + + ); +}); const SelectScrollDownButton = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)); -SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName; +>(function SelectScrollDownButton({ className, ...props }, ref) { + return ( + + + + ); +}); const SelectContent = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, children, position = 'popper', ...props }, ref) => ( - - - - (function SelectContent({ className, children, position = 'popper', ...props }, ref) { + return ( + + - {children} - - - - -)); -SelectContent.displayName = SelectPrimitive.Content.displayName; + + + {children} + + + + + ); +}); const SelectLabel = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SelectLabel.displayName = SelectPrimitive.Label.displayName; +>(function SelectLabel({ className, ...props }, ref) { + return ( + + ); +}); const SelectItem = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - - {children} - -)); -SelectItem.displayName = SelectPrimitive.Item.displayName; +>(function SelectItem({ className, children, ...props }, ref) { + return ( + + + + + + + {children} + + ); +}); const SelectSeparator = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SelectSeparator.displayName = SelectPrimitive.Separator.displayName; +>(function SelectSeparator({ className, ...props }, ref) { + return ( + + ); +}); export { - Select, + SelectRoot, SelectGroup, SelectValue, SelectTrigger, diff --git a/src/components/ui/tooltip/index.stories.tsx b/src/components/ui/tooltip/index.stories.tsx new file mode 100644 index 0000000..65f29a5 --- /dev/null +++ b/src/components/ui/tooltip/index.stories.tsx @@ -0,0 +1,124 @@ +import * as React from 'react'; +import { Meta, StoryFn } from '@storybook/react'; + +import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './index'; + +export default { + title: 'Components/Tooltip', + component: Tooltip, + subcomponents: { TooltipTrigger, TooltipContent, TooltipProvider }, +} as Meta; + +const Template: StoryFn = (args) => ( + + + + + + +

This is a tooltip content

+
+
+
+); + +export const Default = Template.bind({}); +Default.args = { + sideOffset: 4, +}; + +export const WithDifferentPosition: StoryFn = () => ( + +
+ + + + + +

Tooltip on top

+
+
+ + + + + +

Tooltip on right

+
+
+ + + + + +

Tooltip on bottom

+
+
+ + + + + +

Tooltip on left

+
+
+
+
+); + +export const CustomStyles: StoryFn = () => ( + + + + + + +

Custom styled tooltip content

+
+
+
+); + +export const WithDelay: StoryFn = () => ( + + + + + + +

This tooltip has a custom delay

+
+
+
+); + +export const InsideMenu: StoryFn = () => ( + +
+ + + Item 1 + + +

Tooltip for Item 1

+
+
+ + + Item 2 + + +

Tooltip for Item 2

+
+
+ + + Item 3 + + +

Tooltip for Item 3

+
+
+
+
+); diff --git a/src/components/ui/tooltip/index.tsx b/src/components/ui/tooltip/index.tsx index 68c75ee..eeb06cb 100644 --- a/src/components/ui/tooltip/index.tsx +++ b/src/components/ui/tooltip/index.tsx @@ -5,26 +5,32 @@ import * as TooltipPrimitive from '@radix-ui/react-tooltip'; import { cn } from '@/utils'; -const TooltipProvider = TooltipPrimitive.Provider; +const TooltipProvider = ({ children, ...props }) => ( + {children} +); const Tooltip = TooltipPrimitive.Root; - const TooltipTrigger = TooltipPrimitive.Trigger; +const baseTooltipContentClasses = + 'z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95'; +const stateClasses = + 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95'; +const sideClasses = + '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 TooltipContent = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - -)); -TooltipContent.displayName = TooltipPrimitive.Content.displayName; +>(function TooltipContent({ className, sideOffset = 4, ...props }, ref) { + return ( + + ); +}); export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };