diff --git a/docs/templates/Canvas.stories.tsx b/docs/templates/Canvas.stories.tsx index 9643801d47..768300c9bf 100644 --- a/docs/templates/Canvas.stories.tsx +++ b/docs/templates/Canvas.stories.tsx @@ -1,7 +1,7 @@ import { css } from "@emotion/css"; import { StoryObj } from "@storybook/react"; import { - canvasPanelClasses, + canvasSidePanelClasses, canvasToolbarClasses, } from "@hitachivantara/uikit-react-pentaho"; @@ -17,7 +17,10 @@ const classes = { root: css({ "& > div": { height: "calc(100vh - 40px)" }, [`& .${canvasToolbarClasses.root}`]: { top: 8 }, - [`& .${canvasPanelClasses.root}`]: { top: 8, height: "calc(100% - 8px)" }, + [`& .${canvasSidePanelClasses.root}`]: { + top: 8, + height: "calc(100% - 8px)", + }, }), }; diff --git a/packages/cli/src/templates/Canvas/Sidebar.tsx b/packages/cli/src/templates/Canvas/Sidebar.tsx index b2055d3b32..52a0d44dc7 100644 --- a/packages/cli/src/templates/Canvas/Sidebar.tsx +++ b/packages/cli/src/templates/Canvas/Sidebar.tsx @@ -8,14 +8,14 @@ import { import { restrictToWindowEdges } from "@dnd-kit/modifiers"; import { useTheme, useUniqueId } from "@hitachivantara/uikit-react-core"; import { - HvCanvasPanel, - HvCanvasPanelProps, + HvCanvasSidePanel, + HvCanvasSidePanelProps, } from "@hitachivantara/uikit-react-pentaho"; import { classes } from "./styles"; import { restrictToSample } from "./utils"; -export const CanvasSidebar = (props: HvCanvasPanelProps) => { +export const CanvasSidebar = (props: HvCanvasSidePanelProps) => { const { rootId } = useTheme(); const [overlay, setOverlay] = useState(); @@ -43,7 +43,7 @@ export const CanvasSidebar = (props: HvCanvasPanelProps) => { return ( <> - { const { selectedTable, openedTables, setOpenedTables, setSelectedTable } = useCanvasContext(); - const floatingTabs = useMemo( + const bottomTabs = useMemo( () => openedTables?.map((table) => ({ id: table.id, @@ -111,14 +111,14 @@ const Page = () => { } }; - const handleChangeTab: HvCanvasFloatingPanelProps["onTabChange"] = ( + const handleChangeTab: HvCanvasBottomPanelProps["onTabChange"] = ( event, value, ) => { setSelectedTable?.(value as string); }; - const handleAction: HvCanvasFloatingPanelProps["onAction"] = ( + const handleAction: HvCanvasBottomPanelProps["onAction"] = ( event, action, tabId, @@ -170,13 +170,13 @@ const Page = () => { ); }; - const floatingPanelOpen = useMemo( + const bottomPanelOpen = useMemo( () => !!openedTables && openedTables.length > 0 && - floatingTabs && - floatingTabs.length > 0, - [floatingTabs, openedTables], + bottomTabs && + bottomTabs.length > 0, + [bottomTabs, openedTables], ); return ( @@ -188,7 +188,7 @@ const Page = () => { nodeTypes={nodeTypes} edgeTypes={edgeTypes} onInit={setFlowInstance} - /** Flow sidebar passed as prop to access the flow's Dnd context inside CanvasPanel */ + /** Flow sidebar passed as prop to access the flow's Dnd context inside CanvasSidePanel */ sidebar={ { Execute - {floatingTabs && floatingPanelOpen && ( - { onAction={handleAction} > - + )} - {floatingPanelOpen && ( + {bottomPanelOpen && ( { onClose={() => setFullscreen((prev) => !prev)} > - {floatingTabs?.find((x) => x.id === selectedTable)?.title} + {bottomTabs?.find((x) => x.id === selectedTable)?.title} diff --git a/packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.stories.tsx b/packages/pentaho/src/Canvas/BottomPanel/BottomPanel.stories.tsx similarity index 72% rename from packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.stories.tsx rename to packages/pentaho/src/Canvas/BottomPanel/BottomPanel.stories.tsx index ece0bb8731..63f958142e 100644 --- a/packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.stories.tsx +++ b/packages/pentaho/src/Canvas/BottomPanel/BottomPanel.stories.tsx @@ -1,19 +1,19 @@ import { Meta, StoryObj } from "@storybook/react"; import { - HvCanvasFloatingPanel, - HvCanvasFloatingPanelProps, + HvCanvasBottomPanel, + HvCanvasBottomPanelProps, } from "@hitachivantara/uikit-react-pentaho"; import { MainStory } from "./stories/Main"; import MainRaw from "./stories/Main?raw"; -const meta: Meta = { - title: "Pentaho/Canvas/Floating Panel", - component: HvCanvasFloatingPanel, +const meta: Meta = { + title: "Pentaho/Canvas/Bottom Panel", + component: HvCanvasBottomPanel, }; export default meta; -export const Main: StoryObj = { +export const Main: StoryObj = { args: { open: true }, argTypes: { tabs: { control: { disable: true } }, diff --git a/packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.styles.tsx b/packages/pentaho/src/Canvas/BottomPanel/BottomPanel.styles.tsx similarity index 98% rename from packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.styles.tsx rename to packages/pentaho/src/Canvas/BottomPanel/BottomPanel.styles.tsx index 08a28614c3..f86a0b346c 100644 --- a/packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.styles.tsx +++ b/packages/pentaho/src/Canvas/BottomPanel/BottomPanel.styles.tsx @@ -1,7 +1,7 @@ import { createClasses, theme } from "@hitachivantara/uikit-react-core"; export const { staticClasses, useClasses } = createClasses( - "HvCanvasFloatingPanel", + "HvCanvasBottomPanel", { root: { position: "absolute", diff --git a/packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.test.tsx b/packages/pentaho/src/Canvas/BottomPanel/BottomPanel.test.tsx similarity index 90% rename from packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.test.tsx rename to packages/pentaho/src/Canvas/BottomPanel/BottomPanel.test.tsx index 2be36cf71a..5cfbd91618 100644 --- a/packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.test.tsx +++ b/packages/pentaho/src/Canvas/BottomPanel/BottomPanel.test.tsx @@ -5,10 +5,7 @@ import { describe, it, vi } from "vitest"; import { HvButton } from "@hitachivantara/uikit-react-core"; import { Close, DropUpXS } from "@hitachivantara/uikit-react-icons"; -import { - HvCanvasFloatingPanel, - HvCanvasFloatingPanelProps, -} from "./FloatingPanel"; +import { HvCanvasBottomPanel, HvCanvasBottomPanelProps } from "./BottomPanel"; const panelTabs = [ { @@ -21,11 +18,11 @@ const panelTabs = [ }, ]; -const renderSimplePanel = (props?: Partial) => +const renderSimplePanel = (props?: Partial) => render( - + Content - , + , ); const ControlledOpen = () => { @@ -33,17 +30,17 @@ const ControlledOpen = () => { return ( <> setOpen((prev) => !prev)}>Toggle - + Content - + ); }; -const ControlledTab = (props?: Partial) => { +const ControlledTab = (props?: Partial) => { const [tab, setTab] = useState(panelTabs[1].id); return ( - ) => { }} > Content - + ); }; -const ControlledMinimize = (props?: Partial) => { +const ControlledMinimize = (props?: Partial) => { const [minimize, setMinimize] = useState(false); return ( <> setMinimize((prev) => !prev)}>Toggle - + Content - + ); }; @@ -91,7 +88,7 @@ const expectPanelClosed = () => { expect(tabPanel).toBeNull(); }; -describe("CanvasFloatingPanel", () => { +describe("CanvasBottomPanel", () => { it("renders all components when opened", () => { renderSimplePanel({ open: true, diff --git a/packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.tsx b/packages/pentaho/src/Canvas/BottomPanel/BottomPanel.tsx similarity index 91% rename from packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.tsx rename to packages/pentaho/src/Canvas/BottomPanel/BottomPanel.tsx index 07927b892c..1debdbdd18 100644 --- a/packages/pentaho/src/Canvas/FloatingPanel/FloatingPanel.tsx +++ b/packages/pentaho/src/Canvas/BottomPanel/BottomPanel.tsx @@ -14,16 +14,16 @@ import { import { HvCanvasTab } from "../Tab"; import { HvCanvasTabs, HvCanvasTabsProps } from "../Tabs"; -import { staticClasses, useClasses } from "./FloatingPanel.styles"; +import { staticClasses, useClasses } from "./BottomPanel.styles"; -export { staticClasses as floatingPanelClasses }; +export { staticClasses as canvasBottomPanelClasses }; -export type HvCanvasFloatingPanelClasses = ExtractNames; +export type HvCanvasBottomPanelClasses = ExtractNames; -export interface HvCanvasFloatingPanelProps extends HvBaseProps { - /** Open state of the floating panel. */ +export interface HvCanvasBottomPanelProps extends HvBaseProps { + /** Open state of the bottom panel. */ open?: boolean; - /** Minimize state of the floating panel tabs'. */ + /** Minimize state of the bottom panel tabs'. */ minimize?: boolean; /** List of tabs visible on the panel. */ tabs: { @@ -48,15 +48,15 @@ export interface HvCanvasFloatingPanelProps extends HvBaseProps { tabId: string | number, ) => void; /** A Jss Object used to override or extend the styles applied. */ - classes?: HvCanvasFloatingPanelClasses; + classes?: HvCanvasBottomPanelClasses; } /** - * A floating panel component to use in a canvas context. + * A bottom panel component to use in a canvas context. */ -export const HvCanvasFloatingPanel = forwardRef< +export const HvCanvasBottomPanel = forwardRef< HTMLDivElement, - HvCanvasFloatingPanelProps + HvCanvasBottomPanelProps >((props, ref) => { const { id: idProp, @@ -72,7 +72,7 @@ export const HvCanvasFloatingPanel = forwardRef< onTabChange, onAction, ...others - } = useDefaultProps("HvCanvasFloatingPanel", props); + } = useDefaultProps("HvCanvasBottomPanel", props); const { classes, cx } = useClasses(classesProp); diff --git a/packages/pentaho/src/Canvas/BottomPanel/index.ts b/packages/pentaho/src/Canvas/BottomPanel/index.ts new file mode 100644 index 0000000000..86f8e2f3ae --- /dev/null +++ b/packages/pentaho/src/Canvas/BottomPanel/index.ts @@ -0,0 +1 @@ +export * from "./BottomPanel"; diff --git a/packages/pentaho/src/Canvas/FloatingPanel/stories/Main.tsx b/packages/pentaho/src/Canvas/BottomPanel/stories/Main.tsx similarity index 56% rename from packages/pentaho/src/Canvas/FloatingPanel/stories/Main.tsx rename to packages/pentaho/src/Canvas/BottomPanel/stories/Main.tsx index 0c379a8a30..fa1ad912af 100644 --- a/packages/pentaho/src/Canvas/FloatingPanel/stories/Main.tsx +++ b/packages/pentaho/src/Canvas/BottomPanel/stories/Main.tsx @@ -1,7 +1,7 @@ import { css } from "@emotion/css"; import { - HvCanvasFloatingPanel, - HvCanvasFloatingPanelProps, + HvCanvasBottomPanel, + HvCanvasBottomPanelProps, } from "@hitachivantara/uikit-react-pentaho"; const tabs = [ @@ -17,8 +17,8 @@ const tabs = [ const classes = { root: css({ position: "relative" }) }; // for Storybook purposes -export const MainStory = (props: HvCanvasFloatingPanelProps) => ( - +export const MainStory = (props: HvCanvasBottomPanelProps) => ( + Content - + ); diff --git a/packages/pentaho/src/Canvas/Canvas.mdx b/packages/pentaho/src/Canvas/Canvas.mdx index 0d112f842d..3d55b06b4d 100644 --- a/packages/pentaho/src/Canvas/Canvas.mdx +++ b/packages/pentaho/src/Canvas/Canvas.mdx @@ -6,9 +6,8 @@ import { Meta } from "@storybook/addon-docs"; This section showcases all the Pentaho+ canvas components. At the moment, the following components are available: -- [Floating Panel](./?path=/docs/pentaho-canvas-floating-panel--docs) -- [Panel](./?path=/docs/pentaho-canvas-panel--docs) -- [Tabs and Tab](./?path=/docs/pentaho-canvas-tabs--docs) +- [Bottom Panel](./?path=/docs/pentaho-canvas-bottom-panel--docs) +- [Side Panel](./?path=/docs/pentaho-canvas-side-panel--docs) - [Toolbar](./?path=/docs/pentaho-canvas-toolbar--docs) As a disclaimer, it's important to note that all canvas components are a work in progress and there might be breaking changes. diff --git a/packages/pentaho/src/Canvas/FloatingPanel/index.ts b/packages/pentaho/src/Canvas/FloatingPanel/index.ts deleted file mode 100644 index edc690d318..0000000000 --- a/packages/pentaho/src/Canvas/FloatingPanel/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./FloatingPanel"; diff --git a/packages/pentaho/src/Canvas/Panel/Panel.styles.tsx b/packages/pentaho/src/Canvas/Panel/Panel.styles.tsx deleted file mode 100644 index cfb6089500..0000000000 --- a/packages/pentaho/src/Canvas/Panel/Panel.styles.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { - createClasses, - outlineStyles, - theme, -} from "@hitachivantara/uikit-react-core"; - -export const { staticClasses, useClasses } = createClasses("HvCanvasPanel", { - root: { - height: "100%", - position: "absolute", - top: 0, - left: 0, - boxShadow: "4px 0px 8px -4px color-mix(in srgb, #414141 12%, transparent)", - backgroundColor: "transparent", - transition: "visibility 0.3s ease, width 0.3s ease", - overflow: "hidden", - "&$open": { - width: 320, - visibility: "visible", - }, - "&$close": { - width: 0, - visibility: "hidden", - }, - }, - tabs: {}, - content: { - height: "100%", - }, - handle: { - height: "172px", - width: "35px", - display: "flex", - justifyContent: "center", - boxShadow: "4px 0px 8px -4px color-mix(in srgb, #414141 12%, transparent)", - backgroundColor: theme.colors.atmo1, - borderRadius: "0px 16px 16px 0px", - position: "absolute", - transition: "left 0.3s ease", - top: "calc(50% - 86px)", - "&$handleOpen": { - left: 320, - }, - "&$handleClose": { - left: 0, - }, - "&:hover": { - cursor: "pointer", - }, - "&:focus-visible": { - ...outlineStyles, - }, - }, - handleButton: { - top: "calc(50% - 16px)", - position: "absolute", - }, - open: {}, - close: {}, - handleOpen: {}, - handleClose: {}, -}); diff --git a/packages/pentaho/src/Canvas/Panel/Panel.tsx b/packages/pentaho/src/Canvas/Panel/Panel.tsx deleted file mode 100644 index 4627d2806c..0000000000 --- a/packages/pentaho/src/Canvas/Panel/Panel.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import { forwardRef } from "react"; -import { - ExtractNames, - HvBaseProps, - HvPanel, - useControlled, - useDefaultProps, - useLabels, - useUniqueId, -} from "@hitachivantara/uikit-react-core"; -import { End, Start } from "@hitachivantara/uikit-react-icons"; - -import { HvCanvasTab } from "../Tab"; -import { HvCanvasTabs, HvCanvasTabsProps } from "../Tabs"; -import { staticClasses, useClasses } from "./Panel.styles"; - -export { staticClasses as canvasPanelClasses }; - -export type HvCanvasPanelClasses = ExtractNames; - -const DEFAULT_LABELS = { - open: "Open", - close: "Close", -}; - -export interface HvCanvasPanelProps extends HvBaseProps { - /** When controlled, defines id the panel is open or not. */ - open?: boolean; - /** When uncontrolled, defines the initial state of the panel. */ - defaultOpen?: boolean; - /** List of tabs visible on the panel. */ - tabs?: { - id: string | number; - content: React.ReactNode; - }[]; - /** Id of the selected tab if it needs to be controlled. */ - tab?: string | number; - /** Callback triggered whenever the panel toggles. */ - onToggle?: ( - event: React.MouseEvent | React.KeyboardEvent, - open: boolean, - ) => void; - /** Callback triggered when a tab changes/is clicked. */ - onTabChange?: ( - event: React.SyntheticEvent | null, - tabId: string | number | null, - ) => void; - /** An object containing all the labels. */ - labels?: Partial; - /** The content that will be rendered within the canvas panel. */ - children?: React.ReactNode; - /** A Jss Object used to override or extend the styles applied. */ - classes?: HvCanvasPanelClasses; -} - -/** - * A panel component to use in a canvas context. - */ -export const HvCanvasPanel = forwardRef( - (props, ref) => { - const { - id: idProp, - tab: tabProp, - open: openProp, - defaultOpen = false, - tabs, - onToggle, - onTabChange, - labels: labelsProp, - className, - children, - classes: classesProp, - ...others - } = useDefaultProps("HvCanvasPanel", props); - - const id = useUniqueId(idProp); - - const { classes, cx } = useClasses(classesProp); - - const labels = useLabels(DEFAULT_LABELS, labelsProp); - - const [open, setOpen] = useControlled(openProp, Boolean(defaultOpen)); - const [selectedTab, setSelectedTab] = useControlled( - tabProp, - tabs?.[0]?.id ?? "none", - ); - - const handleTogglePanel = ( - event: React.MouseEvent | React.KeyboardEvent, - ) => { - setOpen((prev) => !prev); - onToggle?.(event, !open); - }; - - const handleTabChange: HvCanvasTabsProps["onChange"] = (event, tabId) => { - setSelectedTab(tabId); - onTabChange?.(event, tabId); - }; - - return ( - <> -
- {tabs && ( - - {tabs.map((tab) => ( - - {tab.content} - - ))} - - )} - - {children} - -
-
{ - if (e.key === "Enter" || e.key === " ") { - handleTogglePanel(e); - } - }} - aria-label={open ? labels.close : labels.open} - > -
- {open ? : } -
-
- - ); - }, -); diff --git a/packages/pentaho/src/Canvas/Panel/index.tsx b/packages/pentaho/src/Canvas/Panel/index.tsx deleted file mode 100644 index c9401816c3..0000000000 --- a/packages/pentaho/src/Canvas/Panel/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from "./Panel"; diff --git a/packages/pentaho/src/Canvas/Panel/Panel.stories.tsx b/packages/pentaho/src/Canvas/SidePanel/SidePanel.stories.tsx similarity index 69% rename from packages/pentaho/src/Canvas/Panel/Panel.stories.tsx rename to packages/pentaho/src/Canvas/SidePanel/SidePanel.stories.tsx index db9a6d9665..16188af46d 100644 --- a/packages/pentaho/src/Canvas/Panel/Panel.stories.tsx +++ b/packages/pentaho/src/Canvas/SidePanel/SidePanel.stories.tsx @@ -1,17 +1,17 @@ import { Meta, StoryObj } from "@storybook/react"; import { - HvCanvasPanel, - HvCanvasPanelProps, + HvCanvasSidePanel, + HvCanvasSidePanelProps, } from "@hitachivantara/uikit-react-pentaho"; import { theme } from "@hitachivantara/uikit-styles"; -const meta: Meta = { - title: "Pentaho/Canvas/Panel", - component: HvCanvasPanel, +const meta: Meta = { + title: "Pentaho/Canvas/Side Panel", + component: HvCanvasSidePanel, }; export default meta; -export const Main: StoryObj = { +export const Main: StoryObj = { args: { defaultOpen: true }, argTypes: { classes: { control: { disable: true } }, @@ -35,5 +35,7 @@ export const Main: StoryObj = { ), ], - render: (args) => Some content, + render: (args) => ( + Some content + ), }; diff --git a/packages/pentaho/src/Canvas/SidePanel/SidePanel.styles.tsx b/packages/pentaho/src/Canvas/SidePanel/SidePanel.styles.tsx new file mode 100644 index 0000000000..8ab929189c --- /dev/null +++ b/packages/pentaho/src/Canvas/SidePanel/SidePanel.styles.tsx @@ -0,0 +1,67 @@ +import { + createClasses, + outlineStyles, + theme, +} from "@hitachivantara/uikit-react-core"; + +export const { staticClasses, useClasses } = createClasses( + "HvCanvasSidePanel", + { + root: { + height: "100%", + position: "absolute", + top: 0, + left: 0, + boxShadow: + "4px 0px 8px -4px color-mix(in srgb, #414141 12%, transparent)", + backgroundColor: "transparent", + transition: "visibility 0.3s ease, width 0.3s ease", + overflow: "hidden", + "&$open": { + width: 320, + visibility: "visible", + }, + "&$close": { + width: 0, + visibility: "hidden", + }, + }, + tabs: {}, + content: { + height: "100%", + }, + handle: { + height: "172px", + width: "35px", + display: "flex", + justifyContent: "center", + boxShadow: + "4px 0px 8px -4px color-mix(in srgb, #414141 12%, transparent)", + backgroundColor: theme.colors.atmo1, + borderRadius: "0px 16px 16px 0px", + position: "absolute", + transition: "left 0.3s ease", + top: "calc(50% - 86px)", + "&$handleOpen": { + left: 320, + }, + "&$handleClose": { + left: 0, + }, + "&:hover": { + cursor: "pointer", + }, + "&:focus-visible": { + ...outlineStyles, + }, + }, + handleButton: { + top: "calc(50% - 16px)", + position: "absolute", + }, + open: {}, + close: {}, + handleOpen: {}, + handleClose: {}, + }, +); diff --git a/packages/pentaho/src/Canvas/Panel/Panel.test.tsx b/packages/pentaho/src/Canvas/SidePanel/SidePanel.test.tsx similarity index 93% rename from packages/pentaho/src/Canvas/Panel/Panel.test.tsx rename to packages/pentaho/src/Canvas/SidePanel/SidePanel.test.tsx index db29d0aa6c..0a63c560d9 100644 --- a/packages/pentaho/src/Canvas/Panel/Panel.test.tsx +++ b/packages/pentaho/src/Canvas/SidePanel/SidePanel.test.tsx @@ -4,7 +4,7 @@ import userEvent from "@testing-library/user-event"; import { describe, expect, it, vi } from "vitest"; import { HvButton } from "@hitachivantara/uikit-react-core"; -import { HvCanvasPanel, HvCanvasPanelProps } from "./Panel"; +import { HvCanvasSidePanel, HvCanvasSidePanelProps } from "./SidePanel"; const label = "Test"; @@ -19,20 +19,20 @@ const tabs = [ }, ]; -const renderSimplePanel = (props?: HvCanvasPanelProps) => +const renderSimplePanel = (props?: HvCanvasSidePanelProps) => render( - + {label} - , + , ); const ControlledPanel = ({ onToggle, ...others -}: Partial) => { +}: Partial) => { const [opened, setOpened] = useState(false); return ( - { onToggle?.(e, v); @@ -42,17 +42,17 @@ const ControlledPanel = ({ {...others} > {label} - + ); }; const ControlledTabs = ({ onTabChange, ...others -}: Partial) => { +}: Partial) => { const [tab, setTab] = useState(tabs[1].id); return ( - { onTabChange?.(e, v); @@ -63,7 +63,7 @@ const ControlledTabs = ({ {...others} > {label} - + ); }; @@ -91,7 +91,7 @@ const expectSimplePanelOpened = () => { expect(closeBtn).toBeInTheDocument(); }; -describe("CanvasPanel", () => { +describe("CanvasSidePanel", () => { it("does not show tabs when not provided", () => { renderSimplePanel({ tabs: [] }); const tabList = screen.queryByRole("tablist"); diff --git a/packages/pentaho/src/Canvas/SidePanel/SidePanel.tsx b/packages/pentaho/src/Canvas/SidePanel/SidePanel.tsx new file mode 100644 index 0000000000..1f3df00f5d --- /dev/null +++ b/packages/pentaho/src/Canvas/SidePanel/SidePanel.tsx @@ -0,0 +1,158 @@ +import { forwardRef } from "react"; +import { + ExtractNames, + HvBaseProps, + HvPanel, + useControlled, + useDefaultProps, + useLabels, + useUniqueId, +} from "@hitachivantara/uikit-react-core"; +import { End, Start } from "@hitachivantara/uikit-react-icons"; + +import { HvCanvasTab } from "../Tab"; +import { HvCanvasTabs, HvCanvasTabsProps } from "../Tabs"; +import { staticClasses, useClasses } from "./SidePanel.styles"; + +export { staticClasses as canvasSidePanelClasses }; + +export type HvCanvasSidePanelClasses = ExtractNames; + +const DEFAULT_LABELS = { + open: "Open", + close: "Close", +}; + +export interface HvCanvasSidePanelProps extends HvBaseProps { + /** When controlled, defines id the panel is open or not. */ + open?: boolean; + /** When uncontrolled, defines the initial state of the panel. */ + defaultOpen?: boolean; + /** List of tabs visible on the panel. */ + tabs?: { + id: string | number; + content: React.ReactNode; + }[]; + /** Id of the selected tab if it needs to be controlled. */ + tab?: string | number; + /** Callback triggered whenever the panel toggles. */ + onToggle?: ( + event: React.MouseEvent | React.KeyboardEvent, + open: boolean, + ) => void; + /** Callback triggered when a tab changes/is clicked. */ + onTabChange?: ( + event: React.SyntheticEvent | null, + tabId: string | number | null, + ) => void; + /** An object containing all the labels. */ + labels?: Partial; + /** The content that will be rendered within the canvas panel. */ + children?: React.ReactNode; + /** A Jss Object used to override or extend the styles applied. */ + classes?: HvCanvasSidePanelClasses; +} + +/** + * A side panel component to use in a canvas context. + */ +export const HvCanvasSidePanel = forwardRef< + HTMLDivElement, + HvCanvasSidePanelProps +>((props, ref) => { + const { + id: idProp, + tab: tabProp, + open: openProp, + defaultOpen = false, + tabs, + onToggle, + onTabChange, + labels: labelsProp, + className, + children, + classes: classesProp, + ...others + } = useDefaultProps("HvCanvasSidePanel", props); + + const id = useUniqueId(idProp); + + const { classes, cx } = useClasses(classesProp); + + const labels = useLabels(DEFAULT_LABELS, labelsProp); + + const [open, setOpen] = useControlled(openProp, Boolean(defaultOpen)); + const [selectedTab, setSelectedTab] = useControlled( + tabProp, + tabs?.[0]?.id ?? "none", + ); + + const handleTogglePanel = (event: React.MouseEvent | React.KeyboardEvent) => { + setOpen((prev) => !prev); + onToggle?.(event, !open); + }; + + const handleTabChange: HvCanvasTabsProps["onChange"] = (event, tabId) => { + setSelectedTab(tabId); + onTabChange?.(event, tabId); + }; + + return ( + <> +
+ {tabs && ( + + {tabs.map((tab) => ( + + {tab.content} + + ))} + + )} + + {children} + +
+
{ + if (e.key === "Enter" || e.key === " ") { + handleTogglePanel(e); + } + }} + aria-label={open ? labels.close : labels.open} + > +
+ {open ? : } +
+
+ + ); +}); diff --git a/packages/pentaho/src/Canvas/SidePanel/index.tsx b/packages/pentaho/src/Canvas/SidePanel/index.tsx new file mode 100644 index 0000000000..01efecde3f --- /dev/null +++ b/packages/pentaho/src/Canvas/SidePanel/index.tsx @@ -0,0 +1 @@ +export * from "./SidePanel"; diff --git a/packages/pentaho/src/Canvas/Tabs/Tabs.stories.tsx b/packages/pentaho/src/Canvas/Tabs/Tabs.stories.tsx deleted file mode 100644 index 57ece0d99c..0000000000 --- a/packages/pentaho/src/Canvas/Tabs/Tabs.stories.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Meta, StoryObj } from "@storybook/react"; -import { Alert, Debug, Report } from "@hitachivantara/uikit-react-icons"; -import { - HvCanvasTab, - HvCanvasTabs, - HvCanvasTabsProps, -} from "@hitachivantara/uikit-react-pentaho"; - -const meta: Meta = { - title: "Pentaho/Canvas/Tabs", - component: HvCanvasTabs, - // @ts-expect-error https://github.com/storybookjs/storybook/issues/20782 - subcomponents: { HvCanvasTab }, -}; -export default meta; - -export const Main: StoryObj = { - args: { defaultValue: 0 }, - argTypes: { - classes: { control: { disable: true } }, - ref: { control: { disable: true } }, - }, - render: (args) => { - return ( - - - - Tab 1 - - - - Tab 2 - - - - Tab 3 - - - ); - }, -}; diff --git a/packages/pentaho/src/Canvas/index.ts b/packages/pentaho/src/Canvas/index.ts index a898ab5acb..5e4f2d7619 100644 --- a/packages/pentaho/src/Canvas/index.ts +++ b/packages/pentaho/src/Canvas/index.ts @@ -1,5 +1,5 @@ export * from "./Toolbar"; -export * from "./Panel"; +export * from "./SidePanel"; export * from "./Tabs"; -export * from "./FloatingPanel"; +export * from "./BottomPanel"; export * from "./Tab";