-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[Link] Warn users when links open in a new window #1247
Conversation
const className = classNames(styles.Link, monochrome && styles.monochrome); | ||
let childrenMarkup = children; | ||
|
||
if (external && typeof children === 'string') { |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
<span className={styles.IconLockup}> | ||
{lastWord} | ||
<Icon accessibilityLabel={iconLabel} source={ExternalSmallMinor} /> | ||
</span> |
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.
In order to center the icon with the text, and to prevent the icon from wrapping by itself to the next line, the best solution I found is to wrap the last word and the icon in an inline-flex container.
This way of preventing unwanted wrapping won’t work with languages like Japanese because those languages don’t use spaces between words. I’m not sure what to do about this.
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.
For languages that does not use space between words, you can grab the last character + punctuation as a word. Since each character is consider a word, a single character on the second line is perfectly fine. But punctuation should never be wrap onto the next line by itself.
✅
你好
嗎。
❎
你好嗎
。
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.
Thanks @michelleyschen! Would we want an icon at the end of a text link to behave the same way as punctuation?
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.
yes, I would consider icon a punctuation
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.
Thanks. I have a new implementation that doesn’t manipulate the children string. Should work for all languages now 😄
What if we ignore the content of
Caveats: Could be weird if someone decides to use a |
@yourpalsonja Thanks for looking at this. That’s an interesting idea! I tried it a couple ways, and I think something like it could work. Polaris React uses inline SVGs, relying on them for being able to recolor icons for interaction effects like hover. I am not sure, but I don’t think inline SVGs play well with CSS generated content. BUT, if we made the link The downside is that as you pointed out, the whole link wraps as a unit, which will cause some disruption to the flow of the text on narrower columns when links are long. Example: Both approaches have tradeoffs. Are there other approaches? |
I tried inserting a Have we considered something like a Tooltip? In the end visually impaired users are warned of the new window via the 1 caveat with our Tooltip implementation is that the link would not wrap. |
@dleroux We currently have a few logged a11y issues around tooltips (https://github.com/Shopify/polaris-ux/issues/154, #793), so I'd like to avoid adding more complexity for the link. The
@yourpalsonja If we add the icon as a pseudo-element, we'll need a way to provide the text equivalent for the icon as part of the link content. It doesn't appear that |
@ry5n I was thinking the link wrapping in this case would be a good thing, so the text doesn't look too crowded with the link beside it? I could be wrong though. @dpersing would we need to provide accessible text for the icon, or could we just add text that is read by the screen reader in addition to the icon? (like, "Visit our docs" [icon]), and a screenreader would read "Visit our docs, external link". |
Here’s a side-by-side of how the 2 wrapping options behave:
Here’s what the the current PR does. Screen readers will see “(opens a new window)” appended to the link content. (This follows Devon’s recommendation in the original issue): |
@yourpalsonja I think it's 6 of 1 and half a dozen of the other! I also want to clarify that it's less that it's an external link and more that it's a link that opens a new tab/window. The issue isn't with the content, but with the browser behavior, if that makes sense. @ry5n's "(opens a new window)" text does the trick! |
OK, I think I found another way. This is close to what Dan was thinking. I’ve tested this with different font sizes, and in Chrome, Firefox, Safari and Edge (CodeSandbox doesn’t work in IE11, so I couldn’t test there). I’ve also tested it with our different system fonts (San Francisco, Roboto, and Segoe UI). https://codesandbox.io/s/9wymvnyrw Here’s how this works:
|
Looks great when text is resized too, @ry5n ! ❤️ |
……except it actually doesn’t work in Polaris React, trying it for real. This is probably what Dan ran into. I’m stumped. |
Looks like the span around the last word might be it. https://snook.ca/archives/html_and_css/icon-wrap-after-text |
Yeah. That brings us back to the code in this PR. I pushed an update that fixes cases where there are no spaces. It seems to work OK with Japanese at least. I also reached out to the international team to see if there are any more gotchas with this approach. Once I’m confident in internationalization things, I can write some tests and will ask for final code review. Thanks all! |
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.
From an internationalization perspective, the obvious issue I see is with languages that have no spaces between words. But it seems you have a solution to that @ry5n
The only other thing is choosing an icon that is internationally understandable, especially in our major markets. Once we have a suggested icon we can run it past folks in our in-country teams to check this.
src/components/Link/Link.tsx
Outdated
@@ -1,8 +1,11 @@ | |||
import * as React from 'react'; | |||
|
|||
import {classNames} from '@shopify/react-utilities'; | |||
import {ChevronLeftMinor} from '@shopify/polaris-icons'; |
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 needs to be changed to ExternalSmallMinor
once this icon is included in Polaris Icons. I believe this is the last blocker for this PR.
OK folks, I think this is almost there. @dleroux I went back to your approach again, really dug into Snook’s article and codepen, and found a way to make it work with inline SVGs. I’m confident now this will work for multiple languages. The only real thing still blocking this is the correct icon isn’t available in Polaris Icons yet. |
Nice work! 🎩 looks good. Is the plan to roll this in now or wait until version 4? |
src/components/Link/Link.scss
Outdated
@@ -18,6 +19,26 @@ | |||
} | |||
} | |||
|
|||
// Prevents the icon from wrapping on its own to the next line |
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 think these comments can go, it's pretty self explanatory. Could even call this ExternalIconLockUp
if we want more clarity.
The external link icon merged this morning, so this is ready for final review 😀 I’d like to get this into the current version—@dleroux do you think it’s a breaking change? |
I guess |
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.
👍
WHY are these changes introduced?
Fixes Shopify/polaris-ux#146
WHAT is this pull request doing?
This PR takes the position that we should automatically do the right thing for accessibility whenever possible. It automatically adds screen reader text and an icon when the
external
prop istrue
.Unfortunately, implementation is complicated by CSS things, historical things, and international things (see comments below).
I’m looking for comments on this approach before going any further.
How to 🎩
🖥 Local development instructions
🗒 General tophatting guidelines
📄 Changelog guidelines
Copy-paste this code in
playground/Playground.tsx
:🎩 checklist