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

Add TypeScript types for <Hyperlink> #3077

Merged
merged 3 commits into from
May 22, 2024

Conversation

bradenmacdonald
Copy link
Contributor

@bradenmacdonald bradenmacdonald commented May 17, 2024

Description

Working to incrementally expand typing in paragon. This adds types for <Hyperlink>

I removed the content prop which has been deprecated for five years, since v4.0.2.

I also clarified the description of props like externalLinkAlternativeText and isInline which were very unclear about what they were doing.

Deploy Preview

Will be available later

Merge Checklist

  • If your update includes visual changes, have they been reviewed by a designer? Send them a link to the Netlify deploy preview, if applicable. n/a
  • Does your change adhere to the documented style conventions?
  • Do any prop types have missing descriptions in the Props API tables in the documentation site (check deploy preview)?
  • Were your changes tested using all available themes (see theme switcher in the header of the deploy preview, under the "Settings" icon)?
  • Were your changes tested in the example app?
  • Is there adequate test coverage for your changes?
  • Consider whether this change needs to reviewed/QA'ed for accessibility (a11y). If so, please request an a11y review for the PR in the #wg-paragon Open edX Slack channel.

Post-merge Checklist

  • Verify your changes were released to NPM at the expected version.
  • If you'd like, share your contribution in #show-and-tell.
  • 🎉 🙌 Celebrate! Thanks for your contribution.

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label May 17, 2024
@openedx-webhooks
Copy link

Thanks for the pull request, @bradenmacdonald! Please note that it may take us up to several weeks or months to complete a review and merge your PR.

Feel free to add as much of the following information to the ticket as you can:

  • supporting documentation
  • Open edX discussion forum threads
  • timeline information ("this must be merged by XX date", and why that is)
  • partner information ("this is a course on edx.org")
  • any other information that can help Product understand the context for the PR

All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here.

Please let us know once your PR is ready for our review and all tests are green.

Copy link

netlify bot commented May 17, 2024

Deploy Preview for paragon-openedx ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit c9c030d
🔍 Latest deploy log https://app.netlify.com/sites/paragon-openedx/deploys/664d1682b04d350007f391b0
😎 Deploy Preview https://deploy-preview-3077--paragon-openedx.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

codecov bot commented May 17, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 93.19%. Comparing base (9993fb3) to head (c9c030d).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #3077   +/-   ##
=======================================
  Coverage   93.18%   93.19%           
=======================================
  Files         249      249           
  Lines        4342     4348    +6     
  Branches     1000     1000           
=======================================
+ Hits         4046     4052    +6     
  Misses        293      293           
  Partials        3        3           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

/** Custom class names for the hyperlink */
className?: string;
/** Alt text for the icon indicating that this link opens in a new tab, if target="_blank". e.g. _("in a new tab") */
externalLinkAlternativeText?: string;
Copy link
Contributor Author

@bradenmacdonald bradenmacdonald May 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left this as an optional prop. There was propTypes code below to make externalLinkAlternativeText required when target="_blank" but this wasn't actually working as far as I can tell, especially since a default value is given.

