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

[EuiSkeletonLoading] Improve loading accessibility and bake in isLoading API handling #6562

Merged
merged 9 commits into from
Jan 31, 2023

Conversation

cee-chen
Copy link
Contributor

@cee-chen cee-chen commented Jan 31, 2023

Summary

closes #4814

This adds the loading accessibility detailed in #4814. I recommend following along by commit if possible.

  • All EuiSkeleton components now accept isLoading and children props, which automatically handles conditionally rendering the skeleton components vs. the loaded content (children) for consumers.
  • A Loaded {contentAriaLabel} announcement is now made whenever isLoading flips to false.

screencap

QA

General checklist

  • Checked in Chrome, Safari, Edge, and Firefox
  • Props have proper autodocs (using @default if default values are missing) and playground toggles
  • Added documentation
  • Added or updated jest and cypress tests
  • Checked for accessibility including keyboard-only and screenreader modes
  • A changelog entry exists and is marked appropriately

- [ ] Checked in both light and dark modes
- [ ] Checked in mobile
- [ ] Checked Code Sandbox works for any docs examples
- [ ] Checked for breaking changes and labeled appropriately
- [ ] Updated the Figma library counterpart

- for DRYing out correct accessibility attributes, wrappers, and a simpler loading API
+ update docs/example to how `isLoading`/`children` behavior
+ update docs/example to how `isLoading`/`children` behavior
…apper

+ update docs/example to how `isLoading`/`children` behavior
…apper

