diff --git a/packages/core/src/lib/components/toggle.tsx b/packages/core/src/lib/components/toggle.tsx index 78d4c2e..51e5103 100644 --- a/packages/core/src/lib/components/toggle.tsx +++ b/packages/core/src/lib/components/toggle.tsx @@ -7,16 +7,41 @@ import RichText from "./internal/rich-text"; type ToggleProps = { children?: React.ReactNode; + isOpen?: boolean; + onChangeOpen?: (open: boolean) => void; } & ToggleArgs; -const Toggle: React.FC = ({ children, ...props }) => { +const Toggle: React.FC & { Icon: typeof ToggleIcon } = ({ + children, + onChangeOpen, + ...props +}) => { const { toggle: { color, rich_text: texts }, } = props; const [open, setOpen] = useState(false); - const toggleOpen = useCallback(() => setOpen((prevOpen) => !prevOpen), []); + let iconElement: React.ReactNode = ; + const otherChildren: React.ReactNode[] = []; + + React.Children.forEach(children, (child) => { + if (React.isValidElement(child) && child.type === Toggle.Icon) { + iconElement = child.props.children; + } else { + otherChildren.push(child); + } + }); + + const toggleOpen = useCallback(() => { + setOpen((prevOpen) => { + if (onChangeOpen) { + onChangeOpen(!prevOpen); + } + + return !prevOpen; + }); + }, [setOpen, onChangeOpen]); return (
= ({ children, ...props }) => { aria-expanded={open} >
-

- {children} + {otherChildren}
); }; +type DefaultToggleIconProps = { + open: boolean; +}; + +const DefaultToggleIcon = ({ open }: DefaultToggleIconProps) => { + return ( +
+
+
+ ); +}; + +const ToggleIcon: React.FC<{ children?: React.ReactNode }> = ({ children }) => ( + <>{children} +); + +Toggle.Icon = ToggleIcon; + export default Toggle; diff --git a/packages/core/src/lib/types.ts b/packages/core/src/lib/types.ts index 00a3a7f..7491ca0 100644 --- a/packages/core/src/lib/types.ts +++ b/packages/core/src/lib/types.ts @@ -101,7 +101,6 @@ export type TodoArgs = { checked: boolean; rich_text: TextArgs[]; }; - customElement?: React.ReactNode; } & ContextedBlock; export type ToggleArgs = { @@ -110,7 +109,6 @@ export type ToggleArgs = { color: string; rich_text: TextArgs[]; }; - customElement?: React.ReactNode; } & ContextedBlock; export type QuoteArgs = { diff --git a/packages/story/src/stories/todo/todo.stories.tsx b/packages/story/src/stories/todo/todo.stories.tsx index 56531fb..e7ae040 100644 --- a/packages/story/src/stories/todo/todo.stories.tsx +++ b/packages/story/src/stories/todo/todo.stories.tsx @@ -1,7 +1,8 @@ import type { Meta, StoryObj } from "@storybook/react"; import Component from "../../lib/Notion"; import json from "./todo.json"; -import { Todo, TodoArgs } from "@notionpresso/react"; +import { Todo } from "@notionpresso/react"; +import { TodoArgs } from "@notionpresso/react"; const blocks = json.blocks as any; diff --git a/packages/story/src/stories/toggle/toggle.stories.tsx b/packages/story/src/stories/toggle/toggle.stories.tsx index 6eaf426..822b41b 100644 --- a/packages/story/src/stories/toggle/toggle.stories.tsx +++ b/packages/story/src/stories/toggle/toggle.stories.tsx @@ -2,6 +2,10 @@ import type { Meta, StoryObj } from "@storybook/react"; import Component from "../../lib/Notion"; import json from "./toggle.json"; +import { Toggle } from "@notionpresso/react"; +import type { ToggleArgs } from "@notionpresso/react"; +import { useState } from "react"; + const blocks = json.blocks as any; const meta: Meta = { @@ -12,9 +16,60 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Toggle: Story = { +export const ToggleStory: Story = { + name: "Toggle", args: { title: "Toggle", blocks: blocks, }, }; + +type ToggleProps = ToggleArgs & { + children?: React.ReactNode; +}; + +const CustomToggle = ({ children, ...props }: ToggleProps) => { + const [isOpen, setIsOpen] = useState(false); + + const handleChangeOpen = (open: boolean) => { + setIsOpen(open); + }; + + return ( + + + {isOpen ? ( +
+ ) : ( +
+ )} + + {children} + + ); +}; + +export const CustomToggleStory: Story = { + name: "Custom Toggle", + args: { + title: "Custom Toggle", + blocks: blocks, + custom: { + toggle: CustomToggle, + }, + }, +};