VerticalNavigation
Use a vertical layout for global navigation on wide screens. treeview mode provides structured hierarchy but overrides standard keyboard navigation.
Use mode=“disclosure” for most apps. Avoid mode=“treeview” unless complex hierarchy and custom keyboard interaction are required.
Usage
The example below demonstrates a typical use of the VerticalNavigation component, combining VerticalNavigationTree to render the navigation structure and VerticalNavigationActions to display bottom-aligned actions.
Page content area
import { useState } from "react"; import { css } from "@emotion/css"; export default function Demo() { const [selected, setSelected] = useState("home"); const [collapsed, setCollapsed] = useState(false); return ( <div className="flex" style={{ height: "600px" }}> <HvVerticalNavigation open={!collapsed} onOpenChange={(isOpen) => setCollapsed(!isOpen)} selected={selected} onSelectedChange={setSelected} useIcons className="h-full" > <HvVerticalNavigationSection collapsible data={headerData} /> <HvVerticalNavigationTree search collapsible aria-label="Example 1 navigation" data={navigationData} /> <HvVerticalNavigationActions> <div className="relative"> {!collapsed && ( <Backwards className="absolute pointer-events-none top-0 right-0" /> )} <HvVerticalNavigationAction label={collapsed ? "Expand menu" : "Collapse menu"} icon={collapsed ? <Forwards /> : undefined} onClick={() => setCollapsed((prev) => !prev)} /> </div> </HvVerticalNavigationActions> </HvVerticalNavigation> <div className="flex flex-1 items-center justify-center border-1 border-dashed border-borderStrong ml-xs rounded-sm"> <HvTypography>Page content area</HvTypography> </div> </div> ); } const headerData = [ { id: "home", label: "Home", icon: <div className="i-ph-house" />, }, { id: "marketplace", label: "Data Marketplace", icon: <div className="i-ph-storefront" />, }, { id: "fav", label: "Favorites", icon: <div className="i-ph-star" />, data: [ { id: "fav-1", label: "Customers", icon: <div className="i-ph-table" />, }, { id: "fav-2", label: "Transformations", icon: <div className="i-ph-folder" />, }, { id: "fav-3", label: "sales_report.rep", icon: <div className="i-ph-file" />, }, { id: "fav-4", label: "Sales Analysis", icon: <div className="i-ph-package" />, }, { id: "fav-5", label: "clean_gdpr", icon: <div className="i-ph-file-csv" />, }, { id: "fav-6", label: "Report", icon: <div className="i-ph-file-pdf" />, }, { id: "fav-7", label: "User List", icon: <div className="i-ph-user-list" />, }, ], }, ]; const navigationData = [ { id: "menu1", label: "Explore", path: "", icon: <div className="i-ph-map-trifold" />, data: [ { id: "menu1-1", label: "Browse Files", path: "", icon: <div className="i-ph-folders" />, parent: null, data: [ { id: "menu1-1-1", label: "File 1", path: "", icon: <div className="i-ph-file" />, }, { id: "menu1-1-2", label: "File 2", path: "", icon: <div className="i-ph-file" />, }, { id: "menu1-1-3", label: "File 3", path: "", icon: <div className="i-ph-file" />, }, ], }, { id: "menu1-2", label: "Galaxy", path: "", icon: <div className="i-ph-graph" />, parent: null, }, { id: "menu1-3", label: "Lineage", path: "", icon: <div className="i-ph-tree-structure" />, parent: null, }, { id: "menu1-5", label: "Data Canvas", path: "", icon: <div className="i-ph-tree-view" />, parent: null, }, { id: "menu1-6", label: "API Catalog", path: "", icon: <div className="i-ph-webhooks-logo" />, parent: null, }, { id: "menu1-7", label: "Projects", path: "", icon: <div className="i-ph-suitcase-simple" />, parent: null, }, ], parent: null, }, { id: "menu2", label: "Transform", path: "", icon: <div className="i-ph-intersect-three" />, parent: null, }, { id: "menu3", label: "Management", path: "", icon: <div className="i-ph-gear" />, parent: null, data: [ { id: "menu3-1", label: "Connections", icon: <div className="i-ph-plugs" />, }, { id: "menu3-2", label: "Users", icon: <div className="i-ph-users" />, }, { id: "menu3-3", label: "Roles & Permissions", icon: <div className="i-ph-user-circle-gear" />, }, { id: "menu3-4", label: "Plugins", icon: <div className="i-ph-puzzle-piece" />, }, ], }, { id: "menu4", label: "Schedules", path: "", icon: <div className="i-ph-calendar" />, parent: null, }, { id: "menu5", label: "Monitoring", path: "", icon: <div className="i-ph-pulse" />, parent: null, data: [ { id: "menu5-1", label: "Processes", icon: <div className="i-ph-gear-fine" />, }, ], }, ];
Tree view
Use mode="treeview" to enable keyboard navigation with arrow keys. Press Enter to expand/collapse or select items. Set collapsible to true to allow collapsing non-leaf nodes.
import { useState } from "react"; export default function Demo() { const [value, setValue] = useState("01-01"); return ( <HvVerticalNavigation> <HvVerticalNavigationTree mode="treeview" collpasible defaultExpanded aria-label="Example 3 navigation" selected={value} onChange={(event, data) => setValue(data.id)} data={navigationData} /> <HvVerticalNavigationActions> <HvVerticalNavigationAction label="Profile" icon={<User />} /> <HvVerticalNavigationAction label="Logout" icon={<LogOut />} /> </HvVerticalNavigationActions> </HvVerticalNavigation> ); } const navigationData = [ { id: "00", label: "Installation Overview" }, { id: "01", label: "Hardware", data: [ { id: "01-01", label: "Ambient Monitoring", }, { id: "01-02", label: "Server Status Summary", }, ], }, { id: "02", label: "System", data: [ { id: "02-01", label: "Buckets", }, { id: "02-02", label: "Admin Users", }, { id: "02-03", label: "Log Bundle", data: [ { id: "02-03-01", label: "Rest API", }, { id: "02-03-02", label: "License", }, ], }, ], }, ];
Collapsible
To make the navigation collapsible, use HvVerticalNavigationHeader with a collapse button. Control the open state via the open prop and show the button by passing a handler to onCollapseButtonClick.
Enable useIcons to display icons when collapsed—defaults to the first letter of the label if no icon is provided.
import { useState } from "react"; export default function Demo() { const [value, setValue] = useState("01-01"); const [show, setShow] = useState(false); const [icons, setIcons] = useState(false); const handleIsExpanded = () => { setShow(!show); }; return ( <div className="flex gap-xs" style={{ height: 400 }}> <HvCheckBox label="Show Icons" checked={icons} onChange={() => setIcons(!icons)} /> <HvVerticalNavigation open={show} useIcons={icons}> <HvVerticalNavigationHeader title="Menu" onCollapseButtonClick={handleIsExpanded} collapseButtonProps={{ "aria-label": "collapseButton", "aria-expanded": show, }} /> <HvVerticalNavigationTree collapsible defaultExpanded aria-label="Example 3 navigation" selected={value} onChange={(event, data) => setValue(data.id)} data={navigationData} /> </HvVerticalNavigation> </div> ); } const navigationData = [ { id: "00", label: "Installation Overview", icon: <Open /> }, { id: "01", label: "Hardware", icon: <BarChart />, data: [ { id: "01-01", label: "Ambient Monitoring", icon: <BarChart /> }, { id: "01-02", label: "Server Status Summary" }, ], }, { id: "02", label: "System", icon: <Deploy />, data: [ { id: "02-01", label: "Buckets", icon: <Deploy /> }, { id: "02-02", label: "Admin Users" }, { id: "02-03", label: "Log Bundle", data: [ { id: "02-03-01", label: "Rest API" }, { id: "02-03-02", label: "License" }, ], }, ], }, { id: "03", label: "System 2", data: [ { id: "03-01", label: "Buckets" }, { id: "03-02", label: "Admin Users" }, { id: "03-03", label: "Log Bundle", data: [ { id: "03-03-01", label: "Rest API" }, { id: "03-03-02", label: "License" }, ], }, ], }, ];
Slider
If you set the slider prop to true, the navigation will be displayed as a slider instead of a tree. When the user selects an item that contains
children, the content of the navigation will be replaced with the children of the selected item.
You can use this functionality to display the navigation in regular tree view mode and switch to slider mode when the screen size is lower that a certain threshold.
import { useState } from "react"; export default function Demo() { const [value, setValue] = useState("menu1-3"); return ( <HvVerticalNavigation open slider> <HvVerticalNavigationHeader title="Menu" /> <HvVerticalNavigationTree collapsible defaultExpanded aria-label="Example 4 Slider Mode" selected={value} onChange={(event, data) => setValue(data.id)} data={navigationData} /> </HvVerticalNavigation> ); } const navigationData = [ { id: "menu1", label: "Menu 1", path: "", icon: <Open />, data: [ { id: "menu1-1", label: "Menu 1-1", path: "", icon: <Open />, parent: null, }, { id: "menu1-2", label: "Menu 1-2", path: "", icon: <BarChart />, data: [ { id: "menu1-2-1", label: "Menu 1-2-1", path: "", icon: <Open />, parent: null, }, { id: "menu1-2-2", label: "Menu 1-2-2", path: "", icon: <BarChart />, parent: null, }, { id: "menu1-2-3", label: "Menu 1-2-3", path: "", icon: <Deploy />, parent: null, }, ], parent: null, }, { id: "menu1-3", label: "Menu 1-3", path: "", icon: <Deploy />, parent: null, }, ], parent: null, }, { id: "menu2", label: "Menu 2 with a very big name that should be truncated", path: "", icon: <BarChart />, parent: null, }, { id: "menu3", label: "Menu 3", path: "", icon: <Deploy />, parent: null, }, ];
Custom content
import { useState } from "react"; export default function Demo() { const [collapsed, setCollapsed] = useState(false); return ( <HvVerticalNavigation open={!collapsed} useIcons> <div className="flex flex-col gap-md" style={{ alignItems: collapsed ? "center" : "stretch" }} > {collapsed ? ( <Favorite /> ) : ( <div className="flex items-center"> <Favorite /> <HvTypography variant="label">Custom App</HvTypography> </div> )} <CollapsibleButton collapsed={collapsed} variant="primary" icon={<Add />} label="Create" /> </div> <HvVerticalNavigationTree data={data} /> <HvVerticalNavigationActions> <div className="relative"> {!collapsed && ( <Backwards className="absolute pointer-events-none top-0 right-0" /> )} <HvVerticalNavigationAction label={collapsed ? "Expand menu" : "Collapse menu"} icon={collapsed ? <Forwards /> : undefined} onClick={() => setCollapsed((prev) => !prev)} /> </div> </HvVerticalNavigationActions> </HvVerticalNavigation> ); } const CollapsibleButton = ({ collapsed, label, icon, ...others }: CollapsibleButtonProps) => { const props = collapsed ? { "aria-label": String(label), children: icon, icon: true } : { startIcon: icon, children: label }; return <HvButton {...props} {...others} />; }; const data = [ { id: "00", label: "Jobs", icon: <Job /> }, { id: "01", label: "Charts", icon: <BarChart /> }, { id: "02", label: "Deployment", icon: <Deploy /> }, { id: "03", label: "Cloud", icon: <Cloud /> }, ];