diff --git a/packages/react/src/NavList/NavList.docs.json b/packages/react/src/NavList/NavList.docs.json index 8c128ae36bb..899792d48a9 100644 --- a/packages/react/src/NavList/NavList.docs.json +++ b/packages/react/src/NavList/NavList.docs.json @@ -132,6 +132,12 @@ "description": "A related set of NavList.Items", "defaultValue": "" }, + { + "name": "hideDividier", + "type": "boolean", + "defaultValue": "false", + "description": "When true, the divider between the group and the next item will not be rendered." + }, { "name": "title", "type": "string", @@ -264,4 +270,5 @@ ] } ] -} \ No newline at end of file +} + diff --git a/packages/react/src/NavList/NavList.features.stories.tsx b/packages/react/src/NavList/NavList.features.stories.tsx new file mode 100644 index 00000000000..15d15534086 --- /dev/null +++ b/packages/react/src/NavList/NavList.features.stories.tsx @@ -0,0 +1,591 @@ +import type {Meta, StoryFn} from '@storybook/react-vite' +import React from 'react' +import {PageLayout} from '../PageLayout' +import {NavList} from './NavList' +import { + type Icon, + ArrowRightIcon, + ArrowLeftIcon, + BookIcon, + FileDirectoryIcon, + CodeIcon, + RepoIcon, + IssueOpenedIcon, + GitPullRequestIcon, + CommentDiscussionIcon, + PeopleIcon, + GitCommitIcon, + PackageIcon, + MilestoneIcon, + TelescopeIcon, +} from '@primer/octicons-react' +import Octicon from '../Octicon' +import VisuallyHidden from '../_VisuallyHidden' +import {ReactRouterLikeLink} from '../Pagination/mocks/ReactRouterLink' + +const meta: Meta = { + title: 'Components/NavList/Features', + component: NavList, + parameters: { + layout: 'fullscreen', + }, +} + +export const Simple: StoryFn = () => ( + + + + + Item 1 + + Item 2 + Item 3 + + + + +) + +export const WithSubItems: StoryFn = () => ( + + + + Item 1 + + Item 2 + + + Sub item 1 + + Sub item 2 + + + Item 3 + + + + +) + +export const WithNestedSubItems: StoryFn = () => ( + + + + + Item 1 + + Sub item 1 + + + + Item 2{/* NOTE: Don't nest SubNavs. For testing purposes only */} + + + Sub item 1 + + + Sub item 1.1 + + Sub item 1.1.1 + + Sub item 1.1.2 + + Sub item 1.1.2.1 + + Sub item 1.1.2.2 + + + + + + Sub item 1.2 + + + Sub item 2 + + + Item 3 + + + + +) + +export const WithReactRouterLink = () => ( + + + + + Item 1 + + + Item 2 + + + Item 3 + + + + + +) + +type NextJSLinkProps = {href: string; children: React.ReactNode} + +const NextJSLikeLink = React.forwardRef( + ({href, children}, ref): React.ReactElement => { + const child = React.Children.only(children) + const childProps = { + ref, + href, + } + return <>{React.isValidElement(child) ? React.cloneElement(child, childProps) : null} + }, +) + +export const WithNextJSLink = () => ( + + + + + Item 1 + + + Item 2 + + + Item 3 + + + + + +) + +export const WithReloads: StoryFn = () => { + // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc + const location = window.location + + const storyId = new URLSearchParams(location.search).get('id') + const urlBase = `${location.origin + location.pathname}?id=${storyId}` + const itemId = new URLSearchParams(location.search).get('itemId') + + return ( + <> + + + + + Item 1 + + + Item 2 + + + Sub item 2.1 + + + Sub item 2.2 + + + + + Item 3 + + + Sub item 3.1 + + + Sub item 3.2 + + + + + + + + + ) +} + +export const WithInactiveItems: StoryFn = () => ( + + + + + Item 1 + + + Item 2 + + + Sub item 1 + + + Sub item 2 + + + + Item 3 + + + + +) + +export const WithGroup: StoryFn = () => ( + + + + + + Item 1A + + Item 1B + Item 1C + + + Item 2A + Item 2B + Item 2C + + + + + +) + +export const WithGroupHeadingLinks: StoryFn = () => ( + + + + + + Group 1 + + + Item 1A + + Item 1B + Item 1C + + + + Group 2 + + Item 2A + Item 2B + Item 2C + + + + + +) + +export const WithTrailingAction = () => { + return ( + + + + + + + + Item 1 + + + + Item 2 + + + + + + ) +} + +export const WithTrailingActionInSubItem = () => { + return ( + + + + + + + + Item 1 + + + + Item 2 + + + + Item 3 + + + Sub item 1 + + + + + + + + ) +} + +export const WithExpand: StoryFn = () => { + const items = [ + {href: '#', text: 'Item 4'}, + {href: '#', text: 'Item 5'}, + {href: '#', text: 'Item 6'}, + {href: '#', text: 'Item 7'}, + {href: '#', text: 'Item 8'}, + {href: '#', text: 'Item 9'}, + ] + + return ( + + + + + Item 1 + + Item 2 + Item 3 + + + + + + ) +} + +export const WithExpandAndIcons: StoryFn = () => { + const items = [ + {href: '#', text: 'Item 4'}, + {href: '#', text: 'Item 5'}, + {href: '#', text: 'Item 6'}, + {href: '#', text: 'Item 7'}, + {href: '#', text: 'Item 8'}, + {href: '#', text: 'Item 9'}, + ] + + return ( + + + + + Item 1 + + Item 2 + Item 3 + + + + + + ) +} + +type CustomItemProps = { + text: string + leadingVisual?: Icon + trailingVisual?: Icon | string +} + +export const ExpandWithCustomItems: StoryFn = () => { + const items: {href: string; text: string; 'aria-current'?: 'page'}[] = [ + {href: '#', text: 'Item 4', 'aria-current': 'page'}, + {href: '#', text: 'Item 5'}, + {href: '#', text: 'Item 6'}, + {href: '#', text: 'Item 7'}, + {href: '#', text: 'Item 8'}, + {href: '#', text: 'Item 9'}, + ] + + const Item = ({leadingVisual, text, trailingVisual, ...rest}: CustomItemProps) => { + return ( + {}} href="#" {...rest}> + {leadingVisual ? ( + + + + ) : null} + {text} + + {trailingVisual ? ( + + {typeof trailingVisual === 'string' ? ( + trailingVisual + ) : ( + + )} + results + + ) : null} + + ) + } + + return ( + + + + Item 1 + Item 2 + Item 3 + + + + + + ) +} + +export const ExpandWithPages: StoryFn = () => { + const items = [ + {href: '#', text: 'Item 4'}, + {href: '#', text: 'Item 5'}, + {href: '#', text: 'Item 6'}, + {href: '#', text: 'Item 7'}, + {href: '#', text: 'Item 8'}, + {href: '#', text: 'Item 9'}, + ] + + return ( + + + + + Item 1 + + Item 2 + Item 3 + + + + + + ) +} + +export const WithGroupExpand = () => { + const items1 = [ + {href: '#', text: 'Item 1D'}, + {href: '#', text: 'Item 1E', trailingAction: {label: 'Some action', icon: ArrowRightIcon}}, + ] + + const items2 = [ + {href: '#', text: 'Item 2D', trailingVisual: BookIcon}, + {href: '#', text: 'Item 2E', trailingVisual: FileDirectoryIcon}, + ] + + return ( + + + + + + Item 1A + + Item 1B + Item 1C + + + + Item 2A + Item 2B + Item 2C + + + + + + + ) +} + +export const GroupWithExpandAndCustomItems = () => { + const Item = ({leadingVisual: LeadingVisual, text, trailingVisual: TrailingVisual, ...rest}: CustomItemProps) => { + return ( + {}} href="#" {...rest} key={text}> + {LeadingVisual ? ( + + + + ) : null} + {text} + + {TrailingVisual ? ( + + {typeof TrailingVisual === 'string' ? TrailingVisual : } + results + + ) : null} + + ) + } + + const items = [ + {href: '#', text: 'Commits', leadingVisual: GitCommitIcon, trailingVisual: '32k'}, + {href: '#', text: 'Packages', leadingVisual: PackageIcon, trailingVisual: '1k'}, + {href: '#', text: 'Wikis', leadingVisual: BookIcon, trailingVisual: '121'}, + {href: '#', text: 'Topics', leadingVisual: MilestoneIcon, trailingVisual: '12k'}, + {href: '#', text: 'Marketplace', leadingVisual: TelescopeIcon, trailingVisual: ArrowRightIcon}, + ] + + return ( + + + + + + + Code + 3k + + + + + + Repositories + 713 + + + + + + Issues + 6k + + + + + + Pull requests + 4k + + + + + + Discussions + 236 + + + + + + Users + 10k + + + + + ) +} + +export default meta diff --git a/packages/react/src/NavList/NavList.stories.tsx b/packages/react/src/NavList/NavList.stories.tsx index de783381567..ef03ba7a501 100644 --- a/packages/react/src/NavList/NavList.stories.tsx +++ b/packages/react/src/NavList/NavList.stories.tsx @@ -31,7 +31,9 @@ const meta: Meta = { }, } -export const Simple: StoryFn = () => ( +export default meta + +export const Default = () => ( @@ -45,547 +47,3 @@ export const Simple: StoryFn = () => ( ) - -export const WithSubItems: StoryFn = () => ( - - - - Item 1 - - Item 2 - - - Sub item 1 - - Sub item 2 - - - Item 3 - - - - -) - -export const WithNestedSubItems: StoryFn = () => ( - - - - - Item 1 - - Sub item 1 - - - - Item 2{/* NOTE: Don't nest SubNavs. For testing purposes only */} - - - Sub item 1 - - - Sub item 1.1 - - Sub item 1.1.1 - - Sub item 1.1.2 - - Sub item 1.1.2.1 - - Sub item 1.1.2.2 - - - - - - Sub item 1.2 - - - Sub item 2 - - - Item 3 - - - - -) - -export const WithReactRouterLink = () => ( - - - - - Item 1 - - - Item 2 - - - Item 3 - - - - - -) - -type NextJSLinkProps = {href: string; children: React.ReactNode} - -const NextJSLikeLink = React.forwardRef( - ({href, children}, ref): React.ReactElement => { - const child = React.Children.only(children) - const childProps = { - ref, - href, - } - return <>{React.isValidElement(child) ? React.cloneElement(child, childProps) : null} - }, -) - -export const WithNextJSLink = () => ( - - - - - Item 1 - - - Item 2 - - - Item 3 - - - - - -) - -export const WithReloads: StoryFn = () => { - // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc - const location = window.location - - const storyId = new URLSearchParams(location.search).get('id') - const urlBase = `${location.origin + location.pathname}?id=${storyId}` - const itemId = new URLSearchParams(location.search).get('itemId') - - return ( - <> - - - - - Item 1 - - - Item 2 - - - Sub item 2.1 - - - Sub item 2.2 - - - - - Item 3 - - - Sub item 3.1 - - - Sub item 3.2 - - - - - - - - - ) -} - -export const WithInactiveItems: StoryFn = () => ( - - - - - Item 1 - - - Item 2 - - - Sub item 1 - - - Sub item 2 - - - - Item 3 - - - - -) - -export const WithGroup: StoryFn = () => ( - - - - - - Item 1A - - Item 1B - Item 1C - - - Item 2A - Item 2B - Item 2C - - - - - -) - -export const WithGroupHeadingLinks: StoryFn = () => ( - - - - - - Group 1 - - - Item 1A - - Item 1B - Item 1C - - - - Group 2 - - Item 2A - Item 2B - Item 2C - - - - - -) - -export const WithTrailingAction = () => { - return ( - - - - - - - - Item 1 - - - - Item 2 - - - - - - ) -} - -export const WithTrailingActionInSubItem = () => { - return ( - - - - - - - - Item 1 - - - - Item 2 - - - - Item 3 - - - Sub item 1 - - - - - - - - ) -} - -export const WithExpand: StoryFn = () => { - const items = [ - {href: '#', text: 'Item 4'}, - {href: '#', text: 'Item 5'}, - {href: '#', text: 'Item 6'}, - {href: '#', text: 'Item 7'}, - {href: '#', text: 'Item 8'}, - {href: '#', text: 'Item 9'}, - ] - - return ( - - - - - Item 1 - - Item 2 - Item 3 - - - - - - ) -} - -export const WithExpandAndIcons: StoryFn = () => { - const items = [ - {href: '#', text: 'Item 4'}, - {href: '#', text: 'Item 5'}, - {href: '#', text: 'Item 6'}, - {href: '#', text: 'Item 7'}, - {href: '#', text: 'Item 8'}, - {href: '#', text: 'Item 9'}, - ] - - return ( - - - - - Item 1 - - Item 2 - Item 3 - - - - - - ) -} - -type CustomItemProps = { - text: string - leadingVisual?: Icon - trailingVisual?: Icon | string -} - -export const ExpandWithCustomItems: StoryFn = () => { - const items: {href: string; text: string; 'aria-current'?: 'page'}[] = [ - {href: '#', text: 'Item 4', 'aria-current': 'page'}, - {href: '#', text: 'Item 5'}, - {href: '#', text: 'Item 6'}, - {href: '#', text: 'Item 7'}, - {href: '#', text: 'Item 8'}, - {href: '#', text: 'Item 9'}, - ] - - const Item = ({leadingVisual, text, trailingVisual, ...rest}: CustomItemProps) => { - return ( - {}} href="#" {...rest}> - {leadingVisual ? ( - - - - ) : null} - {text} - - {trailingVisual ? ( - - {typeof trailingVisual === 'string' ? ( - trailingVisual - ) : ( - - )} - results - - ) : null} - - ) - } - - return ( - - - - Item 1 - Item 2 - Item 3 - - - - - - ) -} - -export const ExpandWithPages: StoryFn = () => { - const items = [ - {href: '#', text: 'Item 4'}, - {href: '#', text: 'Item 5'}, - {href: '#', text: 'Item 6'}, - {href: '#', text: 'Item 7'}, - {href: '#', text: 'Item 8'}, - {href: '#', text: 'Item 9'}, - ] - - return ( - - - - - Item 1 - - Item 2 - Item 3 - - - - - - ) -} - -export const WithGroupExpand = () => { - const items1 = [ - {href: '#', text: 'Item 1D'}, - {href: '#', text: 'Item 1E', trailingAction: {label: 'Some action', icon: ArrowRightIcon}}, - ] - - const items2 = [ - {href: '#', text: 'Item 2D', trailingVisual: BookIcon}, - {href: '#', text: 'Item 2E', trailingVisual: FileDirectoryIcon}, - ] - - return ( - - - - - - Item 1A - - Item 1B - Item 1C - - - - Item 2A - Item 2B - Item 2C - - - - - - - ) -} - -export const GroupWithExpandAndCustomItems = () => { - const Item = ({leadingVisual: LeadingVisual, text, trailingVisual: TrailingVisual, ...rest}: CustomItemProps) => { - return ( - {}} href="#" {...rest} key={text}> - {LeadingVisual ? ( - - - - ) : null} - {text} - - {TrailingVisual ? ( - - {typeof TrailingVisual === 'string' ? TrailingVisual : } - results - - ) : null} - - ) - } - - const items = [ - {href: '#', text: 'Commits', leadingVisual: GitCommitIcon, trailingVisual: '32k'}, - {href: '#', text: 'Packages', leadingVisual: PackageIcon, trailingVisual: '1k'}, - {href: '#', text: 'Wikis', leadingVisual: BookIcon, trailingVisual: '121'}, - {href: '#', text: 'Topics', leadingVisual: MilestoneIcon, trailingVisual: '12k'}, - {href: '#', text: 'Marketplace', leadingVisual: TelescopeIcon, trailingVisual: ArrowRightIcon}, - ] - - return ( - - - - - - - Code - 3k - - - - - - Repositories - 713 - - - - - - Issues - 6k - - - - - - Pull requests - 4k - - - - - - Discussions - 236 - - - - - - Users - 10k - - - - - ) -} - -export default meta diff --git a/packages/react/src/NavList/NavList.tsx b/packages/react/src/NavList/NavList.tsx index 360558fded8..694d5ba9afa 100644 --- a/packages/react/src/NavList/NavList.tsx +++ b/packages/react/src/NavList/NavList.tsx @@ -282,11 +282,12 @@ TrailingAction.displayName = 'NavList.TrailingAction' export type NavListGroupProps = React.HTMLAttributes & { children: React.ReactNode + hideDivider?: boolean title?: string } & SxProp const defaultSx = {} -const Group: React.FC = ({title, children, sx: sxProp = defaultSx, ...props}) => { +const Group: React.FC = ({hideDivider, title, children, sx: sxProp = defaultSx, ...props}) => { if (sxProp !== defaultSx) { return ( @@ -297,7 +298,7 @@ const Group: React.FC = ({title, children, sx: sxProp = defau } return ( <> - + {hideDivider ? null : } {/* Setting up the default value for the heading level. TODO: API update to give flexibility to NavList.Group title's heading level */} {title ? (