Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: New Component: Breadcrumb #804

Merged
merged 26 commits into from
Feb 3, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d44b382
Add Breadcrumb nav component
brandonlenz Jan 16, 2021
5e58d3a
WIP commit: add metadata
brandonlenz Jan 19, 2021
fd4aac9
Add breadcrumb position meta data
brandonlenz Jan 19, 2021
9e0f5ff
Add exports for new components
brandonlenz Jan 19, 2021
d5305b2
Simplify structure and rename to match docs
brandonlenz Jan 20, 2021
bc29bfa
Refactor Breadcrumbs for modularity and simplicity
brandonlenz Jan 20, 2021
fae8cda
Merge branch 'main' into bl-breadcrumb-337
brandonlenz Jan 20, 2021
f1e52f3
Update BreadcrumbBar for compositional flexiblity
brandonlenz Jan 20, 2021
28bf629
Add unit tests
brandonlenz Jan 21, 2021
6458229
Fix indentation
brandonlenz Jan 21, 2021
18db9f4
Use existing custom link for storybook example
brandonlenz Jan 21, 2021
7cca031
Fix typo
brandonlenz Jan 21, 2021
cac9ae3
Update custom link stories and test
brandonlenz Jan 21, 2021
2a102df
Update custom element test to use Link
brandonlenz Jan 21, 2021
8abb76f
Use classnames object-syntax for conditional class
brandonlenz Jan 27, 2021
3b391ba
Remove compositional convenience component
brandonlenz Jan 27, 2021
0197cfa
Update BreadcrumbLink to wrap Link
brandonlenz Jan 28, 2021
52841b9
Make sure styled Link class is not applied
brandonlenz Jan 28, 2021
1b9337f
Unify Span for storybook examples
brandonlenz Jan 28, 2021
f450b19
Merge branch 'main' into bl-breadcrumb-337
brandonlenz Jan 28, 2021
1746ba1
Merge branch 'bl-breadcrumb-337' of github.com:trussworks/react-uswds…
brandonlenz Jan 28, 2021
613f3d5
Update storybook title to match new convention
brandonlenz Jan 28, 2021
7330428
Remove unused import
brandonlenz Jan 28, 2021
a20556a
Remove unused eslint ignores and add test case
brandonlenz Jan 29, 2021
d3da5b8
Merge branch 'main' into bl-breadcrumb-337
brandonlenz Feb 2, 2021
cfd8e35
Merge branch 'main' into bl-breadcrumb-337
brandonlenz Feb 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions src/components/breadcrumb/Breadcrumb/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react'
import classnames from 'classnames'

export interface BreadcrumbProps {
label: string
href?: string
current?: boolean
withMetaData?: boolean
position?: number
}

export const Breadcrumb = (
props: BreadcrumbProps & JSX.IntrinsicElements['li']
): React.ReactElement => {
const {
label,
href,
current = false,
withMetaData = false,
position = undefined,
brandonlenz marked this conversation as resolved.
Show resolved Hide resolved
className,
...listItemProps
} = props

const assignMetaDataValue = (value: string): string | undefined => {
return withMetaData ? value : undefined
}

const metaData = {
li: {
property: assignMetaDataValue('itemListElement'),
typeof: assignMetaDataValue('ListItem'),
},
a: {
property: assignMetaDataValue('item'),
typeof: assignMetaDataValue('WebPage'),
},
span: {
property: assignMetaDataValue('name'),
},
}
brandonlenz marked this conversation as resolved.
Show resolved Hide resolved

const metaPositionTag = position ? (
<meta property="position" content={position.toString()} />
) : undefined

if (current) {
return (
<li
property={metaData.li.property}
typeof={metaData.li.typeof}
className={classnames(
'usa-breadcrumb__list-item usa-current',
className
)}
{...listItemProps}
aria-current="page">
<span property={metaData.span.property}>{label}</span>
{withMetaData && metaPositionTag}
</li>
)
}

return (
<li
property={metaData.li.property}
typeof={metaData.li.typeof}
className={classnames('usa-breadcrumb__list-item', className)}
{...listItemProps}>
<a
property={metaData.a.property}
typeof={metaData.a.typeof}
href={href}
className="usa-breadcrumb__link">
<span property={metaData.span.property}>{label}</span>
{withMetaData && metaPositionTag}
</a>
</li>
)
}
51 changes: 51 additions & 0 deletions src/components/breadcrumb/BreadcrumbNav/BreadcrumbNav.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react'
import { Breadcrumb } from '../Breadcrumb/Breadcrumb'
import { BreadcrumbNav } from './BreadcrumbNav'

export default {
title: 'Breadcrumb',
component: BreadcrumbNav,
parameters: {
info: `
Provide secondary navigation to help users understand where they are in a website.

Source: https://designsystem.digital.gov/components/breadcrumb/
`,
},
}

export const DefaultBreadcrumb = (): React.ReactElement => (
<BreadcrumbNav>
<Breadcrumb label="Home" href="#" />
<Breadcrumb label="Federal Contracting" href="#" />
<Breadcrumb label="Contacting assistance programs" href="#" />
<Breadcrumb
label="Women-owned small business federal contracting program"
current
/>
</BreadcrumbNav>
brandonlenz marked this conversation as resolved.
Show resolved Hide resolved
)

export const BreadcrumbWithRdfaMetaData = (): React.ReactElement => (
<BreadcrumbNav withMetaData>
<Breadcrumb label="Home" href="#" />
<Breadcrumb label="Federal Contracting" href="#" />
<Breadcrumb label="Contacting assistance programs" href="#" />
<Breadcrumb
label="Women-owned small business federal contracting program"
current
/>
</BreadcrumbNav>
)

export const WrappingBreadcrumb = (): React.ReactElement => (
<BreadcrumbNav variant="wrap">
<Breadcrumb label="Home" href="#" />
<Breadcrumb label="Federal Contracting" href="#" />
<Breadcrumb label="Contacting assistance programs" href="#" />
<Breadcrumb
label="Women-owned small business federal contracting program"
current
/>
</BreadcrumbNav>
)
47 changes: 47 additions & 0 deletions src/components/breadcrumb/BreadcrumbNav/BreadcrumbNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { ReactElement } from 'react'
import classnames from 'classnames'

import { BreadcrumbProps } from '../Breadcrumb/Breadcrumb'

interface BreadcrumbNavProps {
variant?: 'default' | 'wrap'
withMetaData?: boolean
children: ReactElement<BreadcrumbProps>[]
}

export const BreadcrumbNav = (
props: BreadcrumbNavProps & JSX.IntrinsicElements['nav']
): React.ReactElement => {
const {
variant = 'default',
withMetaData = false,
children,
className,
...navProps
} = props
const uswdsClassName =
variant === 'wrap'
? 'usa-breadcrumb usa-breadcrumb--wrap'
: 'usa-breadcrumb'
const classes = classnames(uswdsClassName, className)

let breadcrumbs = children
if (withMetaData) {
breadcrumbs = children.map((child, index) =>
React.cloneElement(child, {
withMetaData: true,
position: index + 1,
})
)
}

return (
<nav className={classes} {...navProps} aria-label="Breadcrumbs">
<ol
vocab={withMetaData ? 'http://schema.org/' : undefined}
className="usa-breadcrumb__list">
{breadcrumbs}
</ol>
</nav>
)
}