-
Notifications
You must be signed in to change notification settings - Fork 73
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: introduce as
prop for Hyperlink
#3082
feat: introduce as
prop for Hyperlink
#3082
Conversation
✅ Deploy Preview for paragon-openedx ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## release-22.x #3082 +/- ##
================================================
- Coverage 93.44% 93.40% -0.05%
================================================
Files 251 251
Lines 4519 4531 +12
Branches 1055 1064 +9
================================================
+ Hits 4223 4232 +9
- Misses 293 296 +3
Partials 3 3 ☔ View full report in Codecov by Sentry. |
7af05c8
to
fa72a7d
Compare
src/Hyperlink/index.tsx
Outdated
import { Launch } from '../../icons'; | ||
import Icon from '../Icon'; | ||
|
||
export const HYPER_LINK_EXTERNAL_LINK_ALT_TEXT = 'in a new tab'; | ||
export const HYPER_LINK_EXTERNAL_LINK_TITLE = 'Opens in a new tab'; | ||
|
||
interface Props extends Omit<React.ComponentPropsWithRef<'a'>, 'href' | 'target'> { | ||
interface HyperlinkProps extends BsPrefixProps, Omit<React.ComponentPropsWithRef<'a'>, 'href' | 'target'> { | ||
/** specifies the URL */ | ||
destination: string; |
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.
When using Hyperlink
with Link
from React Router (or GatsbyLink
on the Paragon docs site example), the destination
prop will not suffice as it gets passed to an href
prop, leading to the link getting treated as an external URL (triggering full-page refresh).
Both Link
and GatsbyLink
utilize the standard hyperlink (i.e., a
) when href
prop is provided; to get it to work with internal routing, the to
prop must be passed.
Because we use prop spreading of all attributes passed to the Hyperlink
component, consumers can pass to
prop but would continue to need to pass destination
as it's a required prop.
We will need to determine how consumers can pass to
without needing to also pass an identical value to destination
(i.e., href
), e.g.:
<Hyperlink
as={GatsbyLink}
to="/components/button"
// `destination` is still a required prop even though the `to` takes precedence.
destination="/components/button"
>
Button
</Hyperlink>
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.
@bradenmacdonald Curious if you might have any thoughts on how to mitigate this concern around to
vs. href
vs. destination
?
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.
Yeah, I was wondering about this.
I think one nice option is to change the Paragon hyperlink
to accept to
instead of destination
and just treat destination
as a deprecated alias for to
?
Otherwise to avoid the need to introspect as
and determine what prop to pass based on some conditions, you could change the logic that currently converts destination
to href
and instead convert destination
to both href
and to
, and unconditionally pass both props to the inner as
component. Though I think this may display a DOM warning in the console that a
doesn't accept a to
attribute. So maybe some conditional logic is actually needed.
fa72a7d
to
9ead6aa
Compare
as
prop for Hyperlink
9ead6aa
to
765b95e
Compare
✅ Deploy Preview for paragon-openedx-v22 ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
671a6e9
to
6d030f4
Compare
/** specifies the URL */ | ||
destination: PropTypes.string.isRequired, | ||
/** specifies the component element type to render for the hyperlink */ | ||
// @ts-ignore |
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.
[inform] It's unclear why TS throws an error on the as
prop type; as its functional, opting to @ts-ignore
for now.
6d030f4
to
03705d5
Compare
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.
Overall this is looking great! Super happy to see this so close to landing.
I left a couple little comments with questions about onClick
, any thoughts on those would be great!
const wrapper = getByRole('link'); | ||
expect(wrapper).toHaveAttribute('rel', 'noopener noreferrer'); | ||
}); | ||
}); | ||
|
||
describe('event handlers are triggered correctly', () => { | ||
it('should fire onClick', async () => { |
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.
It looks like onClick
is still something we have an example for on the docs site https://deploy-preview-3082--paragon-openedx.netlify.app/components/hyperlink/#with-onclick
I think it might be worth keeping this test to cover the off chance someone accidentally removes onClick={onClick}
from the Hyperlink
component.
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 removed this test case, as its behavior is technically already covered within the "renders Hyperlink" test case, i.e.:
// Clicking on the link should call the onClick handler
await userEvent.click(wrapper);
expect(onClick).toHaveBeenCalledTimes(1);
@@ -95,7 +95,6 @@ exports[`Menu Item renders correctly renders as expected with menu items 1`] = ` | |||
<a | |||
className="pgn__hyperlink default-link standalone-link pgn__menu-item" | |||
href="https://en.wikipedia.org/wiki/Hyperlink" | |||
onClick={[Function]} |
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.
While I think it's absolutely great that we don't have "bonus" onClick
s anymore, it's not clear to me what caused this change. Any insight into this would be awesome!
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.
The removal of the "bonus" onClick
was caused by changing the defaultProps.onClick
to undefined
instead of the no-op function () => {}
. I'm not sure having the no-op function is providing much value, so opted to remove it since its only a pass-thru prop, and isn't a breaking change.
For example, we don't do any conditional checks before calling it within Hyperlink
(e.g., nothing like, onClick.?(e)
implemented).
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 PR is included in version 22.15.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
🎉 This PR is included in version 23.4.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Description
Introduces
as
prop and types forHyperlink
to make it compatible with React Router'sLink
. The previously requireddestination
prop is now only conditionally required when theas
prop is a standard anchor tag (i.e.,a
).If
Hyperlink
is used withLink
, consumers would be passing theto
prop, but Paragon shouldn't hardcode any router-specific props in its codebase.Deploy Preview
https://deploy-preview-3082--paragon-openedx.netlify.app/components/hyperlink
Merge Checklist
example
app?Post-merge Checklist