-
Notifications
You must be signed in to change notification settings - Fork 72
[terra-embedded-content-consumer] - Show focus indicator on iframe of the embedded content when it has focus #1827
Conversation
…frame's contentWindow
…updated examples, add style scss modules
…rame when in focus
Co-authored-by: Saad Adnan <[email protected]>
@@ -5,6 +5,9 @@ | |||
* Added | |||
* Added documentation for FlowsheetDataGrid in `terra-data-grid`. | |||
|
|||
* Updated | |||
* Updated examples, and tests to show the visual focus indicator on the iframe of the embedded content |
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.
nit: We can add a .
at the EOL.
@@ -4,14 +4,10 @@ import { Consumer } from 'xfc'; | |||
import '../providers/EmbeddedContentConsumerCommon.module.scss'; | |||
|
|||
Consumer.init(); | |||
|
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.
nit: can we keep the newline here or remove it from the other doc files as well?
@@ -7,7 +7,8 @@ const cx = classNames.bind(styles); | |||
|
|||
const Provider = () => ( | |||
<ProviderTestTemplate> | |||
<div className={cx('content-wrapper')}> | |||
{/* eslint-disable-next-line */} | |||
<div className={cx('content-wrapper')} tabIndex="0" style={{ outline: 'none' }}> |
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.
nit: can we add a new class to use here that includes the outline style?
Allowing the consumers to set a "hasActionableContent" prop (that is named for intent rather than for result) would be good to allow consumers to disable the focus when they KNOW there is actionable content within the frame. BUT, I would not want the default to be the frame doesn't receive focus - would have to default to FALSE. That would provide a more accessible experience out of the box, even though it may not always be perfect. |
@kolkheang if we add the "hasActionableContent" prop, in addition to removing the visible focus indicator, can we also remove the tabindex="0" to ensure keyboard focus is not set on the container? |
Please disregard my comments about adding a "hasActionableContent" prop. @kolkheang and I discussed it more and determined this would be moot. From an accessibility perspective, we must show a visible focus indicator if we have something with a tabindex="0" Adding the actionable content prop would have potentially allowed for failures which we do not want to do. As is, the current behavior that Kol provides ensures (as best as possible) that the container can receive keyboard focus when there is scrolling AND that the container has the required visible focus indicator to meet WCAG 2.4.7 Focus Visible criterion. |
}, | ||
"dependencies": { | ||
"classnames": "^2.2.5", | ||
"prop-types": "^15.5.8" | ||
"prop-types": "^15.5.8", | ||
"style-to-object": "^0.4.2" |
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.
We should not need to add this third-party dependency.
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.
Good call. With the current way, there is just 1 style for focus outline
, and one style for blur outline
and we have two variables for these. We can set the value for each into the frame's style directly. Previously, I was thinking that we could set multiple style attributes for focus or blur.
$blur-outline: var(--terra-embedded-content-consumer-blur-outline, none); | ||
$focus-outline: var(--terra-embedded-content-consumer-focus-outline, 2px dashed #000); | ||
|
||
:export { | ||
/* stylelint-disable property-no-unknown */ | ||
blurOutline: $blur-outline; | ||
focusOutline: $focus-outline; | ||
} |
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.
You should be able to set the styles using classes. I don't think that this is the correct implementation.
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.
These are not for the classes to be applied to an html element like we normally do.
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.
You would add the class to the iFrame element.
this.xfcFrame?.iframe?.contentWindow?.addEventListener('focus', () => { | ||
const styleObj = parse(focusStyleStr); | ||
Object.entries(styleObj).forEach(([key, value]) => { | ||
this.xfcFrame.iframe.style[key] = value; | ||
}); | ||
}, true); | ||
|
||
// Listen for blur event and callback function to apply the style | ||
this.xfcFrame?.iframe?.contentWindow?.addEventListener('blur', () => { | ||
const styleObj = parse(blurStyleStr); | ||
Object.entries(styleObj).forEach(([key, value]) => { | ||
this.xfcFrame.iframe.style[key] = value; | ||
}); | ||
}, true); |
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.
Instead of this logic, you should be able to use the ":focus" psuedo class.
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.
Can you give an example on how to setup the style and apply to the iframe's style?
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.
Like this?
iframe:focus {
outline: 2px dashed #000;
}
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 would think that your iFrame would have an associated class name or id for styling. However, it would be a similar concept to what you have described here, yes.
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.
The :focus pseudo-class isn't working for iframe. I'll check to see if we can update the classname on the fly for switching the style.
// Cover other scenario where xfc frame style doesn't apply | ||
// such as when `srcdoc` attribute is used which doesn't work | ||
// within xfc's JSONRPC communication. | ||
this.xfcFrame?.iframe?.contentWindow?.addEventListener('focus', () => { |
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.
The contentWindow gives you a reference to the window for the embedded content. You should be able to use document.documentElement (HTML tag) or document.body to handle the logic as necessary.
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.
Yeah, I'd like to handle the focus within the iframe element though, not everywhere else in the document body.
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 you can handle by styling the iFrame element. How are you giving focus to your iFrame? Did you set a tabIndex?
:local { | ||
.clinical-lowlight-theme { | ||
--terra-embedded-content-consumer-focus-outline: 2px dashed #b2b5b6; | ||
--terra-embedded-content-consumer-blur-outline: none; |
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.
We shouldn't need a blur outline style. That should just be the normal state of the element.
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.
Are you saying we can hard-code outline: none
to remove the style from the frame when there is no focus anymore? Because we set the outline
style when there is focus. And if we don't remove that style, it stays.
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.
No, I am saying that you would have CSS for the normal state. When the element is not focused, that CSS will no longer be applied.
Based on the meeting several of us had on Monday, there is additional changes that are needed. The changes are specifically related to checking whether the embedded document (in the iframe) has any focusable/interactable element or not and if not (using I'll be issuing a new PR with these additional changes and include the existing change on this PR. I'll close this PR out for now. |
Summary
Show visual focus indicator on the frame when the embedded content has focus. This allows keyboard only users to see where focus is and use keyboard to scroll the embedded content when content is not fully visible within the viewport.
What was changed:
Showing outline style on the frame when it has focus and remove the outline style when it's not in focus (blur)
Why it was changed:
It's necessary for keyboard only users to see where the focus is and give users indication that while focus is on the frame, they can use arrow keys to scroll the content inside the frame when needed (if content isn't fully visible and scrolling is enabled)
Testing
This change was tested using:
Reviews
In addition to engineering reviews, this PR needs:
Additional Details
This library depends on the changes in xfc library which is currently under review with oracle-samples/xfc#95
Doc Site: https://engineering.cerner.com/terra-framework/pull/1827/
Screen Recording using keyboard navigation with tab key:
https://github.com/cerner/terra-framework/assets/3170314/71e86961-94a2-4ea9-bf53-a55e25c6bed6
This PR resolves:
UXPLATFORM-9564
Thank you for contributing to Terra.
@cerner/terra