If we want to make those props conditionally required (when target=_blank), I can express that in the TypeScript types, but there are several instances in this repo alone that do not do that (example) and I suspect it would then show type errors in many other MFEs as well (if MFEs even use this component? Maybe they use react-router's Link instead).

We probably should make that required at some point, because the default value (HYPER_LINK_EXTERNAL_LINK_ALT_TEXT, above) is not internationalized. But the only good way to do that that I could think of is to require each MFE to subclass Hyperlink with a component that provides internationalized defaults for these fields, and that seems like too much work. Is there not some way to provide internationalized defaults in Paragon itself?

Copy link
Member

@adamstankiewicz adamstankiewicz May 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but this wasn't actually working as far as I can tell, especially since a default value is given.

Yeah, you're likely correct the ifRequiredWhen isn't really doing much due to the default value.

I suspect it would then show type errors in many other MFEs as well (if MFEs even use this component? Maybe they use react-router's Link instead).

Yes, this is usually the case. See the recently filed issue #3050 regarding adapting Hyperlink to be compatible with Link, such that Link usage can have more consistent styling.

We probably should make that required at some point, because the default value (HYPER_LINK_EXTERNAL_LINK_ALT_TEXT, above) is not internationalized. But the only good way to do that that I could think of is to require each MFE to subclass Hyperlink with a component that provides internationalized defaults for these fields, and that seems like too much work. Is there not some way to provide internationalized defaults in Paragon itself?

Paragon has had some i18n support in its components for a couple years now (see ADR and the README), except IIRC the pull_translations job routinely/currently fails due to an translation format error of some kind that's prevented the translations from updating in awhile. Related, I'm also not sure if Paragon has been migrated to using openedx-atlas / openedx-translations yet (unlikely), or if it intends to; @brian-smith-tcril might be able to share some insight about any plans to migrate.

It does seem by moving translations to openedx-translations, most MFEs are no longer importing/supplying paragonMessages anymore (e.g., removed from frontend-app-learning in this commit; I'm personally not sure if the Paragon i18n messages (and the shared header/footer component i18n messages) are somehow still passed to the MFEs, or if that support was (intentionally?) removed as part of the migration to openedx-translations?

If we want it to have a translated default prop (I agree, we should; looks like Hyperlink was missed in the original introduction of i18n for hardcoded English strings), then ideally we mark the strings for i18n via react-intl's defineMessage / intl.formatMessage or FormattedMessage, similar to a handful of other components in Paragon today; if the prop is provided, it gets used (where consumer might pass its own i18n string), otherwise falling back to the default i18n Paragon message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the context on i18n! I'm glad to see there is something in place, at least partially. I can look at fixing that in a follow-up PR.

Also great to see there's a plan to support Link :)

@brian-smith-tcril
Copy link
Contributor

@adamstankiewicz I'd like to merge this but I don't want to get in the way of #3050

Would this cause any problems with the work being done towards that?

Comment on lines -132 to -135
content: {
deprType: DeprTypes.MOVED,
newName: 'children',
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 great to clean this up :) related to removing deprecated stuff, I'm looking forward to having all the deprecated UI components removed as part of the alpha design tokens release, too.

showLaunchIcon,
...attrs
} = props;
interface Props extends Omit<React.ComponentPropsWithoutRef<'a'>, 'href' | 'target'> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[clarification] Hyperlink uses forwardRef below, yet the Props interface is defining it as React.ComponentPropsWithoutRef; should it be using ComponentPropsWithRef?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! In this case, the forwardRef wrapper is overriding the type and injecting the ref prop anyways, so it doesn't really matter whether we use WithoutRef or WithRef here - the type that will be seen elsewhere in the code is the same. But I think it makes sense to use withRef since we are dealing with refs, and it's perhaps less confusing that way. So I just pushed a small commit to change it.

@adamstankiewicz
Copy link
Member

@adamstankiewicz I'd like to merge this but I don't want to get in the way of #3050

Would this cause any problems with the work being done towards that?

I hadn't quite gotten to creating that PR last week; still hope to this week. This work shouldn't cause any problems. The fix for the #3050 is additive (i.e., would introduce a new as prop), where if this PR merges first, the PR for #3050 would ensure the as prop is appropriately typed.

Added a couple other review comments onto the PR.

window.crypto = {
getRandomValues: arr => crypto.randomBytes(arr.length),
(window as any).crypto = {
getRandomValues: (arr: any) => crypto.randomBytes(arr.length),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamstankiewicz I see you added this getRandomValues stub in eac3925 , but I noticed just now that the test suite passes just fine if I completely remove this line. Is it still necessary/useful?

Copy link
Member

@adamstankiewicz adamstankiewicz May 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, looked back through the PR that added this bit; I'm honestly not sure why it was added at this point! Probably can be safely removed. Actually, it looks like it's already been removed in Paragon's alpha release, too (source) 😄

@bradenmacdonald
Copy link
Contributor Author

Thanks for the quick reviews @brian-smith-tcril and @adamstankiewicz ! Could one of you please merge this at your convenience? :)

externalLinkAlternativeText,
externalLinkTitle,
...props,
};

describe('correct rendering', () => {
beforeEach(() => {
onClick.mockClear();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could opt for jest.clearAllMocks vs. clearing the specific onClick mock (even though it's the only mock here).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[inform] When I open my PR to add support for Link usage with Hyperlink, I will plan to make this change (as well as remove the window.crypto stuff in setupTest.js per the other comment).

@adamstankiewicz adamstankiewicz merged commit d4fce25 into openedx:master May 22, 2024
10 checks passed
@openedx-webhooks
Copy link

@bradenmacdonald 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future.

@openedx-semantic-release-bot

🎉 This PR is included in version 22.5.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
open-source-contribution PR author is not from Axim or 2U released
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

5 participants