[EuiSkeletonLoading] Improve loading accessibility and bake in isLoading API handling#6562
Conversation
- 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
|
Preview documentation changes for this PR: https://eui.elastic.co/pr_6562/ |
1Copenut
left a comment
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Credit where credit is due, I got the aria-busy should be on the parent thing from Michael Yasonik here: #4814 (comment)
(or in this case, `EuiPanel` for looks
1Copenut
left a comment
There was a problem hiding this comment.
💯 LGTM! Steady a11y improvement for the win.
|
Preview documentation changes for this PR: https://eui.elastic.co/pr_6562/ |
- Missed in #6562 - Playground still isn't perfect; but good enough for now
* 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 <elizabet.oliveira@elastic.co> * Update src-docs/src/views/skeleton/skeleton_example.js Co-authored-by: Elizabet Oliveira <elizabet.oliveira@elastic.co> * Update src-docs/src/views/skeleton/skeleton_example.js Co-authored-by: Elizabet Oliveira <elizabet.oliveira@elastic.co> * 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 <elizabet.oliveira@elastic.co> Co-authored-by: Constance Chen <constance.chen.3@gmail.com> * 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 <andreareva@gmail.com> Co-authored-by: Elizabet Oliveira <elizabet.oliveira@elastic.co>
## Summary `eui@74.0.1` ⏩ `eui@74.1.0` ___ ## [`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 <42973632+kibanamachine@users.noreply.github.com>
Summary
closes #4814
This adds the loading accessibility detailed in #4814. I recommend following along by commit if possible.
EuiSkeletoncomponents now acceptisLoadingandchildrenprops, which automatically handles conditionally rendering the skeleton components vs. the loaded content (children) for consumers.Loaded {contentAriaLabel}announcement is now made wheneverisLoadingflips to false.QA
General checklist
@defaultif default values are missing) and playground toggles- [ ] 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