@8x8/oxygen-sidebar-menu
v3.0.0
Published
Oxygen - Sidebar Menu
Keywords
Readme
8x8 Oxygen - Sidebar Menu
Installation
$ yarn add @8x8/oxygen-sidebar-menu$ npm install @8x8/oxygen-sidebar-menuThis component is marked as Alpha.
The following functionality is not yet implemented and will be required to finalize the component, also potential issues and items to look into:
- icon active state (green dot)
- CollapseItem separator rendering (check use-cases on whether this item can be the first)
Badge Accessibility Features
The sidebar menu includes comprehensive accessibility support for badges:
Accessibility Structure
- Badges are decorative: All badges are hidden from screen readers using
aria-hidden="true" - Button accessibility: Accessibility attributes are applied to the interactive button elements for proper semantic structure
- Contextual aria-labels: Menu buttons receive descriptive aria-labels that include badge information when present
Automatic Aria-Label Generation
Menu buttons automatically receive contextual aria-labels:
- Without badge:
"Menu item name" - With badge (default):
"Menu item name, requires attention" - With badge (custom):
"Menu item name, custom badge description"
Usage Examples
// Basic menu item without badge
<MenuItem label="Settings" />
// Button aria-label: "Settings"
// Menu item with badge (default message)
<MenuItem label="Messages" hasBadge badgeChildren={5} />
// Button aria-label: "Messages, requires attention"
// Menu item with custom badge description
<MenuItem
label="Messages"
hasBadge
badgeChildren={5}
badgeAriaLabel="5 unread messages"
/>
// Button aria-label: "Messages, 5 unread messages"Components for building sidebar from a configuration object:
SidebarPosition (type)
Position of the sidebar - it can be on the left or right side of the screen
BadgeProps (interface)
Public badge interface for menu items
Members:
- hasBadge (
boolean) - whether the menu item should display a badge - badgeChildren (
ReactNode) - the content that will be rendered inside the badge - badgeAriaLabel (
string) - custom aria-label for the badge (used in button's aria-label)
MenuItemProps (interface)
Properties for a SubItem
Members:
- id (
string) - stable identity of the item. UnderSidebarit is the React key, so an item keeps its own local state (e.g. whether its sub-menu is expanded) when items are added, removed or reordered — and it names the item in the DOM: with atestIdnamespace the<li>renders${testId}_ITEM_${id}and, in the collapsed sidebar, the item's floating-UI ids render${testId}_ITEM_${id}_FLOATING_UI[_TRIGGER]. Items without anidrender no per-item test attributes at all. Used verbatim — keep it unique among siblings and DOM-selector-safe. Not the HTMLidattribute; it never reaches the DOM as one - label (
string) - an internationalized string - isActive (
boolean) - true means SubItem is rendered as an active item - onTrigger (
(event: MouseEvent<HTMLElement, MouseEvent>) => void) - mouse click event and keyboard (space, enter) calls this callback - link (
string) - Path - position (
SidebarPosition) - linkComponent (
ComponentType<any>) - Custom link component - linkProp (
string) - Custom prop for the link path. Defaults to "to" for ReactRouter - testId (
string) - data-test-id namespace the item's rendered test ids sit under — not an id itself: an item with anidrenders${testId}_ITEM_${id}on its<li>. UnderSidebarevery main item receives the sidebar-level value, and every sub item receives its parent item's full test id, so sub-item ids nest:${sidebarTestId}_ITEM_${parentId}_ITEM_${subId}. Without a namespace (or without anid) no test attributes render - itemProps (
SidebarItemAttributes) -data-*/aria-*attributes applied to the item's own<li>, in both the collapsed and expanded sidebar. Generated test attributes always win on key collision - triggerProps (
SidebarItemAttributes) -data-*/aria-*attributes applied to the item's trigger (the<button>, or the elementlinkComponentrenders), in both modes. May override the generatedaria-label; never overridesonClick - hasBadge (
boolean) - true means badge is rendered - badgeChildren (
ReactNode) - the content that will be rendered inside the badge if is active (children will be rendered only sub-menu items) - badgeAriaLabel (
string) - custom aria-label for the badge (used in button's aria-label)
MenuProps (interface)
Members:
- as (
keyof IntrinsicElements) - icon (
ReactElement<any, string | JSXElementConstructor<any>>) - children (
ReactElement<MenuItemProps, string | JSXElementConstructor<any>> | ReactElement<MenuItemProps, string | JSXElementConstructor<...>>[]) - only children of type SubMenuItem are allowed
SidebarItemProps (interface)
Members:
- id (
string, inherited) - seeMenuItemProps. As the React key it falls back tolink, then tolabel; prefer setting it on any item withsubItems(an item identified only by itslabelis remounted, and so collapses, whenever that label changes, e.g. on a locale switch) and on any item automation needs to target (noid, no rendered test id). Development builds emit one consolidated warning naming items without anid, duplicated identities, and label-keyed expandables - icon (
ReactElement<any, string | JSXElementConstructor<any>>) - for a SubItem can be omitted - isFooter (
boolean) - true means item will appear below the collapse button - subItems (
SidebarItemProps[]) - if subItems are present, it becomes a Menu. Sub-item test ids nest under the parent item's full test id
SidebarProps (interface)
Properties of Sidebar component
Members:
- items (
SidebarItemProps[]) - all the items and subitems on the sidebar - initialCollapsedState (
boolean) - Initial value for collapsed state - collapseLabel (
string) - label for collapse button or null to omit collapse button - expandLabel (
string) - label for collapse button when the sidebar is collapsed (bothcollapseLabelandexpandLabelare needed for collapse button to be rendered) - position (
SidebarPosition) - position of the sidebar - onCollapseChange (
(collapsed: boolean) => void) - callback for collapse change - linkComponent (
ComponentType<any>) - Custom link Component. Used to render items instead of Button - linkProp (
string) - Custom prop for the link path. Defaults to "to" for ReactRouter - testId (
string) - data-test-id value
SidebarProviderProps (interface)
Members:
- children (
ReactNode)
SidebarContextType (interface)
Members:
- isSidebarCollapsed (
boolean) - setSidebarCollapsed (
Dispatch<SetStateAction<boolean>>)
Sidebar (function)
Renders a sidebar from a configuration object
Components for building sidebar declaratively:
SidebarPosition (type)
Position of the sidebar - it can be on the left or right side of the screen
BadgeProps (interface)
Public badge interface for menu items
Members:
- hasBadge (
boolean) - whether the menu item should display a badge - badgeChildren (
ReactNode) - the content that will be rendered inside the badge - badgeAriaLabel (
string) - custom aria-label for the badge (used in button's aria-label)
MenuItemProps (interface)
Properties for a SubItem
Members:
- id (
string) - stable identity of the item. UnderSidebarit is the React key, so an item keeps its own local state (e.g. whether its sub-menu is expanded) when items are added, removed or reordered — and it names the item in the DOM: with atestIdnamespace the<li>renders${testId}_ITEM_${id}and, in the collapsed sidebar, the item's floating-UI ids render${testId}_ITEM_${id}_FLOATING_UI[_TRIGGER]. Items without anidrender no per-item test attributes at all. Used verbatim — keep it unique among siblings and DOM-selector-safe. Not the HTMLidattribute; it never reaches the DOM as one - label (
string) - an internationalized string - isActive (
boolean) - true means SubItem is rendered as an active item - onTrigger (
(event: MouseEvent<HTMLElement, MouseEvent>) => void) - mouse click event and keyboard (space, enter) calls this callback - link (
string) - Path - position (
SidebarPosition) - linkComponent (
ComponentType<any>) - Custom link component - linkProp (
string) - Custom prop for the link path. Defaults to "to" for ReactRouter - testId (
string) - data-test-id namespace the item's rendered test ids sit under — not an id itself: an item with anidrenders${testId}_ITEM_${id}on its<li>. UnderSidebarevery main item receives the sidebar-level value, and every sub item receives its parent item's full test id, so sub-item ids nest:${sidebarTestId}_ITEM_${parentId}_ITEM_${subId}. Without a namespace (or without anid) no test attributes render - itemProps (
SidebarItemAttributes) -data-*/aria-*attributes applied to the item's own<li>, in both the collapsed and expanded sidebar. Generated test attributes always win on key collision - triggerProps (
SidebarItemAttributes) -data-*/aria-*attributes applied to the item's trigger (the<button>, or the elementlinkComponentrenders), in both modes. May override the generatedaria-label; never overridesonClick - hasBadge (
boolean) - true means badge is rendered - badgeChildren (
ReactNode) - the content that will be rendered inside the badge - badgeAriaLabel (
string) - custom aria-label for the badge (used in button's aria-label)
MenuProps (interface)
Members:
- as (
keyof IntrinsicElements) - icon (
ReactElement<any, string | JSXElementConstructor<any>>) - children (
ReactElement<MenuItemProps, string | JSXElementConstructor<any>> | ReactElement<MenuItemProps, string | JSXElementConstructor<...>>[]) - only children of type SubMenuItem are allowed
SidebarItemProps (interface)
Members:
- id (
string, inherited) - seeMenuItemProps. As the React key it falls back tolink, then tolabel; prefer setting it on any item withsubItems(an item identified only by itslabelis remounted, and so collapses, whenever that label changes, e.g. on a locale switch) and on any item automation needs to target (noid, no rendered test id). Development builds emit one consolidated warning naming items without anid, duplicated identities, and label-keyed expandables - icon (
ReactElement<any, string | JSXElementConstructor<any>>) - for a SubItem can be omitted - isFooter (
boolean) - true means item will appear below the collapse button - subItems (
SidebarItemProps[]) - if subItems are present, it becomes a Menu. Sub-item test ids nest under the parent item's full test id
SidebarProps (interface)
Properties of Sidebar component
Members:
- items (
SidebarItemProps[]) - all the items and subitems on the sidebar - initialCollapsedState (
boolean) - Initial value for collapsed state - collapseLabel (
string) - label for collapse button or null to omit collapse button - expandLabel (
string) - label for collapse button when the sidebar is collapsed (bothcollapseLabelandexpandLabelare needed for collapse button to be rendered) - position (
SidebarPosition) - position of the sidebar - onCollapseChange (
(collapsed: boolean) => void) - callback for collapse change - linkComponent (
ComponentType<any>) - Custom link Component. Used to render items instead of Button - linkProp (
string) - Custom prop for the link path. Defaults to "to" for ReactRouter - testId (
string) - data-test-id value
SidebarProviderProps (interface)
Members:
- children (
ReactNode)
SidebarContextType (interface)
Members:
- isSidebarCollapsed (
boolean) - setSidebarCollapsed (
Dispatch<SetStateAction<boolean>>)
MenuItem (function)
Renders a menu with submenus
scrollToRef (function)
getCustomButtonOverrideProps (function)
Parameters:
- arg0 (
boolean) - arg1 (
PropsWithAll)
returns: { as: ComponentType; linkProp: string; }
getCustomButtonOverrideProps (function)
Parameters:
- arg0 (
boolean) - arg1 (
PropsWithEither)
returns: { as: ComponentType; linkProp: string; }
getCustomButtonOverrideProps (function)
Parameters:
- customCheck (
boolean) - { linkComponent, link, linkProp } (
PropsWithEither)
returns: { as: ComponentType; linkProp: string; }
SubMenuItem (variable)
Renders a sub menu item
CollapseItem (function)
Renders the collapse item
SidebarContext (variable)
SidebarProvider (function)
Wrap everything in this provider when using declarative sidebar
