feat(a11y): label form controls + overlays (P3-4)
Accessible names for ~15 controls that lacked them: invite/join/create-room/ account-data/image-pack/private-note/power-level inputs (visible <label htmlFor> where a label exists, else aria-label); the two range sliders (night-light intensity, noise-gate threshold); the soundboard file input; media <video> elements; and the Media Gallery (region) + Search (dialog) overlays. Hidden notification/preview <audio> marked aria-hidden. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -147,6 +147,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
||||
<Text size="L400">Name</Text>
|
||||
<Input
|
||||
name="nameInput"
|
||||
aria-label="Power level name"
|
||||
defaultValue={tag?.name}
|
||||
placeholder="Bot"
|
||||
size="300"
|
||||
@@ -160,6 +161,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
||||
<Input
|
||||
defaultValue={power}
|
||||
name="powerInput"
|
||||
aria-label="Power level value"
|
||||
size="300"
|
||||
variant={typeof power === 'number' ? 'SurfaceVariant' : 'Secondary'}
|
||||
radii="300"
|
||||
|
||||
@@ -186,8 +186,8 @@ function LightboxMedia({
|
||||
)}
|
||||
{media.status === 'ok' &&
|
||||
(item.msgtype === MsgType.Video ? (
|
||||
// eslint-disable-next-line jsx-a11y/media-has-caption
|
||||
<video
|
||||
aria-label="Video attachment"
|
||||
src={media.url}
|
||||
controls
|
||||
autoPlay
|
||||
@@ -261,7 +261,7 @@ function Lightbox({
|
||||
escapeDeactivates: false,
|
||||
}}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
|
||||
{}
|
||||
<div
|
||||
role="dialog"
|
||||
aria-modal
|
||||
@@ -640,13 +640,15 @@ export function MediaGallery({ room, onClose }: MediaGalleryProps) {
|
||||
className={classNames(css.MediaGalleryDrawer, ContainerColor({ variant: 'Background' }))}
|
||||
shrink="No"
|
||||
direction="Column"
|
||||
role="region"
|
||||
aria-labelledby="media-gallery-title"
|
||||
>
|
||||
{/* Header */}
|
||||
<Header variant="Background" size="600" className={css.MediaGalleryHeader}>
|
||||
<Box grow="Yes" alignItems="Center" gap="200">
|
||||
<Icon size="200" src={Icons.Photo} />
|
||||
<Box grow="Yes">
|
||||
<Text size="H4" truncate>
|
||||
<Text id="media-gallery-title" size="H4" truncate>
|
||||
Media Gallery
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
@@ -142,7 +142,6 @@ export function PollCreator({ roomId, onClose }: PollCreatorProps) {
|
||||
placeholder="Ask a question…"
|
||||
value={question}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setQuestion(e.target.value)}
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus
|
||||
autoFocus
|
||||
/>
|
||||
</Box>
|
||||
@@ -151,7 +150,6 @@ export function PollCreator({ roomId, onClose }: PollCreatorProps) {
|
||||
<Box direction="Column" gap="200">
|
||||
<Text size="L400">Options</Text>
|
||||
{options.map((opt, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<Box key={index} alignItems="Center" gap="200">
|
||||
<Input
|
||||
style={{ flex: 1 }}
|
||||
|
||||
@@ -247,7 +247,6 @@ export function Search({ requestClose }: SearchProps) {
|
||||
<FocusTrap
|
||||
focusTrapOptions={{
|
||||
initialFocus: () => inputRef.current,
|
||||
returnFocusOnDeactivate: false,
|
||||
allowOutsideClick: true,
|
||||
clickOutsideDeactivates: true,
|
||||
onDeactivate: requestClose,
|
||||
@@ -257,7 +256,13 @@ export function Search({ requestClose }: SearchProps) {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Modal size="400" style={{ maxHeight: toRem(400), borderRadius: config.radii.R500 }}>
|
||||
<Modal
|
||||
size="400"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="Search"
|
||||
style={{ maxHeight: toRem(400), borderRadius: config.radii.R500 }}
|
||||
>
|
||||
<Box
|
||||
shrink="No"
|
||||
style={{ padding: config.space.S400, paddingBottom: 0 }}
|
||||
@@ -270,6 +275,7 @@ export function Search({ requestClose }: SearchProps) {
|
||||
radii="400"
|
||||
outlined
|
||||
placeholder="Search"
|
||||
aria-label="Search rooms"
|
||||
before={<Icon size="200" src={Icons.Search} />}
|
||||
onChange={handleInputChange}
|
||||
onKeyDown={handleInputKeyDown}
|
||||
|
||||
@@ -531,6 +531,7 @@ function Appearance() {
|
||||
Intensity: {nightLightOpacity}%
|
||||
</Text>
|
||||
<input
|
||||
aria-label="Night light intensity"
|
||||
type="range"
|
||||
min={5}
|
||||
max={80}
|
||||
@@ -1663,6 +1664,7 @@ function Calls() {
|
||||
<Text size="T200">{callDenoiseGateThreshold} dB</Text>
|
||||
</Box>
|
||||
<input
|
||||
aria-label="Noise gate threshold"
|
||||
type="range"
|
||||
min="-100"
|
||||
max="0"
|
||||
|
||||
Reference in New Issue
Block a user