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

Support SVGs as images in notification components #1720

Merged
merged 7 commits into from
Sep 12, 2022

Conversation

connor-baer
Copy link
Member

Closes #1707.

Approach and changes

  • Support SVGs as images in the NotificationFullscreen and NotificationModal components

Definition of done

  • Development completed
  • Reviewers assigned
  • Unit and integration tests
  • Meets minimum browser support
  • Meets accessibility requirements

@connor-baer connor-baer requested a review from a team as a code owner August 19, 2022 19:56
@connor-baer connor-baer requested review from robinmetral and removed request for a team August 19, 2022 19:56
@vercel
Copy link

vercel bot commented Aug 19, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
oss-circuit-ui ✅ Ready (Inspect) Visit Preview Sep 9, 2022 at 3:24PM (UTC)

@changeset-bot
Copy link

changeset-bot bot commented Aug 19, 2022

🦋 Changeset detected

Latest commit: 12984db

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sumup/circuit-ui Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov
Copy link

codecov bot commented Aug 19, 2022

Codecov Report

Merging #1720 (12984db) into main (5543831) will decrease coverage by 0.00%.
The diff coverage is 91.30%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1720      +/-   ##
==========================================
- Coverage   91.33%   91.32%   -0.01%     
==========================================
  Files         170      170              
  Lines        3624     3644      +20     
  Branches     1200     1251      +51     
==========================================
+ Hits         3310     3328      +18     
  Misses        296      296              
- Partials       18       20       +2     
Impacted Files Coverage Δ
...components/NotificationModal/NotificationModal.tsx 92.85% <84.61%> (-4.02%) ⬇️
.../NotificationFullscreen/NotificationFullscreen.tsx 100.00% <100.00%> (ø)
...es/circuit-ui/components/Pagination/Pagination.tsx 81.57% <0.00%> (ø)

Copy link
Contributor

@robinmetral robinmetral left a comment

Choose a reason for hiding this comment

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

Thank you! 💙

const Svg = image;
return (
<div css={imageStyles}>
<Svg css={svgStyles} />
Copy link
Contributor

Choose a reason for hiding this comment

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

One downside of this approach, compared to the ImageProps one, is that there's no required alternative text for the asset. On the other hand, for notification SVGs (at least in the SumUp context), it's likely that the asset will only be illustrative and should have aria-hidden="true".

Were you thinking of leaving this concern to developers?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point! I actually didn't think of that 🙈

Would you prefer an optional alt text prop or simply adding aria-hidden="true"/role="presentation" by default? (I haven't seen any use cases where an alt text would have been necessary)

Copy link
Contributor

Choose a reason for hiding this comment

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

Would you prefer an optional alt text prop or simply adding aria-hidden="true"/role="presentation" by default?

My thoughts 👇

Decorative media (by default)

Adding aria-hidden or a presentation role to the SVG is probably the "cleanest" and would work in most (all?) cases today, but I'm not sure we can/should assume that SVGs will always be decorative.

If they're only decorative by default, this might be a good option. What API would you suggest to override the default and add alternative text or a label? The option I'm thinking of is quite verbose.

Also, if we go down that route, I'd also make the img decorative (for consistency).

Alt text

I like this option as well but it might also make the API a bit messy—at least with the option i'm thinking of:

type Props = {
  image?: {
    src?: string,
    children?: FC<SVGProps<SVGSVGElement>>,
    alt: string, // must always be provided, even if it's `""` for a decorative image
  },
  /* etc */
}

My thinking:

  • This is nice because alternative text is always required, no matter if the actual asset is an img or an svg
  • ...on the other hand alt isn't appropriate on an svg, so internally we should check which of the two elements is rendered and either use alt or aria-label
  • BUT! I really don't like APIs like this where you could pass either an src or children—it makes it confusing. But it would be equally confusing to have something like src: string | FC<SVGProps<SVGSVGElement>>
  • ...and finally I don't like how this is moving away from the ImageProps

Did you have other APIs in mind? Right now I'm not convinced by any solution 😅

Copy link
Member Author

@connor-baer connor-baer Aug 22, 2022

Choose a reason for hiding this comment

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

Alright, so you want to have the option to provide alternative text, but by default, the image/illustration should be hidden from screen reader users.

alt isn't appropriate on an svg, so internally we should check which of the two elements is rendered and either use alt or aria-label

Yes. I would stick to alt as the prop name as the aria-label is also "alternative text" and developers are already familiar with its purpose.

I would call the SVG something other than children since that would imply a ReactNode, but we're expecting a ReactElement. So element perhaps? Or svg? 🤔

I don't like how this is moving away from the ImageProps

Eh, I feel you, but I think there's no better approach to this.

So, we end up with:

type Props = {
  image?: {
    src: string,
    alt?: string, // defaults to `""`
  } | {
	children: FC<SVGProps<SVGSVGElement>>,
    alt?: string, // defaults to `""`
  },
  /* etc */
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm thinking of going for this:

type Props = {
  image: ImageProps | { svg: FC<SVGProps<SVGSVGElement>>, alt: string },
  /* etc */
}

Reasoning here is that although the image will often be decorative, I'd still like to consistently require the alt prop when we render graphics across Circuit UI, just to make 100% sure that developers think about it. It'll often be alt="" and that's okay 🙂

Also the naming "svg" is a good choice here IMO: we need the element to be an SVG so I think it doesn't make sense to make the naming broader (e.g. "element").

Let me know if you have concerns!

<div
class="circuit-1"
>
<svg
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this would get announced "image"

Copy link
Contributor

Choose a reason for hiding this comment

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

Should be solved with aria-hidden that is passed to an svg element if the alt value is "". Will verify with manual testing

Copy link
Contributor

Choose a reason for hiding this comment

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

Chrome x VoiceOver:

img svg
alt
Screen.Recording.2022-09-09.at.17.48.37.mov
Screen.Recording.2022-09-09.at.17.54.43.mov
!alt
Screen.Recording.2022-09-09.at.17.51.21.mov
Screen.Recording.2022-09-09.at.17.57.00.mov

TL;DR: everything looks good with this user agent. I think we can roll with it

…tionFullscreen.spec.tsx

Co-authored-by: Robin Métral <robin.metral@sumup.com>
@robinmetral
Copy link
Contributor

FYI I'm picking this up 🙂 Following-up in the existing discussions above

Robin Métral added 4 commits September 9, 2022 17:15
This also improves tests and type descriptions.
This also improves tests and type descriptions.
Copy link
Member Author

@connor-baer connor-baer left a comment

Choose a reason for hiding this comment

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

Approved! ✅ (can't do it properly because I originally opened the PR)

@robinmetral
Copy link
Contributor

Thanks 💙 I'll merge and release this on Monday. Thank you for your contributions to this!

@robinmetral robinmetral merged commit d3c6165 into main Sep 12, 2022
@robinmetral robinmetral deleted the feature/notification-image-svg branch September 12, 2022 08:05
@connor-baer connor-baer mentioned this pull request Sep 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for ReactNode so an SVG component can be used for the image
2 participants