diff --git a/.changeset/slow-humans-visit.md b/.changeset/slow-humans-visit.md new file mode 100644 index 00000000000..3645a4adec0 --- /dev/null +++ b/.changeset/slow-humans-visit.md @@ -0,0 +1,5 @@ +--- +'@primer/react': major +--- + +Promoto newly written UnderlineNav to the main bundle and deprecate the old UnderlineNav diff --git a/docs/content/UnderlineNav.mdx b/docs/content/UnderlineNav.mdx index 42daa647b4e..2d59a177358 100644 --- a/docs/content/UnderlineNav.mdx +++ b/docs/content/UnderlineNav.mdx @@ -1,32 +1,194 @@ --- -componentId: underline_nav title: UnderlineNav +componentId: underline_nav status: Alpha +a11yReviewed: true +description: Use an underlined nav to allow tab like navigation with overflow behaviour in your UI. +source: https://github.com/primer/react/tree/main/src/UnderlineNav +storybook: '/react/storybook/?path=/story/components-underlinenav--playground' --- -import data from '../../src/UnderlineNav.docs.json' +import data from '../../src/UnderlineNav/UnderlineNav.docs.json' -Use the UnderlineNav component to style navigation with a minimal underlined selected state, typically used for navigation placed at the top of the page. +```js +import {UnderlineNav} from '@primer/react' +``` -To use UnderlineNav with [react-router](https://github.com/ReactTraining/react-router) or -[react-router-dom](https://www.npmjs.com/package/react-router-dom), pass -`as={NavLink}` and omit the `selected` prop. -This ensures that the NavLink gets `activeClassName='selected'` +## Examples -**Attention:** Make sure to properly label your `UnderlineNav` with an `aria-label` to provide context about the type of navigation contained in `UnderlineNav`. +### Simple -## Examples +```jsx live + + Code + Issues + Pull Requests + +``` + +### With Icons + +```jsx live + + + Code + + + Issues + + + Pull Requests + + Discussions + + Actions + + + Projects + + +``` + +### Overflow Behaviour + +Component first hides icons if they present to optimize for space and show as many items as possible. If there is still an overflow, it will display the items that don't fit in the `More` menu. + +```javascript noinline live drafts +const Navigation = () => { + const items = [ + {navigation: 'Code', icon: CodeIcon}, + {navigation: 'Issues', icon: IssueOpenedIcon, counter: 120}, + {navigation: 'Pull Requests', icon: GitPullRequestIcon, counter: 13}, + {navigation: 'Discussions', icon: CommentDiscussionIcon, counter: 5}, + {navigation: 'Actions', icon: PlayIcon, counter: 4}, + {navigation: 'Projects', icon: ProjectIcon, counter: 9}, + {navigation: 'Insights', icon: GraphIcon}, + {navigation: 'Settings', icon: GearIcon, counter: 10}, + {navigation: 'Security', icon: ShieldLockIcon}, + ] + const [selectedIndex, setSelectedIndex] = React.useState(0) + return ( + + + {items.map((item, index) => ( + { + setSelectedIndex(index) + e.preventDefault() + }} + counter={item.counter} + > + {item.navigation} + + ))} + + + ) +} +render() +``` + +### Loading State For Counters ```jsx live - - - Home - - Documentation - Support + + + Code + + Issues + Pull Requests ``` +### With React Router + +```jsx +import {Link, useMatch, useResolvedPath} from 'react-router-dom' +import {UnderlineNav} from '@primer/react/drafts' + +function UnderlineNavItem({to, children, ...rest}) { + const resolved = useResolvedPath(to) + const isCurrent = useMatch({path: resolved.pathname, end: true}) + return ( + + {children} + + ) +} + +const Navigation = () => { + return ( + + + Code + + + Issues + + Pull Requests + + ) +} +``` + +### With Next.js + +```jsx +import {useRouter} from 'next/router' +import Link from 'next/link' +import {UnderlineNav} from '@primer/react/drafts' + +function UnderlineNavItem({href, children, ...rest}) { + const router = useRouter() + const isCurrent = typeof href === 'string' ? router.asPath === href : router.pathname === href.pathname + return ( + + {children} + + ) +} + +const Navigation = () => { + return ( + + + Code + + + Issues + + Pull Requests + + ) +} +``` + ## Props + +## Status + + diff --git a/docs/content/deprecated/UnderlineNav.md b/docs/content/deprecated/UnderlineNav.md new file mode 100644 index 00000000000..cd90987f4e9 --- /dev/null +++ b/docs/content/deprecated/UnderlineNav.md @@ -0,0 +1,64 @@ +--- +componentId: underline_nav +title: UnderlineNav (legacy) +status: Deprecated +--- + +import data from '../../../src/deprecated/UnderlineNav.docs.json' + +Use the UnderlineNav component to style navigation with a minimal underlined selected state, typically used for navigation placed at the top of the page. + +## Deprecation + +Use [the new version of UnderlineNav](/UnderlineNav) with design updated and accessibility improvements. + +### Before + +```jsx + + + Home + + Documentation + Support + +``` + +### After + +```jsx + + Code + Issues + Pull Requests + +``` + +Or continue using the deprecated API: + +```js +import UnderlineNav from '@primer/react/deprecated' +``` + +To use UnderlineNav with [react-router](https://github.com/ReactTraining/react-router) or +[react-router-dom](https://www.npmjs.com/package/react-router-dom), pass +`as={NavLink}` and omit the `selected` prop. +This ensures that the NavLink gets `activeClassName='selected'` + +**Attention:** Make sure to properly label your `UnderlineNav` with an `aria-label` to provide context about the type of navigation contained in `UnderlineNav`. + +## Default example + +```jsx live deprecated + + + Home + + Documentation + Support + +``` + +## Component props + + diff --git a/docs/content/drafts/PageHeader.mdx b/docs/content/drafts/PageHeader.mdx index b16684f384f..b1c1d8186cd 100644 --- a/docs/content/drafts/PageHeader.mdx +++ b/docs/content/drafts/PageHeader.mdx @@ -127,20 +127,20 @@ import {PageHeader} from '@primer/react/drafts' Pull request title - - + + Conversation - - + + Commits - - + + Checks - - + + Files Changes - - + + ``` diff --git a/docs/content/drafts/UnderlineNav2.mdx b/docs/content/drafts/UnderlineNav2.mdx deleted file mode 100644 index 55bebf4b798..00000000000 --- a/docs/content/drafts/UnderlineNav2.mdx +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: UnderlineNav v2 -componentId: underline_nav_2 -status: Draft -a11yReviewed: true -description: Use an underlined nav to allow tab like navigation with overflow behaviour in your UI. -source: https://github.com/primer/react/tree/main/src/UnderlineNav2 -storybook: '/react/storybook/?path=/story/drafts-components-underlinenav--playground' ---- - -import data from '../../../src/UnderlineNav2/UnderlineNav2.docs.json' - -```js -import {UnderlineNav} from '@primer/react/drafts' -``` - -## Examples - -### Simple - -```jsx live drafts - - Code - Issues - Pull Requests - -``` - -### With Icons - -```jsx live drafts - - - Code - - - Issues - - - Pull Requests - - Discussions - - Actions - - - Projects - - -``` - -### Overflow Behaviour - -Component first hides icons if they present to optimize for space and show as many items as possible. If there is still an overflow, it will display the items that don't fit in the `More` menu. - -```javascript noinline live drafts -const Navigation = () => { - const items = [ - {navigation: 'Code', icon: CodeIcon}, - {navigation: 'Issues', icon: IssueOpenedIcon, counter: 120}, - {navigation: 'Pull Requests', icon: GitPullRequestIcon, counter: 13}, - {navigation: 'Discussions', icon: CommentDiscussionIcon, counter: 5}, - {navigation: 'Actions', icon: PlayIcon, counter: 4}, - {navigation: 'Projects', icon: ProjectIcon, counter: 9}, - {navigation: 'Insights', icon: GraphIcon}, - {navigation: 'Settings', icon: GearIcon, counter: 10}, - {navigation: 'Security', icon: ShieldLockIcon}, - ] - const [selectedIndex, setSelectedIndex] = React.useState(0) - return ( - - - {items.map((item, index) => ( - { - setSelectedIndex(index) - e.preventDefault() - }} - counter={item.counter} - > - {item.navigation} - - ))} - - - ) -} -render() -``` - -### Loading State For Counters - -```jsx live drafts - - - Code - - Issues - Pull Requests - -``` - -### With React Router - -```jsx -import {Link, useMatch, useResolvedPath} from 'react-router-dom' -import {UnderlineNav} from '@primer/react/drafts' - -function UnderlineNavItem({to, children, ...rest}) { - const resolved = useResolvedPath(to) - const isCurrent = useMatch({path: resolved.pathname, end: true}) - return ( - - {children} - - ) -} - -const Navigation = () => { - return ( - - - Code - - - Issues - - Pull Requests - - ) -} -``` - -### With Next.js - -```jsx -import {useRouter} from 'next/router' -import Link from 'next/link' -import {UnderlineNav} from '@primer/react/drafts' - -function UnderlineNavItem({href, children, ...rest}) { - const router = useRouter() - const isCurrent = typeof href === 'string' ? router.asPath === href : router.pathname === href.pathname - return ( - - {children} - - ) -} - -const Navigation = () => { - return ( - - - Code - - - Issues - - Pull Requests - - ) -} -``` - -## Props - - - -## Status - - diff --git a/docs/src/@primer/gatsby-theme-doctocat/nav.yml b/docs/src/@primer/gatsby-theme-doctocat/nav.yml index 006169b5b64..9ec2c5a2800 100644 --- a/docs/src/@primer/gatsby-theme-doctocat/nav.yml +++ b/docs/src/@primer/gatsby-theme-doctocat/nav.yml @@ -166,8 +166,6 @@ url: /drafts/MarkdownViewer - title: TreeView url: /TreeView - - title: UnderlineNav v2 - url: /drafts/UnderlineNav2 - title: PageHeader url: /drafts/PageHeader - title: Hidden @@ -206,3 +204,5 @@ url: /deprecated/SelectMenu - title: SideNav url: /deprecated/SideNav + - title: UnderlineNav (legacy) + url: /deprecated/UnderlineNav diff --git a/e2e/components/UnderlineNav.test.ts b/e2e/components/UnderlineNav.test.ts index a8647296b88..9c4feae9033 100644 --- a/e2e/components/UnderlineNav.test.ts +++ b/e2e/components/UnderlineNav.test.ts @@ -9,7 +9,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-examples--profile-page', + id: 'components-underlinenav-examples--profile-page', globals: { colorScheme: theme, }, @@ -21,7 +21,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-examples--profile-page', + id: 'components-underlinenav-examples--profile-page', globals: { colorScheme: theme, }, @@ -43,7 +43,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-examples--pull-request-page', + id: 'components-underlinenav-examples--pull-request-page', globals: { colorScheme: theme, }, @@ -55,7 +55,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-examples--pull-request-page', + id: 'components-underlinenav-examples--pull-request-page', globals: { colorScheme: theme, }, @@ -82,7 +82,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-examples--repos-page', + id: 'components-underlinenav-examples--repos-page', globals: { colorScheme: theme, }, @@ -94,7 +94,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-examples--repos-page', + id: 'components-underlinenav-examples--repos-page', globals: { colorScheme: theme, }, @@ -116,7 +116,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--counters-loading-state', + id: 'components-underlinenav-features--counters-loading-state', globals: { colorScheme: theme, }, @@ -128,7 +128,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--counters-loading-state', + id: 'components-underlinenav-features--counters-loading-state', globals: { colorScheme: theme, }, @@ -150,7 +150,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--default', + id: 'components-underlinenav-features--default', globals: { colorScheme: theme, }, @@ -162,7 +162,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--default', + id: 'components-underlinenav-features--default', globals: { colorScheme: theme, }, @@ -184,7 +184,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--overflow-template', + id: 'components-underlinenav-features--overflow-template', globals: { colorScheme: theme, }, @@ -196,7 +196,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--overflow-template', + id: 'components-underlinenav-features--overflow-template', globals: { colorScheme: theme, }, @@ -218,7 +218,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--with-counter-labels', + id: 'components-underlinenav-features--with-counter-labels', globals: { colorScheme: theme, }, @@ -230,7 +230,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--with-counter-labels', + id: 'components-underlinenav-features--with-counter-labels', globals: { colorScheme: theme, }, @@ -252,7 +252,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('default @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--with-icons', + id: 'components-underlinenav-features--with-icons', globals: { colorScheme: theme, }, @@ -264,7 +264,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--with-icons', + id: 'components-underlinenav-features--with-icons', globals: { colorScheme: theme, }, @@ -286,7 +286,7 @@ test.describe('UnderlineNav', () => { test.describe(theme, () => { test('Overflow interaction @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--overflow-template', + id: 'components-underlinenav-features--overflow-template', globals: { colorScheme: theme, }, @@ -310,7 +310,7 @@ test.describe('UnderlineNav', () => { test('Hide icons when there is not enough space to display all list items @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--overflow-template', + id: 'components-underlinenav-features--overflow-template', globals: { colorScheme: theme, }, @@ -328,7 +328,7 @@ test.describe('UnderlineNav', () => { test('Keep selected item visible @vrt', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--overflow-template', + id: 'components-underlinenav-features--overflow-template', globals: { colorScheme: theme, }, @@ -375,7 +375,7 @@ test.describe('UnderlineNav', () => { test('axe @aat', async ({page}) => { await visit(page, { - id: 'drafts-components-underlinenav-features--overflow-template', + id: 'components-underlinenav-features--overflow-template', globals: { colorScheme: theme, }, diff --git a/generated/components.json b/generated/components.json index add33745532..2dcce052d9e 100644 --- a/generated/components.json +++ b/generated/components.json @@ -1993,63 +1993,6 @@ ], "subcomponents": [] }, - "underline_nav": { - "id": "underline_nav", - "name": "UnderlineNav", - "status": "alpha", - "a11yReviewed": false, - "stories": [], - "props": [ - { - "name": "actions", - "type": "React.ReactNode", - "description": "Place another element, such as a button, to the opposite side of the navigation items." - }, - { - "name": "align", - "type": "'right'", - "description": "Use `right` to have navigation items aligned right." - }, - { - "name": "full", - "type": "boolean", - "description": "Used to make navigation fill the width of the container." - }, - { - "name": "aria-label", - "type": "string", - "description": "Used to set the `aria-label` on the top level `