From 204b4e04a3f43ef970be136c1c32986dc2bf2604 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Wed, 13 Mar 2024 18:00:21 +0800 Subject: [PATCH] fix: FormItemLayout width fix, `` renamed with prop name reverted, started new form story (#21989) * init * Fix some TS errors. Comment out a unspecified form field. --------- Co-authored-by: Ivan Vasilov --- .../AIPolicyEditorPanel/AIPolicyHeader.tsx | 18 +- .../Policies/AIPolicyEditorPanel/index.tsx | 18 +- .../ui-patterns/InfoTooltip/InfoTooltip.tsx | 6 +- packages/ui-patterns/form/FormLayout2.tsx | 434 ++++++++++++++++++ .../ui-patterns/form/Layout/FormLayout.tsx | 4 +- packages/ui-patterns/form/Page2.stories.tsx | 37 ++ packages/ui/index.tsx | 12 +- .../ui/src/components/shadcn/ui/sheet.tsx | 214 ++++----- 8 files changed, 608 insertions(+), 135 deletions(-) create mode 100644 packages/ui-patterns/form/FormLayout2.tsx create mode 100644 packages/ui-patterns/form/Page2.stories.tsx diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx index 2b3ea1336d9..ced99acc728 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx @@ -2,9 +2,9 @@ import type { PostgresPolicy } from '@supabase/postgres-meta' import clsx from 'clsx' import { PanelLeftClose, PanelRightClose, X } from 'lucide-react' import { - SheetClose_Shadcn_, - SheetHeader_Shadcn_, - SheetTitle_Shadcn_, + SheetClose, + SheetHeader, + SheetTitle, TooltipContent_Shadcn_, TooltipTrigger_Shadcn_, Tooltip_Shadcn_, @@ -21,14 +21,14 @@ export const AIPolicyHeader = ({ setAssistantVisible: (v: boolean) => void }) => { return ( -
- Close - +
- + {selectedPolicy !== undefined ? `Update policy: ${selectedPolicy.name}` : 'Create a new Row Level Security policy'} - +
@@ -69,6 +69,6 @@ export const AIPolicyHeader = ({ {assistantVisible ? 'Hide' : 'Show'} tools - + ) } diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx index ef37455eb38..c37158fdd30 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx @@ -14,9 +14,9 @@ import { IconGrid, Modal, ScrollArea, - SheetContent_Shadcn_, - SheetFooter_Shadcn_, - Sheet_Shadcn_, + SheetContent, + SheetFooter, + Sheet, TabsContent_Shadcn_, TabsList_Shadcn_, TabsTrigger_Shadcn_, @@ -293,8 +293,8 @@ export const AIPolicyEditorPanel = memo(function ({ return ( <> - onClosingPanel()}> - onClosingPanel()}> + )} - + @@ -419,7 +419,7 @@ export const AIPolicyEditorPanel = memo(function ({ Save policy
- + @@ -512,8 +512,8 @@ export const AIPolicyEditorPanel = memo(function ({

- - + +
) }) diff --git a/packages/ui-patterns/InfoTooltip/InfoTooltip.tsx b/packages/ui-patterns/InfoTooltip/InfoTooltip.tsx index a712a069192..ae2f2004fdf 100644 --- a/packages/ui-patterns/InfoTooltip/InfoTooltip.tsx +++ b/packages/ui-patterns/InfoTooltip/InfoTooltip.tsx @@ -23,7 +23,11 @@ const InfoTooltip = forwardRef< >(({ ...props }, ref) => { return ( - + diff --git a/packages/ui-patterns/form/FormLayout2.tsx b/packages/ui-patterns/form/FormLayout2.tsx new file mode 100644 index 00000000000..22df7d26056 --- /dev/null +++ b/packages/ui-patterns/form/FormLayout2.tsx @@ -0,0 +1,434 @@ +import { zodResolver } from '@hookform/resolvers/zod' +import { Box, FileWarning } from 'lucide-react' +import { useForm } from 'react-hook-form' +import { + Badge_Shadcn_, + Button, + Checkbox_Shadcn_, + Form_Shadcn_, + FormControl_Shadcn_, + FormField_Shadcn_, + RadioGroup_Shadcn_, + RadioGroupItem_Shadcn_, + Select_Shadcn_, + SelectContent_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, + Separator, + Sheet, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetSection, + SheetTitle, + SidePanel, + Switch, +} from 'ui' +import { z } from 'zod' +import { Input } from '../DataInputs/Input' +import { InfoTooltip } from '../InfoTooltip/InfoTooltip' +import { FormItemLayout } from './FormItemLayout/FormItemLayout' + +const items = [ + { + id: 'recents', + label: 'Recents', + }, + { + id: 'home', + label: 'Home', + }, + { + id: 'applications', + label: 'Applications', + }, + { + id: 'desktop', + label: 'Desktop', + }, + { + id: 'downloads', + label: 'Downloads', + }, + { + id: 'documents', + label: 'Documents', + }, +] as const + +export const Page = () => { + const FormSchema = z.object({ + username: z.string().min(2, { + message: 'Username must be at least 2 characters.', + }), + kevins_input: z.string().min(6, { + message: 'Username must be at least 6 characters.', + }), + email: z + .string({ + required_error: 'Please select an email to display.', + }) + .email(), + consistent_settings: z.boolean().default(false).optional(), + switch_option: z.boolean().default(false).optional(), + items: z.array(z.string()).refine((value) => value.some((item) => item), { + message: 'You have to select at least one item.', + }), + type: z.enum(['all', 'mentions', 'none'], { + required_error: 'You need to select a notification type.', + }), + }) + + const form = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { + username: '', + items: ['recents', 'home'], + }, + }) + + function onSubmit(data: z.infer) { + console.log(data) + } + + const UserIcon = () => { + return ( +
+ +
+ ) + } + + return ( + + + + Create a function + Create a function + + +
+ + ( + You can also rename this later. + } + > + + + + + )} + /> + + + + {/* ( + + Language + + + + + + + + + + No language found. + + {languages.map((language) => ( + { + form.setValue('language', language.value) + }} + > + + {language.label} + + ))} + + + + + + This is the language that will be used in the dashboard. + + + + )} + /> */} + + ( + + + + + + )} + /> + + + + ( + + + + + + + + + +
+ + m@example.com +
+
+ +
+ + UserIconm@google.com +
+
+ +
+ + m@support.com +
+
+
+
+
+ )} + /> +
+ + + + + ( + + + } + placeholder="Needs to be 6 long" + {...field} + /> + + + )} + /> + + + + + + ( + + + Danger zone! + + } + label="Use consistent settings" + description="This is your public display name." + layout="flex" + > + + + + + )} + /> + + + + + + ( + Please give me info} + > + {/*
+ Sidebar + + Select the items you want to display in the sidebar. + +
*/} + {items.map((item) => ( + { + return ( + + + { + return checked + ? field.onChange([...field.value, item.id]) + : field.onChange( + field.value?.filter((value) => value !== item.id) + ) + }} + /> + + + ) + }} + /> + ))} + {/* */} +
+ )} + /> +
+ + + ( + + + + + + + + + + + + + + + + + + + + + + )} + /> + + + + + + +
+
+
+ ) +} diff --git a/packages/ui-patterns/form/Layout/FormLayout.tsx b/packages/ui-patterns/form/Layout/FormLayout.tsx index 2805b481748..d4adde5c66f 100644 --- a/packages/ui-patterns/form/Layout/FormLayout.tsx +++ b/packages/ui-patterns/form/Layout/FormLayout.tsx @@ -41,7 +41,7 @@ const ContainerVariants = cva('grid gap-2', { false: '', }, layout: { - horizontal: 'flex flex-row gap-6 justify-between', + horizontal: 'grid grid-cols-12', vertical: 'flex flex-col gap-3', flex: 'flex flex-row gap-3', }, @@ -71,7 +71,7 @@ const LabelContainerVariants = cva('', { right: '', }, layout: { - horizontal: 'flex flex-col gap-2', + horizontal: 'flex flex-col gap-2 col-span-4', vertical: 'flex flex-row gap-2 justify-between', flex: 'flex flex-col gap-0', }, diff --git a/packages/ui-patterns/form/Page2.stories.tsx b/packages/ui-patterns/form/Page2.stories.tsx new file mode 100644 index 00000000000..84956639fcb --- /dev/null +++ b/packages/ui-patterns/form/Page2.stories.tsx @@ -0,0 +1,37 @@ +// import { within, userEvent, expect } from '@storybook/test' +import { TooltipProvider_Shadcn_ } from 'ui' +import { Page } from './FormLayout2' + +export default { + title: 'Form Examples/Side Panel Function Create', + component: Page, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'centered', + }, + decorators: [ + (Story: any) => { + return ( + + + + ) + }, + ], +} + +export const StateOne = {} + +// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing +// export const LoggedIn = { +// play: async ({ canvasElement }) => { +// const canvas = within(canvasElement) +// const loginButton = canvas.getByRole('button', { name: /Log in/i }) +// await expect(loginButton).toBeInTheDocument() +// await userEvent.click(loginButton) +// await expect(loginButton).not.toBeInTheDocument() + +// const logoutButton = canvas.getByRole('button', { name: /Log out/i }) +// await expect(logoutButton).toBeInTheDocument() +// }, +// } diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index 3900e6bfb7c..c9937e3cba4 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -85,6 +85,7 @@ export * from './src/components/shadcn/ui/toaster' export { Badge as Badge_Shadcn_ } from './src/components/shadcn/ui/badge' export * from './src/components/shadcn/ui/separator' +export * from './src/components/shadcn/ui/sheet' export { Command as Command_Shadcn_, @@ -171,17 +172,6 @@ export { CollapsibleContent as CollapsibleContent_Shadcn_, } from './src/components/shadcn/ui/collapsible' -export { - Sheet as Sheet_Shadcn_, - SheetTrigger as SheetTrigger_Shadcn_, - SheetClose as SheetClose_Shadcn_, - SheetContent as SheetContent_Shadcn_, - SheetHeader as SheetHeader_Shadcn_, - SheetFooter as SheetFooter_Shadcn_, - SheetTitle as SheetTitle_Shadcn_, - SheetDescription as SheetDescription_Shadcn_, -} from './src/components/shadcn/ui/sheet' - export { Tabs as Tabs_Shadcn_, TabsContent as TabsContent_Shadcn_, diff --git a/packages/ui/src/components/shadcn/ui/sheet.tsx b/packages/ui/src/components/shadcn/ui/sheet.tsx index d7e47afbf07..3600c2f60a9 100644 --- a/packages/ui/src/components/shadcn/ui/sheet.tsx +++ b/packages/ui/src/components/shadcn/ui/sheet.tsx @@ -5,6 +5,7 @@ import { cva, type VariantProps } from 'class-variance-authority' import * as React from 'react' import { cn } from '../../../lib/utils/cn' +import { X } from 'lucide-react' const Sheet = SheetPrimitive.Root @@ -14,23 +15,23 @@ const SheetClose = SheetPrimitive.Close const portalVariants = cva('fixed inset-0 z-40 flex', { variants: { - position: { + side: { top: 'items-start', bottom: 'items-end', left: 'justify-start', right: 'justify-end', }, }, - defaultVariants: { position: 'right' }, + defaultVariants: { side: 'right' }, }) interface SheetPortalProps extends SheetPrimitive.DialogPortalProps, VariantProps {} -const SheetPortal = ({ position, children, ...props }: SheetPortalProps) => ( +const SheetPortal = ({ side, children, ...props }: SheetPortalProps) => ( -
{children}
+
{children}
) SheetPortal.displayName = SheetPrimitive.Portal.displayName @@ -41,7 +42,7 @@ const SheetOverlay = React.forwardRef< >(({ className, children, ...props }, ref) => ( , @@ -151,32 +149,41 @@ export interface DialogContentProps const SheetContent = React.forwardRef< React.ElementRef, DialogContentProps ->(({ position, size, className, children, ...props }, ref) => ( - +>(({ side, size, className, children, ...props }, ref) => ( + {children} - {/* + Close - */} + )) SheetContent.displayName = SheetPrimitive.Content.displayName const SheetHeader = ({ className, ...props }: React.HTMLAttributes) => ( -
+
) SheetHeader.displayName = 'SheetHeader' +const SheetSection = ({ className, ...props }: React.HTMLAttributes) => ( +
+) +SheetSection.displayName = 'SheetSection' + const SheetFooter = ({ className, ...props }: React.HTMLAttributes) => (
) @@ -211,8 +218,9 @@ export { SheetClose, SheetContent, SheetDescription, - SheetFooter, SheetHeader, + SheetSection, + SheetFooter, SheetTitle, SheetTrigger, }