diff --git a/packages/propel/src/combobox/combobox.stories.tsx b/packages/propel/src/combobox/combobox.stories.tsx index 5789514249b..42bfc32a75a 100644 --- a/packages/propel/src/combobox/combobox.stories.tsx +++ b/packages/propel/src/combobox/combobox.stories.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import type { Meta, StoryObj } from "@storybook/react-vite"; import { Check, ChevronsUpDown } from "lucide-react"; import { useArgs } from "storybook/preview-api"; -import { Combobox } from "./combobox"; +import { Combobox, ComboboxButton, ComboboxOptions, ComboboxOption } from "./combobox"; const frameworks = [ { value: "react", label: "React" }, @@ -19,9 +19,9 @@ const meta = { title: "Components/Combobox", component: Combobox, subcomponents: { - ComboboxButton: Combobox.Button, - ComboboxOptions: Combobox.Options, - ComboboxOption: Combobox.Option, + ComboboxButton, + ComboboxOptions, + ComboboxOption, }, parameters: { layout: "centered", @@ -37,22 +37,22 @@ const meta = { const setValue = (newValue: string | string[]) => updateArgs({ value: newValue }); return ( setValue(v as string)}> - + {value ? frameworks.find((f) => f.value === value)?.label : "Select framework..."} - - + + {frameworks.map((framework) => ( - {value === framework.value && } {framework.label} - + ))} - + ); }, @@ -68,22 +68,22 @@ export const WithoutSearch: Story = { const [value, setValue] = useState(""); return ( setValue(v as string)}> - + {value ? frameworks.find((f) => f.value === value)?.label : "Select framework..."} - - + + {frameworks.map((framework) => ( - {value === framework.value && } {framework.label} - + ))} - + ); }, @@ -95,22 +95,22 @@ export const MultiSelect: Story = { return ( setValue(v as string[])}> - + {value.length > 0 ? `${value.length} selected` : "Select frameworks..."} - - + + {frameworks.map((framework) => ( - {value.includes(framework.value) && } {framework.label} - + ))} - + ); }, @@ -123,24 +123,24 @@ export const MultiSelectWithLimit: Story = { return (
setValue(v as string[])}> - + {value.length > 0 ? `${value.length}/3 selected` : "Select up to 3 frameworks..."} - - + + {frameworks.map((framework) => ( - {value.includes(framework.value) && } {framework.label} - + ))} - +

Maximum 3 selections allowed

@@ -154,22 +154,22 @@ export const Disabled: Story = { const [value, setValue] = useState(""); return ( setValue(v as string)}> - + {value ? frameworks.find((f) => f.value === value)?.label : "Select framework..."} - - + + {frameworks.map((framework) => ( - {value === framework.value && } {framework.label} - + ))} - + ); }, @@ -180,13 +180,13 @@ export const DisabledOptions: Story = { const [value, setValue] = useState(""); return ( setValue(v as string)}> - + {value ? frameworks.find((f) => f.value === value)?.label : "Select framework..."} - - + + {frameworks.map((framework) => ( - {value === framework.value && } {framework.label} - + ))} - + ); }, @@ -207,22 +207,22 @@ export const CustomMaxHeight: Story = { const [value, setValue] = useState(""); return ( setValue(v as string)}> - + {value ? frameworks.find((f) => f.value === value)?.label : "Select framework..."} - - + + {frameworks.map((framework) => ( - {value === framework.value && } {framework.label} - + ))} - + ); }, @@ -233,27 +233,27 @@ export const CustomEmptyMessage: Story = { const [value, setValue] = useState(""); return ( setValue(v as string)}> - + {value ? frameworks.find((f) => f.value === value)?.label : "Select framework..."} - - + {frameworks.map((framework) => ( - {value === framework.value && } {framework.label} - + ))} - + ); }, diff --git a/packages/propel/src/combobox/combobox.tsx b/packages/propel/src/combobox/combobox.tsx index 94b307533c8..65567041459 100644 --- a/packages/propel/src/combobox/combobox.tsx +++ b/packages/propel/src/combobox/combobox.tsx @@ -220,11 +220,10 @@ function ComboboxOption({ value, children, disabled, className }: ComboboxOption ); } -// Compound component export -const Combobox = Object.assign(ComboboxRoot, { - Button: ComboboxButton, - Options: ComboboxOptions, - Option: ComboboxOption, -}); +ComboboxRoot.displayName = "Combobox"; +ComboboxButton.displayName = "ComboboxButton"; +ComboboxOptions.displayName = "ComboboxOptions"; +ComboboxOption.displayName = "ComboboxOption"; + -export { Combobox }; +export { ComboboxRoot as Combobox, ComboboxButton, ComboboxOptions, ComboboxOption }; diff --git a/packages/propel/src/command/command.stories.tsx b/packages/propel/src/command/command.stories.tsx index 9f41c9b4b93..86378ca59c8 100644 --- a/packages/propel/src/command/command.stories.tsx +++ b/packages/propel/src/command/command.stories.tsx @@ -1,15 +1,15 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; import { File, Folder, Settings, User } from "lucide-react"; -import { Command } from "./command"; +import { Command, CommandInput, CommandList, CommandItem, CommandEmpty } from "./command"; const meta = { title: "Components/Command", component: Command, subcomponents: { - CommandInput: Command.Input, - CommandList: Command.List, - CommandItem: Command.Item, - CommandEmpty: Command.Empty, + CommandInput, + CommandList, + CommandItem, + CommandEmpty, }, parameters: { layout: "centered", @@ -24,13 +24,13 @@ export const Default: Story = { render() { return ( - - - Item 1 - Item 2 - Item 3 - - No results found. + + + Item 1 + Item 2 + Item 3 + + No results found. ); }, @@ -40,29 +40,29 @@ export const WithIcons: Story = { render() { return ( - - - + + Documents - - + + Downloads - - + + README.md - - + + package.json - - - No files or folders found. + + + No files or folders found. ); }, @@ -72,32 +72,32 @@ export const WithCategories: Story = { render() { return ( - - +
User
- + Profile - - + + Settings - +
Files
- + Open Folder - - + + New File - -
- No commands found. + + + No commands found.
); }, @@ -107,12 +107,12 @@ export const EmptyState: Story = { render() { return ( - - {/* No items - will show empty state */} - + + {/* No items - will show empty state */} +

No results found

Try searching for something else

-
+
); }, @@ -122,15 +122,15 @@ export const LongList: Story = { render() { return ( - - + + {Array.from({ length: 20 }, (_, i) => ( - + Item {i + 1} - + ))} - - No results found. + + No results found. ); }, @@ -140,20 +140,20 @@ export const WithoutSearch: Story = { render() { return ( - - + + Profile - - + + Settings - - + + Files - - + + ); }, @@ -163,22 +163,22 @@ export const CustomStyling: Story = { render() { return ( - - - + + Custom Item 1 - - + + Custom Item 2 - - + + Custom Item 3 - - - No matching items found. + + + No matching items found. ); }, @@ -188,15 +188,15 @@ export const DisabledItems: Story = { render() { return ( - - - Active Item 1 - + + + Active Item 1 + Disabled Item - - Active Item 2 - - No results found. + + Active Item 2 + + No results found. ); }, diff --git a/packages/propel/src/command/command.tsx b/packages/propel/src/command/command.tsx index e462a7f2d79..4c46d9babd3 100644 --- a/packages/propel/src/command/command.tsx +++ b/packages/propel/src/command/command.tsx @@ -31,11 +31,11 @@ function CommandItem({ ...props }: React.ComponentProps; } -const Command = Object.assign(CommandComponent, { - Input: CommandInput, - List: CommandList, - Empty: CommandEmpty, - Item: CommandItem, -}); +// Display names for debugging +CommandComponent.displayName = "Command"; +CommandInput.displayName = "CommandInput"; +CommandList.displayName = "CommandList"; +CommandEmpty.displayName = "CommandEmpty"; +CommandItem.displayName = "CommandItem"; -export { Command }; +export { CommandComponent as Command, CommandInput, CommandList, CommandEmpty, CommandItem }; diff --git a/packages/propel/src/context-menu/context-menu.stories.tsx b/packages/propel/src/context-menu/context-menu.stories.tsx index a378dbd196f..08576aa0df8 100644 --- a/packages/propel/src/context-menu/context-menu.stories.tsx +++ b/packages/propel/src/context-menu/context-menu.stories.tsx @@ -1,20 +1,20 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; import { Copy, Download, Edit, Share, Trash, Star, Archive } from "lucide-react"; import { ChevronRightIcon } from "../icons/arrows/chevron-right"; -import { ContextMenu } from "./context-menu"; +import { ContextMenu, ContextMenuTrigger, ContextMenuPortal, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuSubmenu, ContextMenuSubmenuTrigger } from "./context-menu"; // cannot use satisfies here because base-ui does not have portable types. const meta: Meta = { title: "Components/ContextMenu", component: ContextMenu, subcomponents: { - ContextMenuTrigger: ContextMenu.Trigger, - ContextMenuPortal: ContextMenu.Portal, - ContextMenuContent: ContextMenu.Content, - ContextMenuItem: ContextMenu.Item, - ContextMenuSeparator: ContextMenu.Separator, - ContextMenuSubmenu: ContextMenu.Submenu, - ContextMenuSubmenuTrigger: ContextMenu.SubmenuTrigger, + ContextMenuTrigger, + ContextMenuPortal, + ContextMenuContent, + ContextMenuItem, + ContextMenuSeparator, + ContextMenuSubmenu, + ContextMenuSubmenuTrigger, }, args: { children: null, @@ -32,20 +32,20 @@ export const Default: Story = { render() { return ( - +
Right click here
-
- - - Back - Forward - Reload - - More Tools - - + + + + Back + Forward + Reload + + More Tools + +
); }, @@ -55,36 +55,36 @@ export const WithIcons: Story = { render() { return ( - +
Right click here
-
- - - + + + + Copy - - + + Edit - - + + Download - - - + + + Share - - + + Delete - - - + + +
); }, @@ -94,43 +94,43 @@ export const WithSubmenus: Story = { render() { return ( - +
Right click here
-
- - - + + + + Copy - - + + Edit - - - - + + + + Share - - - - Email - Message - Copy Link - - - - - + + + + Email + Message + Copy Link + + + + + Delete - - - + + +
); }, @@ -140,36 +140,36 @@ export const DisabledItems: Story = { render() { return ( - +
Right click here
-
- - - + + + + Copy - - + + Edit (Disabled) - - + + Download - - - + + + Share (Disabled) - - + + Delete - - - + + +
); }, @@ -179,7 +179,7 @@ export const OnFileCard: Story = { render() { return ( - +
@@ -191,32 +191,32 @@ export const OnFileCard: Story = {
-
- - - + + + + Download - - + + Copy Link - - + + Add to Favorites - - - + + + Archive - - + + Delete - - - + + +
); }, @@ -226,31 +226,31 @@ export const OnImage: Story = { render() { return ( - +
Image Placeholder
-
- - - + + + + Save Image - - + + Copy Image - - + + Copy Image URL - - - Open Image in New Tab - - + + + Open Image in New Tab + +
); }, @@ -260,7 +260,7 @@ export const OnText: Story = { render() { return ( - +

Context Menu on Text

@@ -268,21 +268,21 @@ export const OnText: Story = { applied to text content areas.

-
- - - + + + + Copy - - + + Edit - - - Select All - - + + + Select All + +
); }, @@ -292,48 +292,48 @@ export const NestedSubmenus: Story = { render() { return ( - +
Right click here
-
- - - New File - New Folder - - - + + + + New File + New Folder + + + Import - - - - From File - From URL - - + + + + From File + From URL + + From Cloud - - - - Google Drive - Dropbox - OneDrive - - - - - - - - + + + + Google Drive + Dropbox + OneDrive + + + + + + + + Delete - - - + + +
); }, @@ -343,36 +343,36 @@ export const WithKeyboardShortcuts: Story = { render() { return ( - +
Right click here
-
- - - + + + + Copy ⌘C - - + + Edit ⌘E - - + + Download ⌘D - - - + + + Delete ⌘⌫ - - - + + +
); }, diff --git a/packages/propel/src/context-menu/context-menu.tsx b/packages/propel/src/context-menu/context-menu.tsx index 494cceb6706..5e916a1eaa9 100644 --- a/packages/propel/src/context-menu/context-menu.tsx +++ b/packages/propel/src/context-menu/context-menu.tsx @@ -128,15 +128,13 @@ ContextMenuItem.displayName = "ContextMenuItem"; ContextMenuSeparator.displayName = "ContextMenuSeparator"; ContextMenuSubmenuTrigger.displayName = "ContextMenuSubmenuTrigger"; -// compound components -const ContextMenu = Object.assign(ContextMenuRoot, { - Trigger: ContextMenuTrigger, - Portal: ContextMenuPortal, - Content: ContextMenuContent, - Item: ContextMenuItem, - Separator: ContextMenuSeparator, - Submenu: ContextMenuSubmenu, - SubmenuTrigger: ContextMenuSubmenuTrigger, -}); - -export { ContextMenu }; +export { + ContextMenuRoot as ContextMenu, + ContextMenuTrigger, + ContextMenuPortal, + ContextMenuContent, + ContextMenuItem, + ContextMenuSeparator, + ContextMenuSubmenu, + ContextMenuSubmenuTrigger, +}; diff --git a/packages/propel/src/context-menu/index.ts b/packages/propel/src/context-menu/index.ts index 7a0cbc670c9..5cc8201c916 100644 --- a/packages/propel/src/context-menu/index.ts +++ b/packages/propel/src/context-menu/index.ts @@ -1,4 +1,13 @@ -export { ContextMenu } from "./context-menu"; +export { + ContextMenu, + ContextMenuTrigger, + ContextMenuPortal, + ContextMenuContent, + ContextMenuItem, + ContextMenuSeparator, + ContextMenuSubmenu, + ContextMenuSubmenuTrigger, +} from "./context-menu"; export type { ContextMenuProps, ContextMenuTriggerProps, diff --git a/packages/propel/src/dialog/dialog.stories.tsx b/packages/propel/src/dialog/dialog.stories.tsx index cf9ccff56d8..2ba3a54804a 100644 --- a/packages/propel/src/dialog/dialog.stories.tsx +++ b/packages/propel/src/dialog/dialog.stories.tsx @@ -2,14 +2,14 @@ import { useState } from "react"; import type { Meta, StoryObj } from "@storybook/react-vite"; import { useArgs } from "storybook/preview-api"; import { CloseIcon } from "../icons/actions/close-icon"; -import { Dialog, EDialogWidth } from "./root"; +import { Dialog, DialogPanel, DialogTitle, EDialogWidth } from "./root"; const meta = { title: "Components/Dialog", component: Dialog, subcomponents: { - DialogPanel: Dialog.Panel, - DialogTitle: Dialog.Title, + DialogPanel, + DialogTitle, }, args: { children: null, @@ -31,9 +31,9 @@ const meta = { {open && ( - +
- Dialog Title + Dialog Title

This is the dialog content. You can put any content here.

@@ -52,7 +52,7 @@ const meta = {
-
+
)} @@ -79,9 +79,9 @@ export const TopPosition: Story = { {open && ( - +
- Top Positioned Dialog + Top Positioned Dialog

This dialog appears at the top of the screen instead of centered. @@ -96,7 +96,7 @@ export const TopPosition: Story = {

-
+
)} @@ -114,9 +114,9 @@ export const SmallWidth: Story = { {open && ( - +
- Small Dialog + Small Dialog

This is a small dialog.

@@ -129,7 +129,7 @@ export const SmallWidth: Story = {
-
+
)} @@ -147,9 +147,9 @@ export const LargeWidth: Story = { {open && ( - +
- Large Dialog + Large Dialog

This is a large dialog with more horizontal space for content. @@ -164,7 +164,7 @@ export const LargeWidth: Story = {

-
+
)} @@ -182,10 +182,10 @@ export const WithCloseButton: Story = { {open && ( - +
- Dialog with Close Button + Dialog with Close Button @@ -194,7 +194,7 @@ export const WithCloseButton: Story = {

This dialog has a close button in the header.

-
+
)} @@ -216,9 +216,9 @@ export const ConfirmationDialog: Story = { {open && ( - +
- Confirm Deletion + Confirm Deletion

Are you sure you want to delete this item? This action cannot be undone. @@ -239,7 +239,7 @@ export const ConfirmationDialog: Story = {

-
+
)} @@ -262,9 +262,9 @@ export const FormDialog: Story = { {open && ( - +
- Create New Item + Create New Item
- +
)} @@ -320,9 +320,9 @@ export const ScrollableContent: Story = { {open && ( - +
- Scrollable Content + Scrollable Content
{Array.from({ length: 20 }, (_, i) => (

@@ -340,7 +340,7 @@ export const ScrollableContent: Story = {

-
+
)} @@ -375,9 +375,9 @@ export const AllWidths: Story = { ))} {widths.map(({ width, label }) => ( setOpenWidth(null)}> - +
- {label} Dialog + {label} Dialog

This dialog uses the {label} width variant.

@@ -390,7 +390,7 @@ export const AllWidths: Story = {
-
+
))} diff --git a/packages/propel/src/dialog/root.tsx b/packages/propel/src/dialog/root.tsx index e0a518b228f..6ccfd8db474 100644 --- a/packages/propel/src/dialog/root.tsx +++ b/packages/propel/src/dialog/root.tsx @@ -34,6 +34,18 @@ export interface DialogTitleProps extends React.ComponentProps { + children: React.ReactNode; +} + +export interface DialogOverlayProps extends React.ComponentProps { + className?: string; +} + +export interface DialogTriggerProps extends React.ComponentProps { + children: React.ReactNode; +} + // Constants const OVERLAY_CLASSNAME = cn("fixed inset-0 z-backdrop bg-custom-backdrop"); const BASE_CLASSNAME = "relative text-left bg-custom-background-100 rounded-lg shadow-md w-full z-modal"; @@ -122,14 +134,6 @@ const DialogTitle = memo(function DialogTitle({ className, children, ...props }: }); DialogTitle.displayName = "DialogTitle"; +DialogComponent.displayName = "Dialog"; -// Create the compound Dialog component with proper typing -const Dialog = Object.assign(DialogComponent, { - Panel: DialogPanel, - Title: DialogTitle, -}) as typeof DialogComponent & { - Panel: typeof DialogPanel; - Title: typeof DialogTitle; -}; - -export { Dialog, DialogTitle, DialogPanel }; +export { DialogComponent as Dialog, DialogTitle, DialogPanel, DialogTrigger }; diff --git a/packages/propel/src/emoji-icon-picker/emoji-picker.tsx b/packages/propel/src/emoji-icon-picker/emoji-picker.tsx index fcb22d310c7..58b9b6cdb6a 100644 --- a/packages/propel/src/emoji-icon-picker/emoji-picker.tsx +++ b/packages/propel/src/emoji-icon-picker/emoji-picker.tsx @@ -1,6 +1,6 @@ import { useMemo, useCallback } from "react"; import { Tabs } from "@base-ui-components/react"; -import { Popover } from "../popover"; +import { Popover, PopoverTrigger, PopoverContent } from "../popover"; import { cn } from "../utils/classname"; import { convertPlacementToSideAndAlign } from "../utils/placement"; import { EmojiRoot } from "./emoji/emoji"; @@ -95,10 +95,10 @@ export function EmojiPicker(props: TCustomEmojiPicker) { return ( - + {label} - - + ))} - + ); } diff --git a/packages/propel/src/emoji-reaction/emoji-reaction-picker.tsx b/packages/propel/src/emoji-reaction/emoji-reaction-picker.tsx index e1cb4740b39..cfe49a07577 100644 --- a/packages/propel/src/emoji-reaction/emoji-reaction-picker.tsx +++ b/packages/propel/src/emoji-reaction/emoji-reaction-picker.tsx @@ -1,7 +1,7 @@ import React, { useMemo, useCallback } from "react"; import { EmojiRoot } from "../emoji-icon-picker/emoji/emoji"; import { emojiToString } from "../emoji-icon-picker/helper"; -import { Popover } from "../popover"; +import { Popover, PopoverTrigger, PopoverContent } from "../popover"; import { cn } from "../utils/classname"; import { convertPlacementToSideAndAlign } from "../utils/placement"; import type { TPlacement, TSide, TAlign } from "../utils/placement"; @@ -59,10 +59,10 @@ export function EmojiReactionPicker(props: EmojiReactionPickerProps) { return ( - + {label} - - + - + ); } diff --git a/packages/propel/src/popover/popover.stories.tsx b/packages/propel/src/popover/popover.stories.tsx index 2a0d60c0a6c..ed52309b8cc 100644 --- a/packages/propel/src/popover/popover.stories.tsx +++ b/packages/propel/src/popover/popover.stories.tsx @@ -2,15 +2,15 @@ import { useState } from "react"; import type { Meta, StoryObj } from "@storybook/react-vite"; import { useArgs } from "storybook/preview-api"; import { CloseIcon } from "../icons/actions/close-icon"; -import { Popover } from "./root"; +import { Popover, PopoverTrigger, PopoverContent } from "./root"; // cannot use satifies here because base-ui does not have portable types. const meta: Meta = { title: "Components/Popover", component: Popover, subcomponents: { - PopoverButton: Popover.Button, - PopoverPanel: Popover.Panel, + PopoverTrigger, + PopoverContent, }, parameters: { layout: "centered", @@ -27,13 +27,13 @@ const meta: Meta = { return ( - + Open Popover - - + +

Popover Title

This is the popover content. You can put any content here.

-
+
); }, @@ -63,10 +63,10 @@ export const Controlled: Story = { - + Controlled Popover - - + +

Controlled State

Current state: {open ? "Open" : "Closed"}

-
+
); @@ -86,13 +86,13 @@ export const SideTop: Story = { const [open, setOpen] = useState(args.open); return ( - + Open Above - - + +

Top Positioned

This popover appears above the button.

-
+
); }, @@ -103,13 +103,13 @@ export const SideBottom: Story = { const [open, setOpen] = useState(args.open); return ( - + Open Below - - + +

Bottom Positioned

This popover appears below the button.

-
+
); }, @@ -120,13 +120,13 @@ export const SideLeft: Story = { const [open, setOpen] = useState(args.open); return ( - + Open Left - - + +

Left Positioned

This popover appears to the left of the button.

-
+
); }, @@ -137,13 +137,13 @@ export const SideRight: Story = { const [open, setOpen] = useState(args.open); return ( - + Open Right - - + +

Right Positioned

This popover appears to the right of the button.

-
+
); }, @@ -154,13 +154,13 @@ export const AlignStart: Story = { const [open, setOpen] = useState(args.open); return ( - + Align Start - - + +

Start Aligned

This popover is aligned to the start.

-
+
); }, @@ -171,13 +171,13 @@ export const AlignEnd: Story = { const [open, setOpen] = useState(args.open); return ( - + Align End - - + +

End Aligned

This popover is aligned to the end.

-
+
); }, @@ -188,13 +188,13 @@ export const CustomOffset: Story = { const [open, setOpen] = useState(args.open); return ( - + Custom Offset - - + +

Custom Side Offset

This popover has a custom side offset of 20px.

-
+
); }, @@ -210,10 +210,10 @@ export const WithForm: Story = { }; return ( - + Open Form - - + +

Quick Form

@@ -251,7 +251,7 @@ export const WithForm: Story = {
-
+
); }, @@ -262,17 +262,17 @@ export const WithList: Story = { const [open, setOpen] = useState(args.open); return ( - + Show Options - - + +

Options

-
+
); }, @@ -285,11 +285,11 @@ export const ColorPicker: Story = { return ( - +
Pick Color - - + +

Select Color

{colors.map((color) => ( @@ -304,7 +304,7 @@ export const ColorPicker: Story = { /> ))}
-
+ ); }, diff --git a/packages/propel/src/popover/root.tsx b/packages/propel/src/popover/root.tsx index d7d9ac40b85..6b2b6e7c9bf 100644 --- a/packages/propel/src/popover/root.tsx +++ b/packages/propel/src/popover/root.tsx @@ -45,6 +45,15 @@ const PopoverContent = memo(function PopoverContent({ }); // wrapper components +const PopoverTrigger = React.memo(function PopoverTrigger(props: React.ComponentProps) { + return ; +}); + +const PopoverPortal = React.memo(function PopoverPortal(props: React.ComponentProps) { + return ; +}); + +const PopoverPositioner = React.memo(function PopoverPositioner(props: React.ComponentProps) { const PopoverTrigger = memo(function PopoverTrigger(props: React.ComponentProps) { return ; }); @@ -58,6 +67,9 @@ const PopoverPositioner = memo(function PopoverPositioner(props: React.Component }); // compound components +const PopoverRoot = React.memo>(function Popover(props) { + return ; +}); const Popover = Object.assign( memo(function Popover(props: React.ComponentProps) { return ; @@ -70,9 +82,9 @@ const Popover = Object.assign( // display names PopoverContent.displayName = "PopoverContent"; -Popover.displayName = "Popover"; +PopoverRoot.displayName = "Popover"; PopoverPortal.displayName = "PopoverPortal"; PopoverTrigger.displayName = "PopoverTrigger"; PopoverPositioner.displayName = "PopoverPositioner"; -export { Popover }; +export { PopoverRoot as Popover, PopoverTrigger, PopoverContent }; diff --git a/packages/propel/src/skeleton/root.tsx b/packages/propel/src/skeleton/root.tsx index 03bb61bd35b..5eeeec97a9d 100644 --- a/packages/propel/src/skeleton/root.tsx +++ b/packages/propel/src/skeleton/root.tsx @@ -2,12 +2,18 @@ import React from "react"; // helpers import { cn } from "../utils/classname"; -type SkeletonProps = { +export type SkeletonProps = { children: React.ReactNode; className?: string; ariaLabel?: string; }; +export type SkeletonItemProps = { + height?: string; + width?: string; + className?: string; +}; + function SkeletonRoot({ children, className = "", ariaLabel = "Loading content" }: SkeletonProps) { return (
@@ -16,13 +22,7 @@ function SkeletonRoot({ children, className = "", ariaLabel = "Loading content" ); } -type ItemProps = { - height?: string; - width?: string; - className?: string; -}; - -function SkeletonItem({ height = "auto", width = "auto", className = "" }: ItemProps) { +function SkeletonItem({ height = "auto", width = "auto", className = "" }: SkeletonItemProps) { return (
- + ); }, @@ -29,10 +29,10 @@ export const Card: Story = { render() { return ( - +
- - + +
); @@ -45,10 +45,10 @@ export const List: Story = { {[...Array(5)].map((_, i) => (
- +
- - + +
))} @@ -62,15 +62,15 @@ export const Table: Story = { return (
- - - + + +
{[...Array(5)].map((_, i) => (
- - - + + +
))}
@@ -83,16 +83,16 @@ export const Profile: Story = { return (
- +
- - + +
- - - + + +
); @@ -103,7 +103,7 @@ export const Avatar: Story = { render() { return ( - + ); }, @@ -114,7 +114,7 @@ export const AvatarGroup: Story = { return ( {[...Array(4)].map((_, i) => ( - + ))} ); @@ -125,10 +125,10 @@ export const Text: Story = { render() { return ( - - - - + + + + ); }, @@ -138,7 +138,7 @@ export const Button: Story = { render() { return ( - + ); }, @@ -148,8 +148,8 @@ export const Input: Story = { render() { return ( - - + + ); }, @@ -160,18 +160,18 @@ export const Form: Story = { return (
- - + +
- - + +
- - + +
- +
); }, @@ -181,13 +181,13 @@ export const ProductCard: Story = { render() { return ( - +
- - - + + +
- +
); }, diff --git a/packages/propel/src/tabs/tabs.stories.tsx b/packages/propel/src/tabs/tabs.stories.tsx index a0a5614fbd1..83e0716568e 100644 --- a/packages/propel/src/tabs/tabs.stories.tsx +++ b/packages/propel/src/tabs/tabs.stories.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import type { Meta, StoryObj } from "@storybook/react-vite"; import { Settings, User, Bell } from "lucide-react"; import { HomeIcon } from "../icons/workspace/home-icon"; -import { Tabs } from "./tabs"; +import { Tabs, TabsList, TabsTrigger, TabsContent, TabsIndicator } from "./tabs"; type TabOption = { label: string; @@ -20,10 +20,10 @@ const meta: Meta = { title: "Components/Tabs", component: Tabs, subcomponents: { - TabsList: Tabs.List, - TabsTrigger: Tabs.Trigger, - TabsContent: Tabs.Content, - TabsIndicator: Tabs.Indicator, + TabsList, + TabsTrigger, + TabsContent, + TabsIndicator, }, parameters: { layout: "centered", @@ -41,21 +41,21 @@ export const Basic: Story = { return (
- + {tabOptions.map((option) => ( - + {option.label} - + ))} - - + + {tabOptions.map((option) => ( - +

{option.label}

Content for the {option.label.toLowerCase()} tab.

-
+ ))}
@@ -77,14 +77,14 @@ export const Sizes: Story = {
{sizeLabels[size]}
- + {tabOptions.map((option) => ( - + {option.label} - + ))} - - + +
))} @@ -103,18 +103,18 @@ export const Controlled: Story = { Active tab: {activeTab}
value && setActiveTab(value)}> - + {tabOptions.map((option) => ( - + {option.label} - + ))} - - + + {tabOptions.map((option) => ( - +
Content for {option.label}
-
+ ))}
@@ -127,23 +127,23 @@ export const DisabledTab: Story = { return (
- - Account - + + Account + Password - - Notifications - - - + + Notifications + + +
Account content
-
- + +
Password content (disabled)
-
- + +
Notifications content
-
+
); @@ -162,19 +162,19 @@ export const WithIcons: Story = { return (
- + {tabsWithIcons.map((tab) => ( - + {tab.label} - + ))} - - + + {tabsWithIcons.map((tab) => ( - +
Content for {tab.label}
-
+ ))}
@@ -194,18 +194,18 @@ export const IconsOnly: Story = { return (
- + {iconTabs.map((tab) => ( - + - + ))} - - + + {iconTabs.map((tab) => ( - +
Content for {tab.value}
-
+ ))}
@@ -245,9 +245,9 @@ export const DynamicTabs: Story = {
value && setActiveTab(value)}> - + {tabs.map((tab) => ( - + {tab.label} {tabs.length > 1 && (