a11y - fix iframes without title (#7614)

* iframe title in AppTile

Signed-off-by: Kerry Archibald <kerrya@element.io>

* iframe title in hostSignupDialog

Signed-off-by: Kerry Archibald <kerrya@element.io>

* iframe title in MFileBody

* iframe titles in modal widget and int man

Signed-off-by: Kerry Archibald <kerrya@element.io>

* enable jsx-a11y/iframe-has-title rule

Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
Kerry 2022-01-24 15:07:54 +01:00 committed by GitHub
parent d60b234b75
commit 26e1570dd6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 17 additions and 4 deletions

View file

@ -45,7 +45,6 @@ module.exports = {
"jsx-a11y/alt-text": "off", "jsx-a11y/alt-text": "off",
"jsx-a11y/aria-activedescendant-has-tabindex": "off", "jsx-a11y/aria-activedescendant-has-tabindex": "off",
"jsx-a11y/click-events-have-key-events": "off", "jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/iframe-has-title": "off",
"jsx-a11y/interactive-supports-focus": "off", "jsx-a11y/interactive-supports-focus": "off",
"jsx-a11y/label-has-associated-control": "off", "jsx-a11y/label-has-associated-control": "off",
"jsx-a11y/media-has-caption": "off", "jsx-a11y/media-has-caption": "off",

View file

@ -281,6 +281,12 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
} }
{ !this.state.error && { !this.state.error &&
<iframe <iframe
title={_t(
"Upgrade to %(hostSignupBrand)s",
{
hostSignupBrand: this.config.brand,
},
)}
src={this.config.url} src={this.config.url}
ref={this.iframeRef} ref={this.iframeRef}
sandbox="allow-forms allow-scripts allow-same-origin allow-popups" sandbox="allow-forms allow-scripts allow-same-origin allow-popups"

View file

@ -198,6 +198,7 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
</div> </div>
<div> <div>
<iframe <iframe
title={this.widget.name}
ref={this.appFrame} ref={this.appFrame}
sandbox="allow-forms allow-scripts allow-same-origin" sandbox="allow-forms allow-scripts allow-same-origin"
src={widgetUrl} src={widgetUrl}

View file

@ -46,6 +46,7 @@ import { IApp } from "../../../stores/WidgetStore";
import { WidgetLayoutStore, Container } from "../../../stores/widgets/WidgetLayoutStore"; import { WidgetLayoutStore, Container } from "../../../stores/widgets/WidgetLayoutStore";
import { OwnProfileStore } from '../../../stores/OwnProfileStore'; import { OwnProfileStore } from '../../../stores/OwnProfileStore';
import { UPDATE_EVENT } from '../../../stores/AsyncStore'; import { UPDATE_EVENT } from '../../../stores/AsyncStore';
import WidgetUtils from '../../../utils/WidgetUtils';
interface IProps { interface IProps {
app: IApp; app: IApp;
@ -471,6 +472,9 @@ export default class AppTile extends React.Component<IProps, IState> {
<Spinner message={_t("Loading...")} /> <Spinner message={_t("Loading...")} />
</div> </div>
); );
const widgetTitle = WidgetUtils.getWidgetName(this.props.app);
if (this.sgWidget === null) { if (this.sgWidget === null) {
appTileBody = ( appTileBody = (
<div className={appTileBodyClass} style={appTileBodyStyles}> <div className={appTileBodyClass} style={appTileBodyStyles}>
@ -509,6 +513,7 @@ export default class AppTile extends React.Component<IProps, IState> {
<div className={appTileBodyClass + (this.state.loading ? 'mx_AppLoading' : '')} style={appTileBodyStyles}> <div className={appTileBodyClass + (this.state.loading ? 'mx_AppLoading' : '')} style={appTileBodyStyles}>
{ this.state.loading && loadingElement } { this.state.loading && loadingElement }
<iframe <iframe
title={widgetTitle}
allow={iframeFeatures} allow={iframeFeatures}
ref={this.iframeRefChange} ref={this.iframeRefChange}
src={this.sgWidget.embedUrl} src={this.sgWidget.embedUrl}

View file

@ -272,6 +272,8 @@ export default class MFileBody extends React.Component<IProps, IState> {
be suitable to just remove this bit of code. be suitable to just remove this bit of code.
*/ } */ }
<iframe <iframe
aria-hidden
title={presentableTextForFile(this.content, _t("Attachment"), true, true)}
src={url} src={url}
onLoad={() => this.downloadFile(this.fileName, this.linkText)} onLoad={() => this.downloadFile(this.fileName, this.linkText)}
ref={this.iframe} ref={this.iframe}

View file

@ -101,6 +101,6 @@ export default class IntegrationManager extends React.Component<IProps, IState>
); );
} }
return <iframe src={this.props.url} onError={this.onError} />; return <iframe title={_t("Integration manager")} src={this.props.url} onError={this.onError} />;
} }
} }

