Skip to content

Commit

Permalink
NavList add defaultOpen to NavList.Item (#3698)
Browse files Browse the repository at this point in the history
* adding defaultOpen to NavList

* add console.error if using defaultOpen on a NavList.Item without a NavList.SubNav

* update defaultOpen

* add changeset

* fix lint errors
  • Loading branch information
gracepark authored Sep 6, 2023
1 parent 6754627 commit d759fd3
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 6 deletions.
7 changes: 7 additions & 0 deletions .changeset/fifty-seas-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@primer/react': patch
---

Adds the defaultOpen prop to NavList.Item

<!-- Changed components: _none_ -->
5 changes: 5 additions & 0 deletions src/NavList/NavList.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
"defaultValue": "false",
"description": "Set `aria-current` to `\"page\"` to indicate that the item represents the current page. Set `aria-current` to `\"location\"` to indicate that the item represents the current location on a page. For more information about `aria-current`, see [MDN](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current)."
},
{
"name": "defaultOpen",
"type": "boolean",
"description": "The open state of the item when it is initially rendered if the item has a SubNav."
},
{
"name": "ref",
"type": "React.RefObject<HTMLAnchorElement>"
Expand Down
7 changes: 6 additions & 1 deletion src/NavList/NavList.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,12 @@ export const WithNestedSubItems: Story = () => (
<PageLayout>
<PageLayout.Pane position="start">
<NavList>
<NavList.Item href="#">Item 1</NavList.Item>
<NavList.Item defaultOpen={true} href="#">
Item 1
<NavList.SubNav>
<NavList.Item href="#">Sub item 1</NavList.Item>
</NavList.SubNav>
</NavList.Item>
<NavList.Item href="#">
Item 2{/* NOTE: Don't nest SubNavs. For testing purposes only */}
<NavList.SubNav>
Expand Down
16 changes: 11 additions & 5 deletions src/NavList/NavList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@ Root.displayName = 'NavList'

export type NavListItemProps = {
children: React.ReactNode
defaultOpen?: boolean
href?: string
'aria-current'?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false' | boolean
} & SxProp

const Item = React.forwardRef<HTMLAnchorElement, NavListItemProps>(
({'aria-current': ariaCurrent, children, sx: sxProp = defaultSxProp, ...props}, ref) => {
({'aria-current': ariaCurrent, children, defaultOpen, sx: sxProp = defaultSxProp, ...props}, ref) => {
const {depth} = React.useContext(SubNavContext)

// Get SubNav from children
Expand All @@ -64,10 +65,14 @@ const Item = React.forwardRef<HTMLAnchorElement, NavListItemProps>(
isValidElement(child) ? child.type !== SubNav : true,
)

if (!isValidElement(subNav) && defaultOpen)
// eslint-disable-next-line no-console
console.error('NavList.Item must have a NavList.SubNav to use defaultOpen.')

// Render ItemWithSubNav if SubNav is present
if (subNav && isValidElement(subNav)) {
return (
<ItemWithSubNav subNav={subNav} depth={depth} sx={sxProp}>
<ItemWithSubNav subNav={subNav} depth={depth} defaultOpen={defaultOpen} sx={sxProp}>
{childrenWithoutSubNav}
</ItemWithSubNav>
)
Expand Down Expand Up @@ -96,6 +101,7 @@ type ItemWithSubNavProps = {
children: React.ReactNode
subNav: React.ReactNode
depth: number
defaultOpen?: boolean
} & SxProp

const ItemWithSubNavContext = React.createContext<{buttonId: string; subNavId: string; isOpen: boolean}>({
Expand All @@ -106,10 +112,10 @@ const ItemWithSubNavContext = React.createContext<{buttonId: string; subNavId: s

// TODO: ref prop
// TODO: Animate open/close transition
function ItemWithSubNav({children, subNav, depth, sx: sxProp = defaultSxProp}: ItemWithSubNavProps) {
function ItemWithSubNav({children, subNav, depth, defaultOpen, sx: sxProp = defaultSxProp}: ItemWithSubNavProps) {
const buttonId = useId()
const subNavId = useId()
const [isOpen, setIsOpen] = React.useState(false)
const [isOpen, setIsOpen] = React.useState((defaultOpen || null) ?? false)
const subNavRef = React.useRef<HTMLDivElement>(null)
const [containsCurrentItem, setContainsCurrentItem] = React.useState(false)

Expand All @@ -124,7 +130,7 @@ function ItemWithSubNav({children, subNav, depth, sx: sxProp = defaultSxProp}: I
setIsOpen(true)
}
}
}, [subNav])
}, [subNav, buttonId])

return (
<ItemWithSubNavContext.Provider value={{buttonId, subNavId, isOpen}}>
Expand Down

0 comments on commit d759fd3

Please sign in to comment.