[]
@@ -41,6 +68,8 @@ export interface SideNavigationGroupProps {
export const SideNavigationGroup = ({ children, label = "", open = false }: SideNavigationGroupProps): ReactNode => {
const [isOpen, setIsOpen] = useState(open)
+ const level = useContext(LevelContext)
+ const levelClassName = `level-${level + 1}`
// Sync internal state with external prop changes
useEffect(() => {
@@ -52,26 +81,52 @@ export const SideNavigationGroup = ({ children, label = "", open = false }: Side
setIsOpen(!isOpen)
}
- const renderExpandButton = () =>
- children && Children.count(children) > 0 ? (
-
+
) : null
- const renderGroup = () => (
-
- {label}
- {renderExpandButton()}
-
+ const renderLabel = () => (
+
+ {label}
+
)
+ const renderGroup = () => {
+ const baseClassName = `juno-sidenavigation-group ${sideNavGroupStyles} ${isOpen ? "juno-sidenavigation-group-open" : ""}`
+
+ if (hasChildren) {
+ return (
+
+ )
+ }
+
+ return (
+
+ {renderLabel()}
+
+ )
+ }
+
return (
<>
{renderGroup()}
- {isOpen && children}
+ {isOpen && {children}}
>
)
}
diff --git a/packages/ui-components/src/components/SideNavigationGroup/SideNavigationGroup.test.tsx b/packages/ui-components/src/components/SideNavigationGroup/SideNavigationGroup.test.tsx
index d1b3323500..31345887e8 100644
--- a/packages/ui-components/src/components/SideNavigationGroup/SideNavigationGroup.test.tsx
+++ b/packages/ui-components/src/components/SideNavigationGroup/SideNavigationGroup.test.tsx
@@ -61,4 +61,73 @@ describe("SideNavigationGroup", () => {
expect(screen.queryByText("Child Item 1")).not.toBeInTheDocument()
expect(screen.queryByText("Child Item 2")).not.toBeInTheDocument()
})
+
+ test("renders the group as a button with aria-expanded when it has children", () => {
+ render(
+
+
+
+ )
+
+ const group = screen.getByRole("button", { name: /Group with children/ })
+ expect(group.tagName).toBe("BUTTON")
+ expect(group).toHaveAttribute("aria-expanded", "false")
+ })
+
+ test("renders the group as a non-button element when it has no children", () => {
+ render()
+
+ expect(screen.queryByRole("button")).not.toBeInTheDocument()
+ expect(screen.getByText("Childless Group")).toBeInTheDocument()
+ })
+
+ test("sets a title attribute on the group when label is a string", () => {
+ render(
+
+
+
+ )
+
+ const group = screen.getByRole("button")
+ expect(group).toHaveAttribute("title", "A very long group label that may overflow")
+ })
+
+ test("does not set a title attribute when label is a ReactNode", () => {
+ render(
+ Node label}>
+
+
+ )
+
+ const group = screen.getByRole("button")
+ expect(group).not.toHaveAttribute("title")
+ })
+
+ test("indents the group label based on its nesting level", () => {
+ render(
+
+
+
+
+
+
+
+ )
+
+ expect(screen.getByText("Top")).toHaveClass("level-1")
+ expect(screen.getByText("Middle")).toHaveClass("level-2")
+ expect(screen.getByText("Inner")).toHaveClass("level-3")
+ })
+
+ test("propagates its level so child SideNavigationItems indent correctly", () => {
+ render(
+
+
+
+
+
+ )
+
+ expect(screen.getByText("Leaf")).toHaveClass("level-3")
+ })
})
diff --git a/packages/ui-components/src/components/SideNavigationItem/SideNavigationItem.component.tsx b/packages/ui-components/src/components/SideNavigationItem/SideNavigationItem.component.tsx
index 9605c7d111..b80f50b3cb 100644
--- a/packages/ui-components/src/components/SideNavigationItem/SideNavigationItem.component.tsx
+++ b/packages/ui-components/src/components/SideNavigationItem/SideNavigationItem.component.tsx
@@ -7,7 +7,6 @@ import React, {
useState,
useEffect,
useContext,
- createContext,
ReactNode,
HTMLAttributes,
MouseEventHandler,
@@ -16,9 +15,8 @@ import React, {
Children,
} from "react"
import { Icon, KnownIcons } from "../Icon/Icon.component"
-import "./sidenavigationitem.css"
-
-const LevelContext = createContext(0)
+import { LevelContext } from "../SideNavigation/levelContext"
+import "../SideNavigation/sidenavigation.css"
const sideNavItemStyles = `
jn:flex
@@ -32,8 +30,9 @@ const sideNavItemStyles = `
const leftStyles = `
jn:flex
- jn:items-center
+ jn:items-start
jn:flex-grow
+ jn:min-w-0
`
const disabledStyles = `
@@ -112,6 +111,13 @@ export const SideNavigationItem = ({
}
}
+ const titleText: string | undefined =
+ typeof label === "string" && label.length > 0
+ ? label
+ : typeof children === "string" && children.length > 0
+ ? children
+ : undefined
+
const renderExpandButton = () =>
children && typeof children !== "string" && Children.count(children) ? (