View file

@ -1256,6 +1256,7 @@
"Connecting to integration manager...": "Connecting to integration manager...", "Connecting to integration manager...": "Connecting to integration manager...",
"Cannot connect to integration manager": "Cannot connect to integration manager", "Cannot connect to integration manager": "Cannot connect to integration manager",
"The integration manager is offline or it cannot reach your homeserver.": "The integration manager is offline or it cannot reach your homeserver.", "The integration manager is offline or it cannot reach your homeserver.": "The integration manager is offline or it cannot reach your homeserver.",
"Integration manager": "Integration manager",
"Private (invite only)": "Private (invite only)", "Private (invite only)": "Private (invite only)",
"Only invited people can join.": "Only invited people can join.", "Only invited people can join.": "Only invited people can join.",
"Anyone can find and join.": "Anyone can find and join.", "Anyone can find and join.": "Anyone can find and join.",
@ -2580,6 +2581,7 @@
"%(hostSignupBrand)s Setup": "%(hostSignupBrand)s Setup", "%(hostSignupBrand)s Setup": "%(hostSignupBrand)s Setup",
"Maximise dialog": "Maximise dialog", "Maximise dialog": "Maximise dialog",
"Minimise dialog": "Minimise dialog", "Minimise dialog": "Minimise dialog",
"Upgrade to %(hostSignupBrand)s": "Upgrade to %(hostSignupBrand)s",
"Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.": "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.", "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.": "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.",
"Verifying this user will mark their session as trusted, and also mark your session as trusted to them.": "Verifying this user will mark their session as trusted, and also mark your session as trusted to them.", "Verifying this user will mark their session as trusted, and also mark your session as trusted to them.": "Verifying this user will mark their session as trusted, and also mark your session as trusted to them.",
"Verify this device to mark it as trusted. Trusting this device gives you and other users extra peace of mind when using end-to-end encrypted messages.": "Verify this device to mark it as trusted. Trusting this device gives you and other users extra peace of mind when using end-to-end encrypted messages.", "Verify this device to mark it as trusted. Trusting this device gives you and other users extra peace of mind when using end-to-end encrypted messages.": "Verify this device to mark it as trusted. Trusting this device gives you and other users extra peace of mind when using end-to-end encrypted messages.",
@ -2782,7 +2784,6 @@
"Missing session data": "Missing session data", "Missing session data": "Missing session data",
"Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.", "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.",
"Your browser likely removed this data when running low on disk space.": "Your browser likely removed this data when running low on disk space.", "Your browser likely removed this data when running low on disk space.": "Your browser likely removed this data when running low on disk space.",
"Integration manager": "Integration manager",
"Find others by phone or email": "Find others by phone or email", "Find others by phone or email": "Find others by phone or email",
"Be found by phone or email": "Be found by phone or email", "Be found by phone or email": "Be found by phone or email",
"Use bots, bridges, widgets and sticker packs": "Use bots, bridges, widgets and sticker packs", "Use bots, bridges, widgets and sticker packs": "Use bots, bridges, widgets and sticker packs",
@ -3012,7 +3013,6 @@
"Send a Direct Message": "Send a Direct Message", "Send a Direct Message": "Send a Direct Message",
"Explore Public Rooms": "Explore Public Rooms", "Explore Public Rooms": "Explore Public Rooms",
"Create a Group Chat": "Create a Group Chat", "Create a Group Chat": "Create a Group Chat",
"Upgrade to %(hostSignupBrand)s": "Upgrade to %(hostSignupBrand)s",
"Open dial pad": "Open dial pad", "Open dial pad": "Open dial pad",
"Public community": "Public community", "Public community": "Public community",
"Private community": "Private community", "Private community": "Private community",