From 085d218bffd86c8329879fd73bfc6b77e90d2af5 Mon Sep 17 00:00:00 2001 From: Anthony Lio Date: Fri, 4 Sep 2026 10:32:57 +0300 Subject: [PATCH] fix(docs): button a11y enhancements (#49952) ## What kind of change does this PR introduce? bug fix for accessibility, fixes [docs-1265](https://linear.app/supabase/issue/DOCS-1365/add-aria-label-to-icon-only-buttons-button-name) ## What is the current behavior? some controles in the docs app have no accessible name, so screen readers announce them as an unlabelled "button" ## What is the new behavior? - adds each control a name the way its neighbours already do - adds menu toggle a state-dependent `aria-label` and `aria-expanded` - adds `button-name` to `enforced_rules` ## Summary by CodeRabbit - **Accessibility** - Added descriptive labels to configuration selectors and mobile menu controls. - Mobile menu controls now announce whether the menu is open or closed. - Expanded accessibility validation to check button names across documentation pages. - **UI Improvements** - Updated the raw throughput table control with a clearer button appearance and expandable chevron indicator. - Replaced a schema-migration tooltip with a direct in-page link. - **Documentation** - Removed the Info Tooltip component guidance from the contributing documentation. --- apps/docs/app/contributing/content.mdx | 8 -- .../ProjectConfigVariables.ComboBox.tsx | 1 + .../RealtimeLimitsEstimator.tsx | 29 ++-- .../declarative-database-schemas.mdx | 2 +- apps/docs/features/docs/MdxBase.shared.tsx | 2 - apps/docs/features/ui/InfoTooltip.tsx | 127 ------------------ apps/docs/layouts/MainSkeleton.tsx | 2 + e2e/docs/utils/axe-helpers.ts | 4 +- 8 files changed, 18 insertions(+), 157 deletions(-) delete mode 100644 apps/docs/features/ui/InfoTooltip.tsx diff --git a/apps/docs/app/contributing/content.mdx b/apps/docs/app/contributing/content.mdx index a310714f4a3..9dc50751a97 100644 --- a/apps/docs/app/contributing/content.mdx +++ b/apps/docs/app/contributing/content.mdx @@ -472,14 +472,6 @@ void main() async { -### Info Tooltip - -The InfoTooltip component is used to add more context to a word or phrase via tooltip. - -```mdx -Supabase -``` - ## Partials We incorporate content reuse in the docs to avoid duplication. If you find yourself writing the same content over and over, you can put it in a partial instead. Here are some examples of commonly used partials: diff --git a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.ComboBox.tsx b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.ComboBox.tsx index 6b88f8ae343..a88c010ebd3 100644 --- a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.ComboBox.tsx +++ b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.ComboBox.tsx @@ -86,6 +86,7 @@ export function ComboBox({ role="combobox" disabled={disabled} aria-expanded={open} + aria-label={`Select your ${name}`} className={cn( 'overflow-hidden', 'h-auto min-h-10', diff --git a/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx b/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx index 660566d03f5..a1e5e965e52 100644 --- a/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx +++ b/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx @@ -2,7 +2,7 @@ import throughputTable from '~/data/realtime/throughput.json' import { ChevronDown } from 'lucide-react' import { useState } from 'react' import { - Button, + cn, Collapsible, CollapsibleContent, CollapsibleTrigger, @@ -138,22 +138,17 @@ export default function RealtimeLimitsEstimater({}) { )} - -
-

View raw throughput table

-
+ + View raw throughput table +
diff --git a/apps/docs/content/guides/local-development/declarative-database-schemas.mdx b/apps/docs/content/guides/local-development/declarative-database-schemas.mdx index 1611efb5a24..fe8e6a4a866 100644 --- a/apps/docs/content/guides/local-development/declarative-database-schemas.mdx +++ b/apps/docs/content/guides/local-development/declarative-database-schemas.mdx @@ -7,7 +7,7 @@ subtitle: 'Manage your database schemas in one place and generate versioned migr ## Overview -Declarative schemas provide a developer-friendly way to maintain

Files of SQL statements that track the evolution of your database schema over time.
They allow you to version control your database schema alongside your application code.

See the database migrations guide to learn more.

}>schema migrations
. +Declarative schemas provide a developer-friendly way to maintain [schema migrations](#schema-migrations). [Migrations](/docs/guides/deployment/database-migrations) are traditionally managed imperatively (you provide the instructions on how exactly to change the database). This can lead to related information being scattered over multiple migration files. With declarative schemas, you instead declare the state you want your database to be in, and the instructions are generated for you. diff --git a/apps/docs/features/docs/MdxBase.shared.tsx b/apps/docs/features/docs/MdxBase.shared.tsx index 355c3f129ab..5e18f0134f8 100644 --- a/apps/docs/features/docs/MdxBase.shared.tsx +++ b/apps/docs/features/docs/MdxBase.shared.tsx @@ -27,7 +27,6 @@ import { NamedCodeBlock } from '~/features/directives/CodeTabs.components' import { MdxAnchor } from '~/features/docs/MdxAnchor' import { Accordion, AccordionItem } from '~/features/ui/Accordion' import { CodeBlock } from '~/features/ui/CodeBlock/CodeBlock' -import InfoTooltip from '~/features/ui/InfoTooltip' import { ShowUntil } from '~/features/ui/ShowUntil' import { TabPanel, Tabs } from '~/features/ui/Tabs' import { ArrowDown, Check, X } from 'lucide-react' @@ -114,7 +113,6 @@ const components = { TabPanel, TerraformProviderSchema, WrapperDashboardIntegration, - InfoTooltip, a: MdxAnchor, h2: (props: ComponentPropsWithoutRef<'h2'>) => ( diff --git a/apps/docs/features/ui/InfoTooltip.tsx b/apps/docs/features/ui/InfoTooltip.tsx deleted file mode 100644 index 84cd2767d05..00000000000 --- a/apps/docs/features/ui/InfoTooltip.tsx +++ /dev/null @@ -1,127 +0,0 @@ -'use client' - -import { useBreakpoint } from 'common' -import { InfoIcon, XIcon } from 'lucide-react' -import React, { - useCallback, - useEffect, - useId, - useRef, - useState, - type PropsWithChildren, -} from 'react' -import { ErrorBoundary } from 'react-error-boundary' -import { - Button, - cn, - CommandEmpty, - Sheet, - SheetContent, - SheetHeader, - Tooltip, - TooltipContent, - TooltipTrigger, -} from 'ui' - -interface PopUpProps extends PropsWithChildren { - tooltipContent: React.ReactNode - className?: string - contentContainerClassName?: string -} - -const buttonClassName = cn( - 'relative px-1 py-0 -my-px', - 'rounded-sm bg-surface-200 border border-dashed', - 'transition-colors hover:border-strong group/inline-popup' -) - -const InfoTooltip = ({ - children, - className, - tooltipContent, - contentContainerClassName, -}: PopUpProps) => { - const id = useId().replaceAll(':', '') - const timeout = useRef | null>(null) - - const [mobileSheetOpen, setMobileSheetOpen] = useState(false) - const [tooltipOpen, _setTooltipOpen] = useState(false) - const isMobile = useBreakpoint('md') - - const setTooltipOpen = useCallback( - (open: boolean) => { - _setTooltipOpen(open) - setMobileSheetOpen(true) - - timeout.current = setTimeout(() => { - if (isMobile) return - const targetElem: HTMLElement | null = document.querySelector(`#tooltip-content-${id}`) - targetElem?.focus() - }) - }, - [_setTooltipOpen, id, isMobile] - ) - - useEffect(() => { - return () => { - if (timeout.current) { - clearTimeout(timeout.current) - } - } - }, []) - - return ( - <> - !isMobile && setTooltipOpen(open)}> - - setMobileSheetOpen(true)} - className={cn(buttonClassName, className)} - > - {children} - - - - - {tooltipContent} - - - {isMobile && ( - - - }> - -
- -

{children}

-
- -
- {tooltipContent} -
-
-
- )} - - ) -} - -export default InfoTooltip diff --git a/apps/docs/layouts/MainSkeleton.tsx b/apps/docs/layouts/MainSkeleton.tsx index 25ac4a58199..5d49d78f7b7 100644 --- a/apps/docs/layouts/MainSkeleton.tsx +++ b/apps/docs/layouts/MainSkeleton.tsx @@ -214,6 +214,8 @@ const MobileHeader = memo(function MobileHeader(props: MobileHeaderProps) { mobileMenuOpen && 'mt-0.5' )} onClick={() => menuState.setMenuMobileOpen(!mobileMenuOpen)} + aria-label={mobileMenuOpen ? 'Close menu' : 'Open menu'} + aria-expanded={mobileMenuOpen} >
{ const reported = await scan(page, { tags: WCAG_TAGS, excludeRules: EXCLUDED_RULES, include }) - const enforced = await scan(page, { rules: ENFORCED_RULES, include }) + const enforced = await scan(page, { rules: ENFORCED_RULES }) const byRule = new Map([...reported, ...enforced].map((violation) => [violation.id, violation]))