mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[bugfix] Fix a couple accessibility issues with :focus
elements (#3979)
* [bugfix/frontend] Fix accessibility/focus issues in settings + web ui * fix little error * tweaks
This commit is contained in:
@@ -65,20 +65,23 @@ export default function HeaderPermsOverview() {
|
||||
} = useGetHeaderAllowsQuery(NoArg, { skip: permType !== "allow" });
|
||||
|
||||
const itemToEntry = (perm: HeaderPermission) => {
|
||||
const onClick = () => {
|
||||
// When clicking on a header perm,
|
||||
// go to the detail view for perm.
|
||||
setLocation(`/${permType}s/${perm.id}`, {
|
||||
// Store the back location in
|
||||
// history so the detail view
|
||||
// can use it to return here.
|
||||
state: { backLocation: location }
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<dl
|
||||
key={perm.id}
|
||||
className="entry pseudolink"
|
||||
onClick={() => {
|
||||
// When clicking on a header perm,
|
||||
// go to the detail view for perm.
|
||||
setLocation(`/${permType}s/${perm.id}`, {
|
||||
// Store the back location in
|
||||
// history so the detail view
|
||||
// can use it to return here.
|
||||
state: { backLocation: location }
|
||||
});
|
||||
}}
|
||||
onClick={onClick}
|
||||
onKeyDown={e => e.key === "Enter" && onClick()}
|
||||
role="link"
|
||||
tabIndex={0}
|
||||
>
|
||||
|
@@ -211,21 +211,24 @@ function DraftListEntry({ permDraft, linkTo, backLocation }: DraftEntryProps) {
|
||||
|
||||
const title = `${permTypeUpper} ${domain}`;
|
||||
|
||||
const onClick = () => {
|
||||
// When clicking on a draft, direct
|
||||
// to the detail view for that draft.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`pseudolink domain-permission-draft entry ${permType}`}
|
||||
aria-label={title}
|
||||
title={title}
|
||||
onClick={() => {
|
||||
// When clicking on a draft, direct
|
||||
// to the detail view for that draft.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
}}
|
||||
onClick={onClick}
|
||||
onKeyDown={e => e.key === "Enter" && onClick()}
|
||||
role="link"
|
||||
tabIndex={0}
|
||||
>
|
||||
|
@@ -186,21 +186,24 @@ function ExcludeListEntry({ permExclude, linkTo, backLocation }: ExcludeEntryPro
|
||||
return <ErrorC error={new Error("id was undefined")} />;
|
||||
}
|
||||
|
||||
const onClick = () => {
|
||||
// When clicking on a exclude, direct
|
||||
// to the detail view for that exclude.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`pseudolink domain-permission-exclude entry`}
|
||||
aria-label={`Exclude ${domain}`}
|
||||
title={`Exclude ${domain}`}
|
||||
onClick={() => {
|
||||
// When clicking on a exclude, direct
|
||||
// to the detail view for that exclude.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
}}
|
||||
onClick={onClick}
|
||||
onKeyDown={e => e.key === "Enter" && onClick()}
|
||||
role="link"
|
||||
tabIndex={0}
|
||||
>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { useRef } from "react";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { useExportDomainListMutation } from "../../../lib/query/admin/domain-permissions/export";
|
||||
@@ -70,6 +70,11 @@ export default function ImportExportForm({ form, submitParse, parseResult }: Imp
|
||||
/* eslint-disable-next-line react-hooks/exhaustive-deps */
|
||||
}, [exportResult]);
|
||||
|
||||
const importFileRef = useRef<HTMLInputElement>(null);
|
||||
const importFileOnClick = () => {
|
||||
importFileRef.current?.click();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>Import / Export domain permissions</h1>
|
||||
@@ -101,7 +106,13 @@ export default function ImportExportForm({ form, submitParse, parseResult }: Imp
|
||||
showError={false}
|
||||
disabled={form.permType.value === undefined || form.permType.value.length === 0}
|
||||
/>
|
||||
<label className={`button with-icon${form.permType.value === undefined || form.permType.value.length === 0 ? " disabled" : ""}`}>
|
||||
<label
|
||||
className={`button with-icon${form.permType.value === undefined || form.permType.value.length === 0 ? " disabled" : ""}`}
|
||||
tabIndex={0}
|
||||
onClick={importFileOnClick}
|
||||
onKeyDown={e => e.key === "Enter" && importFileOnClick()}
|
||||
role="button"
|
||||
>
|
||||
<i className="fa fa-fw " aria-hidden="true" />
|
||||
Import file
|
||||
<input
|
||||
@@ -110,6 +121,7 @@ export default function ImportExportForm({ form, submitParse, parseResult }: Imp
|
||||
onChange={fileChanged}
|
||||
accept="application/json,text/plain,text/csv"
|
||||
disabled={form.permType.value === undefined || form.permType.value.length === 0}
|
||||
ref={importFileRef}
|
||||
/>
|
||||
</label>
|
||||
<b /> {/* grid filler */}
|
||||
|
@@ -109,21 +109,24 @@ export function SubscriptionListEntry({ permSub, linkTo, backLocation }: Subscri
|
||||
successfullyFetchedAtStr = new Date(successfullyFetchedAt).toDateString();
|
||||
}
|
||||
|
||||
const onClick = () => {
|
||||
// When clicking on a subscription, direct
|
||||
// to the detail view for that subscription.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`pseudolink domain-permission-subscription entry`}
|
||||
aria-label={ariaLabel}
|
||||
title={ariaLabel}
|
||||
onClick={() => {
|
||||
// When clicking on a subscription, direct
|
||||
// to the detail view for that subscription.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
}}
|
||||
onClick={onClick}
|
||||
onKeyDown={e => e.key === "Enter" && onClick()}
|
||||
role="link"
|
||||
tabIndex={0}
|
||||
>
|
||||
|
@@ -184,21 +184,24 @@ function ReportListEntry({ report, linkTo, backLocation }: ReportEntryProps) {
|
||||
const created = new Date(report.created_at).toLocaleString();
|
||||
const title = `${status}. @${target.account.acct} was reported by @${from.account.acct} on ${created}. Reason: "${comment}"`;
|
||||
|
||||
const onClick = () => {
|
||||
// When clicking on a report, direct
|
||||
// to the detail view for that report.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`pseudolink report entry${report.action_taken ? " resolved" : ""}`}
|
||||
aria-label={title}
|
||||
title={title}
|
||||
onClick={() => {
|
||||
// When clicking on a report, direct
|
||||
// to the detail view for that report.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
}}
|
||||
onClick={onClick}
|
||||
onKeyDown={e => e.key === "Enter" && onClick()}
|
||||
role="link"
|
||||
tabIndex={0}
|
||||
>
|
||||
|
@@ -139,21 +139,24 @@ function ApplicationListEntry({ app, linkTo, backLocation }: ApplicationListEntr
|
||||
const created = useCreated(app);
|
||||
const redirectURIs = useRedirectURIs(app);
|
||||
|
||||
const onClick = () => {
|
||||
// When clicking on an app, direct
|
||||
// to the detail view for that app.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`pseudolink application entry`}
|
||||
aria-label={`${app.name}`}
|
||||
title={`${app.name}`}
|
||||
onClick={() => {
|
||||
// When clicking on an app, direct
|
||||
// to the detail view for that app.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
}}
|
||||
onClick={onClick}
|
||||
onKeyDown={e => e.key === "Enter" && onClick()}
|
||||
role="link"
|
||||
tabIndex={0}
|
||||
>
|
||||
|
@@ -102,7 +102,6 @@ export default function Export({ exportStats }: { exportStats: AccountExportStat
|
||||
Following {exportStats.following_count} account{ exportStats.following_count !== 1 && "s" }
|
||||
</span>
|
||||
<MutationButton
|
||||
className="text-cutoff"
|
||||
label="Download following.csv"
|
||||
type="button"
|
||||
onClick={() => exportFollowing()}
|
||||
@@ -116,7 +115,6 @@ export default function Export({ exportStats }: { exportStats: AccountExportStat
|
||||
Followed by {exportStats.followers_count} account{ exportStats.followers_count !== 1 && "s" }
|
||||
</span>
|
||||
<MutationButton
|
||||
className="text-cutoff"
|
||||
label="Download followers.csv"
|
||||
type="button"
|
||||
onClick={() => exportFollowers()}
|
||||
@@ -130,7 +128,6 @@ export default function Export({ exportStats }: { exportStats: AccountExportStat
|
||||
Created {exportStats.lists_count} list{ exportStats.lists_count !== 1 && "s" }
|
||||
</span>
|
||||
<MutationButton
|
||||
className="text-cutoff"
|
||||
label="Download lists.csv"
|
||||
type="button"
|
||||
onClick={() => exportLists()}
|
||||
@@ -144,7 +141,6 @@ export default function Export({ exportStats }: { exportStats: AccountExportStat
|
||||
Blocking {exportStats.blocks_count} account{ exportStats.blocks_count !== 1 && "s" }
|
||||
</span>
|
||||
<MutationButton
|
||||
className="text-cutoff"
|
||||
label="Download blocks.csv"
|
||||
type="button"
|
||||
onClick={() => exportBlocks()}
|
||||
@@ -158,7 +154,6 @@ export default function Export({ exportStats }: { exportStats: AccountExportStat
|
||||
Muting {exportStats.mutes_count} account{ exportStats.mutes_count !== 1 && "s" }
|
||||
</span>
|
||||
<MutationButton
|
||||
className="text-cutoff"
|
||||
label="Download mutes.csv"
|
||||
type="button"
|
||||
onClick={() => exportMutes()}
|
||||
|
@@ -174,21 +174,24 @@ function ReqsListEntry({ req, linkTo, backLocation }: ReqsListEntryProps) {
|
||||
const ourContent = useContent(req.status);
|
||||
const theirContent = useContent(req.reply);
|
||||
|
||||
const onClick = () => {
|
||||
// When clicking on a request, direct
|
||||
// to the detail view for that request.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`pseudolink entry interaction-request`}
|
||||
aria-label={label}
|
||||
title={label}
|
||||
onClick={() => {
|
||||
// When clicking on a request, direct
|
||||
// to the detail view for that request.
|
||||
setLocation(linkTo, {
|
||||
// Store the back location in history so
|
||||
// the detail view can use it to return to
|
||||
// this page (including query parameters).
|
||||
state: { backLocation: backLocation }
|
||||
});
|
||||
}}
|
||||
onClick={onClick}
|
||||
onKeyDown={e => e.key === "Enter" && onClick()}
|
||||
role="link"
|
||||
tabIndex={0}
|
||||
>
|
||||
|
@@ -167,6 +167,7 @@ function ProfileForm({ data: profile }: ProfileFormProps) {
|
||||
<MutationButton
|
||||
className="delete-header-button"
|
||||
label="Delete header"
|
||||
tabIndex={0}
|
||||
disabled={noHeader}
|
||||
result={deleteHeaderRes}
|
||||
onClick={(e) => {
|
||||
@@ -179,7 +180,7 @@ function ProfileForm({ data: profile }: ProfileFormProps) {
|
||||
}}
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<fieldset className="file-input-with-image-description">
|
||||
<legend>Avatar</legend>
|
||||
<FileInput
|
||||
@@ -197,6 +198,7 @@ function ProfileForm({ data: profile }: ProfileFormProps) {
|
||||
<MutationButton
|
||||
className="delete-avatar-button"
|
||||
label="Delete avatar"
|
||||
tabIndex={0}
|
||||
disabled={noAvatar}
|
||||
result={deleteAvatarRes}
|
||||
onClick={(e) => {
|
||||
|
Reference in New Issue
Block a user