fix: migrate all uses of visuallyHidden (#22001)

Replace all usages of MUI's `visuallyHidden` utility from `@mui/utils`
with Tailwind's `sr-only` class. Both produce identical CSS, so this is
a no-op behaviorally -- just removes another MUI dependency from the
codebase. Also updates the accessibility example in the frontend
contributing docs to match.
This commit is contained in:
Jake Howell
2026-02-09 23:17:03 +11:00
committed by GitHub
parent 95b3bc9c7a
commit f11a8086b0
9 changed files with 9 additions and 23 deletions
+2 -6
View File
@@ -220,16 +220,12 @@ screen-readers; a placeholder text value is not enough for all users.
When possible, make sure that all image/graphic elements have accompanying text
that describes the image. `<img />` elements should have an `alt` text value. In
other situations, it might make sense to place invisible, descriptive text
inside the component itself using MUI's `visuallyHidden` utility function.
inside the component itself using Tailwind's `sr-only` class.
```tsx
import { visuallyHidden } from "@mui/utils";
<Button>
<GearIcon />
<Box component="span" sx={visuallyHidden}>
Settings
</Box>
<span className="sr-only">Settings</span>
</Button>;
```
-1
View File
@@ -49,7 +49,6 @@
"@monaco-editor/react": "4.7.0",
"@mui/material": "5.18.0",
"@mui/system": "5.18.0",
"@mui/utils": "5.17.1",
"@mui/x-tree-view": "7.29.10",
"@radix-ui/react-avatar": "1.1.11",
"@radix-ui/react-checkbox": "1.3.3",
-3
View File
@@ -61,9 +61,6 @@ importers:
'@mui/system':
specifier: 5.18.0
version: 5.18.0(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)
'@mui/utils':
specifier: 5.17.1
version: 5.17.1(@types/react@19.2.7)(react@19.2.2)
'@mui/x-tree-view':
specifier: 7.29.10
version: 7.29.10(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
+1 -2
View File
@@ -1,7 +1,6 @@
import { css, Global, useTheme } from "@emotion/react";
import InputAdornment from "@mui/material/InputAdornment";
import TextField, { type TextFieldProps } from "@mui/material/TextField";
import { visuallyHidden } from "@mui/utils";
import { Button } from "components/Button/Button";
import { ExternalImage } from "components/ExternalImage/ExternalImage";
import { Loader } from "components/Loader/Loader";
@@ -116,7 +115,7 @@ export const IconField: FC<IconFieldProps> = ({
- Except we don't do it when running tests, because Jest doesn't define
`IntersectionObserver`, and it would make them slower anyway. */}
{process.env.NODE_ENV !== "test" && (
<div css={{ ...visuallyHidden }}>
<div className="sr-only" aria-hidden="true">
<Suspense>
<EmojiPicker onEmojiSelect={() => {}} />
</Suspense>
@@ -1,5 +1,4 @@
import Skeleton from "@mui/material/Skeleton";
import { visuallyHidden } from "@mui/utils";
import type * as TypesGen from "api/typesGenerated";
import { Abbr } from "components/Abbr/Abbr";
import { Button } from "components/Button/Button";
@@ -74,7 +73,7 @@ export const ProxyMenu: FC<ProxyMenuProps> = ({ proxyContextValue }) => {
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="lg">
<span css={{ ...visuallyHidden }}>
<span className="sr-only">
Latency for {selectedProxy?.display_name ?? "your region"}
</span>
@@ -1,7 +1,6 @@
import type { Interpolation, Theme } from "@emotion/react";
import Drawer from "@mui/material/Drawer";
import IconButton from "@mui/material/IconButton";
import { visuallyHidden } from "@mui/utils";
import { JobError } from "api/queries/templates";
import type { TemplateVersion } from "api/typesGenerated";
import { Button } from "components/Button/Button";
@@ -46,7 +45,7 @@ export const BuildLogsDrawer: FC<BuildLogsDrawerProps> = ({
<h3 css={styles.title}>Creating template...</h3>
<IconButton size="small" onClick={drawerProps.onClose}>
<XIcon className="size-icon-sm" />
<span style={visuallyHidden}>Close build logs</span>
<span className="sr-only">Close build logs</span>
</IconButton>
</header>
+1 -2
View File
@@ -1,4 +1,3 @@
import { visuallyHidden } from "@mui/utils";
import type { AuthMethods } from "api/typesGenerated";
import { Button } from "components/Button/Button";
import { ExternalImage } from "components/ExternalImage/ExternalImage";
@@ -80,7 +79,7 @@ const OidcIcon: FC<OidcIconProps> = ({ iconUrl }) => {
return (
<>
<img alt="" src={iconUrl} aria-labelledby={oidcId} />
<div id={oidcId} css={{ ...visuallyHidden }}>
<div id={oidcId} className="sr-only">
Open ID Connect
</div>
</>
@@ -1,5 +1,4 @@
import { useTheme } from "@emotion/react";
import visuallyHidden from "@mui/utils/visuallyHidden";
import { richParameters } from "api/queries/templates";
import { workspaceBuildParameters } from "api/queries/workspaceBuilds";
import type {
@@ -69,7 +68,7 @@ export const BuildParametersPopover: FC<BuildParametersPopoverProps> = ({
className="min-w-fit"
>
<ChevronDownIcon />
<span css={{ ...visuallyHidden }}>{label}</span>
<span className="sr-only">{label}</span>
</TopbarButton>
</PopoverTrigger>
<PopoverContent
@@ -1,6 +1,5 @@
import type { Interpolation, Theme } from "@emotion/react";
import Link, { type LinkProps } from "@mui/material/Link";
import { visuallyHidden } from "@mui/utils";
import { getErrorMessage } from "api/errors";
import {
updateDeadline,
@@ -218,7 +217,7 @@ const AutostopDisplay: FC<AutostopDisplayProps> = ({
}}
>
<MinusIcon />
<span style={visuallyHidden}>Subtract 1 hour from deadline</span>
<span className="sr-only">Subtract 1 hour from deadline</span>
</Button>
</TooltipTrigger>
<TooltipContent side="bottom">
@@ -236,7 +235,7 @@ const AutostopDisplay: FC<AutostopDisplayProps> = ({
}}
>
<PlusIcon />
<span style={visuallyHidden}>Add 1 hour to deadline</span>
<span className="sr-only">Add 1 hour to deadline</span>
</Button>
</TooltipTrigger>
<TooltipContent side="bottom">Add 1 hour to deadline</TooltipContent>