+ update docs/example to how `isLoading`/`children` behavior
- the new `aria-busy` wrapper appears to make the `z-index` workaround not work, so use `isolation` (https://developer.mozilla.org/en-US/docs/Web/CSS/isolation) instead to force the necessary stacking context
@cee-chen cee-chen requested a review from 1Copenut January 31, 2023 02:43
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_6562/

Copy link
Contributor

@1Copenut 1Copenut left a comment

Choose a reason for hiding this comment

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

This is such a boon improvement @Cee. I've been testing this morning with various browsers and VoiceOver. Have one small change in the src-docs example for Skeleton Loading to make axe happy.

For whatever reason, Safari + VO isn't announcing the content loaded when it's just text, title, or icons. If we have mixed content or are wrapping multiples with the single EuiSkeletonLoading it works perfectly. Firefox + VO works perfectly all around.

I'm bringing it to our team meeting, but my hunch is to launch, verify with other screen readers, and course correct if necessary.

{...rest}
>
{isLoading ? (
React.cloneElement(loadingContent, loadingProps)
Copy link
Contributor

Choose a reason for hiding this comment

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

This pattern is just the ticket. Controlling the aria-busy with the parent, then adding the relevant ARIA props to a consumer-passed child component.

I had a thought this could get us into a situation where axe-core throws about a nested element role, but MDN bailed me out with this gem on the progressbar entry:

All descendants are presentational

There are some types of user interface components that, when represented in a platform accessibility API, can only contain text. Accessibility APIs do not have a way of representing semantic elements contained in a progressbar. To deal with this limitation, browsers, automatically apply role presentation to all descendant elements of any progressbar element as it is a role that does not support semantic children.

This nullifies the implicit roles of child elements, making elements and content inert.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Credit where credit is due, I got the aria-busy should be on the parent thing from Michael Yasonik here: #4814 (comment)

src-docs/src/views/skeleton/skeleton_loading.tsx Outdated Show resolved Hide resolved
(or in this case, `EuiPanel` for looks
Copy link
Contributor

@1Copenut 1Copenut left a comment

Choose a reason for hiding this comment

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

💯 LGTM! Steady a11y improvement for the win.

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_6562/

@cee-chen cee-chen merged commit 364238c into elastic:feature/skeletons Jan 31, 2023
@cee-chen cee-chen deleted the skeletons-aria-attrs branch January 31, 2023 19:21
cee-chen added a commit that referenced this pull request Jan 31, 2023
- Missed in #6562

- Playground still isn't perfect; but good enough for now
cee-chen added a commit that referenced this pull request Jan 31, 2023
* EuiSkeleton components (#6502)

* Setup EuiSkeleton files and folders structure

* Moved Skeleton under the Display side menu category

* Component variants setup

* feat: skeleton setup [text, rect, circle]

* feat: added skeleton item draft and other minors

* chore: renamed sizes

* feat: added Heading in favor of Rect component

* Update src-docs/src/views/skeleton/skeleton_example.js

Co-authored-by: Elizabet Oliveira <[email protected]>

* Update src-docs/src/views/skeleton/skeleton_example.js

Co-authored-by: Elizabet Oliveira <[email protected]>

* Update src-docs/src/views/skeleton/skeleton_example.js

Co-authored-by: Elizabet Oliveira <[email protected]>

* chore: wrapped p with EuiText and indentation

* chore: removed useless styles

* chore: centralized and renamed skeleton animation keyfram

* refactor: renamed euiSkeletonHeading to euiSkeletonTitle and updated sizes with euiTitle ones

* chore: renamed EuiSkeletonItem to EuiSkeletonRectangle

* Remove hard-coded `euiSkeletonTitleStyles` heights map

- in favor of calling `euiTitle`'s font utils and grabbing `lineHeight` directly from it

* [docs] Add EuiSwitch toggle to EuiSkeletonTitle tests

- this toggle help demonstrates to consumers how to conditionally switch from loading to non-loading components, and also allows us to test heights

* Add `size` prop to `EuiSkeletonText`

+ add calculations & offsets to account for text scale

+ update docs to allow changing size & toggle between text to test visual behavior

* [docs] Add loading toggle for EuiSkeletonCircle

+ prettier fixes

* [PR feedback] Fix incorrect BEM naming; remove extra modifier classes

- BEM: `__` should only be used for children/descendants, and these are parent-level styles and should use regular camelCasing

- modifier classes removal: we're moving away from setting these extra CSS classes, which do not have any actual CSS tied to them (since we're using Emotion CSS-in-JS instead). The top-level className remains as an API for consumers to hook into for overrides if needed.

* [PR feedback] DRY out all `aria`/a11y attributes to reusable helper

- not all components were correctly receiving all the aria attrs they should have been - this helper fixes that

* [PR feedback] Rename` _skeleton` to `utils`, DRY out repeated gradient CSS

- `utils` better matches naming/architecture convention in other components (+ ignore i18n complaint)

+ tweak gradient size and animation for circle and rectangle components to look a bit better

+ rename global animation to a more generic name/usage

* [PR feedback] DRY out repeated CSS between modifiers
- should exist in the base styles instead

+ bonus - DRY out `logicalSizeCSS` to only require 1 input if both sides are the same

* [PR feedback] Avoid dynamic wildcard Emotion classes - use `style` instead

The reason for this is performance - Emotion generates a completely new hash/className for every single possible permutation of width/height passed to it. We want to avoid this for wildcard prop-based styles and use inline styles instead

* [PR feedback] Improve/add unit tests

+ cover all props

+ prefer RTL over Enzyme (part of ongoing migration)

+ fix type issue found during testing

* [docs] Add toggle to EuiSkeletonRectangle example

* [PR feedback] EuiSkeletonRectangle tweaks

- allow numbers as well as strings - now that we're using inline `style`s for the dimensions, React accepts numbers as well (which matches EuiImage API)

- remove image URI in favor of a picsum link

- set width/height on img to prevent page jumping

* [PR feedback] Tweak EuiSkeletonText typing

- for whatever reason, using `|` prints the line numbers in non-ascending order in the props table - using an array and `as const` fixes this, and is reusable in tests

* [PR feedback] Convert docs files to Typescript

+ improve mobile display of demos

* [PR feedback] Documentation copy + order

- move EuiSkeletonCircle slightly lower in docs order - EuiSkeletonText is likely going to be more popular since it already exists

- misc copy tweaks

* [Docs] Set up playgrounds

* DRY out aria-label further

- since `euiLoadingStrings.ariaLabel` already exists, just reuse that instead of making our translators re-translate the same string

* Add fix for Safari workaround

- note: this is already broken on prod as well for `EuiLoadingContent`

* Changelog

* chore: comment typo and zero value for border radius

---------

Co-authored-by: Elizabet Oliveira <[email protected]>
Co-authored-by: Constance Chen <[email protected]>

* Design review (#6560)

* Deprecate `EuiLoadingContent` in favor of `EuiSkeletonText` (#6557)

* Deprecate EuiLoadingContent + dogfood EuiSkeletonText

* Remove unnecessary tests

- leave a basic `is rendered` test in just to confirm the content, but should be deleted in the future

* Update documentation with deprecation notice

* changelog

* Fix Emotion styles var name

* [EuiSkeletonLoading] Improve loading accessibility and bake in `isLoading` API handling (#6562)

* Create reusable `EuiSkeletonLoading` component

- for DRYing out correct accessibility attributes, wrappers, and a simpler loading API

* Convert `EuiSkeletonText` to dogfood new `EuiSkeletonLoading` wrapper

+ update docs/example to how `isLoading`/`children` behavior

* Convert `EuiSkeletonTitle` to dogfood new `EuiSkeletonLoading` wrapper

+ update docs/example to how `isLoading`/`children` behavior

* Convert `EuiSkeletonRectangle` to dogfood new `EuiSkeletonLoading` wrapper

+ update docs/example to how `isLoading`/`children` behavior

* Convert `EuiSkeletonRectangle` to dogfood new `EuiSkeletonLoading` wrapper

+ update docs/example to how `isLoading`/`children` behavior

* Add docs example + a11y callout for `EuiSkeletonLoading`

* Fix annoying Safari bug popping up again

- the new `aria-busy` wrapper appears to make the `z-index` workaround not work, so use `isolation` (https://developer.mozilla.org/en-US/docs/Web/CSS/isolation) instead to force the necessary stacking context

* changelog

* [PR feedback] use `div` instead of `section`

(or in this case, `EuiPanel` for looks

* [PR feedback] Add `children` to playground

- Missed in #6562

- Playground still isn't perfect; but good enough for now

* Tweak default `EuiSkeletonCircle` size to match default `EuiAvatar` size

---------

Co-authored-by: Andrea Della Valle <[email protected]>
Co-authored-by: Elizabet Oliveira <[email protected]>
cee-chen pushed a commit to elastic/kibana that referenced this pull request Feb 9, 2023
## Summary

`[email protected]` ⏩ `[email protected]`

___

## [`74.1.0`](https://github.com/elastic/eui/releases/tag/v74.1.0)

- Added new `EuiSkeletonText`, `EuiSkeletonTitle`, `EuiSkeletonCircle`,
and `EuiSkeletonRectangle` components
([#6502](elastic/eui#6502))
- Updated `EuiSuperSelect` screen reader instructions to be more
specific ([#6549](elastic/eui#6549))
- Added `error` and updated `alert` glyphs to `EuiIcon`
([#6550](elastic/eui#6550))
- All `EuiSkeleton` components now accept an `isLoading` flag and
`children`, which automatically handles conditionally rendering loading
skeletons vs. loaded content (`children`)
([#6562](elastic/eui#6562))
- All `EuiSkeleton` components now accept a `contentAriaLabel` prop,
which more meaningfully describes the loaded content to screen readers
([#6562](elastic/eui#6562))
- Updated `EuiPopover` screen reader instructions for mobile and click
behaviors ([#6567](elastic/eui#6567))

**Bug fixes**

- Fixed `EuiCard` to ensure `onClick` method only runs once when `title`
contains a React node
([#6551](elastic/eui#6551))

**Deprecations**

- Deprecated `EuiLoadingContent` - use `EuiSkeletonText` instead
([#6557](elastic/eui#6557))

---------

Co-authored-by: Kibana Machine <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants