-
Notifications
You must be signed in to change notification settings - Fork 81
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
Conversation
src/components/breadcrumb/BreadcrumbNav/BreadcrumbNav.stories.tsx
Outdated
Show resolved
Hide resolved
this looks like a solid start, thanks for working on this! I want to ask if we should consider a more compositional approach to these components, to allow for more flexibility in case users need to pass other props down. for example something like this:
with |
@suzubara I'm with you on the compositional approach being more flexible. I originally pursued that path; my main reasoning for moving away from it was to be able to apply RDFA meta tags to the child components keeping parity with the uswds example. If we go with a compositional approach we would lose control over adding RDFA meta data to the children (without knowing what types of elements will be received). I imagine going that route, we would not be able to support the As far as passing in custom links, not just <BreadcrumbBar listProps={{ vocab: "http://schema.org" }}>
<Breadcrumb><BreadcrumbLink href="#">Link 1</BreadcrumbLink></Breadcrumb> //This combination of components could remain in a `LinkingBreadcrumb` component
<Breadcrumb><CustomLink href="#">Link 2</CustomLink></Breadcrumb>
<Breadcrumb>Current Link</Breadcrumb>
</BreadcrumbBar> If there's some other React magic you'd recommend I use to get around these hiccups, please let me know. Curious on your thoughts. |
✅ That should have been part of the initial issue description too as well. Whoops! Whatever solution we go with - let's write story examples in storybook with that use case to show how that would be handled. |
Thanks @haworku and @suzubara. I'm working towards and interface with out-of-the-box components that directly mirror uswds implementations that looks like this: <BreadcrumbBar>
<LinkingBreadcrumb href="#">Home</LinkingBreadcrumb>
<LinkingBreadcrumb href="#">Federal Contracting</LinkingBreadcrumb>
<LinkingBreadcrumb href="#">Contacting assistance programs</LinkingBreadcrumb>
<Breadcrumb current>Women-owned small business federal contracting program</Breadcrumb>
</BreadcrumbBar> The PR to be updated shortly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is looking really good! I have 2 main pieces of feedback:
- for components that pass intrinsic props onto one element, we've been following a pattern of using intersection types to add those props to the component (as opposed to nesting them inside of another prop). So for example, the
Breadcrumb
component would look like:
export const Breadcrumb = (props: BreadcrumbProps & JSX.IntrinsicElements['li']
I know for components that are passing intrinsic props to multiple elements, they need to be grouped together, but unless necessary I would suggest following the above pattern.
- I am kind of torn on the use of the
LinkingBreadcrumb
component over usingBreadcrumb
andBreadcrumbLink
outright.. I realize it's packaging those two components together, but the need to pass separate sets of props for theli
and thea
smells like configuration to me. Also it enforces a structure where all of thechildren
are rendered inside thea
, which would not facilitate the USWDS example with RDFa metadata where the<meta>
tag is a sibling of<a>
. My suggestion would be to:
- forgo
LinkingBreadcrumb
or at least recommend it for only the most simplest of use cases where minimal customization is needed. I might also rename it toBreadcrumbWithLink
to be more explicit about what it's doing - modify
BreadcrumbLink
so that it mirrors the existingLink
component, applies theusa-breadcrumb__link
but can also handle a custom element - resulting in an example implementation like:
<BreadcrumbBar listProps={{ ...rdfaMetadata.ol }}>
<Breadcrumb { ...rdfaMetadata.li }>
<BreadcrumbLink href="#" { ...rdfaMetadata.a }>
<span property="name">Home</span>
</BreadcrumbLink>
<meta property="position" content="1" />
</Breadcrumb>
<Breadcrumb { ...rdfaMetadata.li }>
<BreadcrumbLink<CustomLinkProps> to="#" asCustom={CustomLink} { ...rdfaMetadata.a }>
<span property="name">Federal Contracting</span>
</BreadcrumbLink>
<meta property="position" content="2" />
</Breadcrumb>
<Breadcrumb current { ...rdfaMetadata.li }>
<span property="name">
Women-owned small business federal contracting program
</span>
<meta property="position" content="4" />
</Breadcrumb>
</BreadcrumbBar>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Things look good to me!
A thought about a way to cut scope for this PR regarding<LinkingBreadcrumb />
:
This component is a nicety, not the core behavior of breadcrumb. Consumers could adapt their own version suited to their use case. They know what types of links they have and exactly what attributes they need.
If at the end of the day we feel weirdness or uncertainty about this component, or if refactoring things to be more like <Link>
feels like a heavy lift, I could see us moving this pattern into the Storybook examples, rather than exporting from the lib at this point. We could backlog a story about making a more superpowered <BreadcrumbLink>
for a later date. Not trying to dissuade you @brandonlenz at all, just want to say I feel like we have the core work for Breadcrumb done (which is great!).
src/components/breadcrumb/LinkingBreadcrumb/LinkingBreadcrumb.tsx
Outdated
Show resolved
Hide resolved
export function BreadcrumbLink(props: DefaultLinkProps): React.ReactElement | ||
export function BreadcrumbLink<T>(props: CustomLinkProps<T>): React.ReactElement | ||
export function BreadcrumbLink<FCProps = DefaultLinkProps>( | ||
props: DefaultLinkProps | CustomLinkProps<FCProps> | ||
): React.ReactElement { | ||
const { className } = props | ||
const classes = classnames(className, 'usa-breadcrumb__link') | ||
|
||
if (isCustomProps(props)) { | ||
return <Link<FCProps> {...props} className={classes} variant="unstyled" /> | ||
} | ||
|
||
return <Link {...props} className={classes} variant="unstyled" /> | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've now got BreadcrumbLink
wrapping Link
. I did not want to re-implement any logic from the Link
component, to prevent duplicated maintenance in the event the Link implementation were to change. Ultimately I had to repeat some as you can see here.
I was hoping there would be a way to wrap the Link component's signature completely in more of a HOC fashion, and simply inject the className
. Due to Link's clever overloading involving the optional generic, I had to mirror at least that part here, making my preferred solution impossible as far as I can tell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I have verified the markup matches the examples in the USWDS docs and tested this component out on MilMove! everything works as expected. We should remove the stray eslint-disable
lines, as I don't think they are needed, but after that I think this is good to 🚢 🎉
Summary
Add USWDS Breadcrumb Component.
Related Issues or PRs
Fixes #337
How To Test
Storybook remains the best way to interact with the component, especially regarding meta data. I would recommend inspecting the elements from storybook to verify:
There are also several jest tests that cover basic rendering and uswds class application.
Screenshots (from storybook)
Default Breadcrumb:
Note: non-wrapping breadcrumbs truncate:
Breadcrumb with RDFA Metadata:
Wrapping Breadcrumb:
Breadcrumb using custom Link components: