mirror of
https://github.com/supabase/supabase.git
synced 2026-09-03 07:28:20 +08:00
Closes FE-3811
## Problem
CodeRabbit reviews UI PRs without prompting on accessibility gaps
axe-core cannot judge: live regions, keyboard and hover, reduced motion,
alt quality, focus visibility, color-only state, and vague link names.
## Solution
- Add a path_instruction on `{apps,packages}/**/*.{tsx,jsx,css,mdx}`.
- Keep comments advisory. Skip tests, generated files, Radix/shadcn from
`ui`, and mechanical axe findings.
- Cover live-region lifecycle, pointer-only and hover-only UI, reduced
motion, alt quality including a two-sentence length heuristic, focus
rings, color-only state, and generic link names.
## Manual testing
1. After merge, open a PR that touches a UI or MDX file under `apps/` or
`packages/`.
2. Confirm CodeRabbit comments on at least one of: an unannounced status
change, a live region created with its message, a pointer-only or
hover-only control, animation without reduced motion, generic or
redundant or long alt, `outline-none` without a focus-visible
replacement, color-only status, or a "learn more" link that does not
name its destination.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Accessibility**
* Expanded accessibility review coverage for interface content and
styling.
* Reviews now identify missing focus indicators, color-only status or
selection cues, and unclear link labels.
* Continued checks cover state announcements, pointer-only interactions,
reduced-motion support, and alternative text quality.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
141 lines
8.4 KiB
YAML
141 lines
8.4 KiB
YAML
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
|
|
|
|
# Don't inherit organization-level settings (they're tuned for other repos);
|
|
# this config is self-contained and unset values use CodeRabbit defaults.
|
|
inheritance: false
|
|
|
|
# Enrich linked issues with related code and potential solutions during review.
|
|
issue_enrichment:
|
|
auto_enrich:
|
|
enabled: true
|
|
|
|
reviews:
|
|
# Skip machine-generated / vendored files (mirrors .prettierignore). Keeps
|
|
# reviews focused on hand-written code and preserves rate-limit budget on
|
|
# large codegen diffs.
|
|
path_filters:
|
|
- '!pnpm-lock.yaml'
|
|
- '!packages/api-types/types/**' # generated API types (api.d.ts, platform.d.ts)
|
|
- '!supabase/functions/common/database-types.ts' # generated by `pnpm generate:types`
|
|
- '!**/routeTree.gen.ts' # TanStack Router generated
|
|
- '!**/__generated__/**'
|
|
- '!apps/docs/features/docs/generated/**'
|
|
- '!apps/www/.generated/**'
|
|
- '!apps/design-system/__registry__/**'
|
|
- '!apps/ui-library/__registry__/**'
|
|
- '!apps/ui-library/public/r/**' # registry output
|
|
- '!packages/icons/__registry__/**'
|
|
- '!packages/icons/src/icons/**' # generated icon components
|
|
|
|
# Targeted, path-scoped review guidance, version-controlled alongside the code.
|
|
path_instructions:
|
|
- path: 'packages/common/telemetry-constants.ts'
|
|
instructions: |
|
|
Strictly enforce event naming: [object]_[verb] in snake_case. Only approved
|
|
verbs: opened, clicked, submitted, created, removed, updated, retrieved,
|
|
intended, evaluated, added, enabled, disabled, copied, exposed, failed,
|
|
converted. Properties must be camelCase for new events (match existing
|
|
convention when adding to existing events). Flag any usage of
|
|
useSendEventMutation. Verify @group Events and @source JSDoc tags are
|
|
accurate. Check that new interfaces are added to the TelemetryEvent union type.
|
|
- path: 'apps/studio/components/**/!(*.test).tsx' # production components only, not tests
|
|
instructions: |
|
|
Only suggest adding PostHog event tracking (via useTrack from
|
|
lib/telemetry/track, [object]_[verb] snake_case) when a new user-facing
|
|
interaction is growth-relevant: e.g. first-use of a feature, onboarding steps,
|
|
project/org creation, upgrade/billing actions, enabling or disabling a product
|
|
feature, or any action that signals activation or retention. Do not suggest
|
|
tracking for: passive views, page loads, UI-only state changes (e.g. expanding
|
|
a panel, switching tabs in a settings page), developer/internal tooling
|
|
interactions, or interactions clearly unrelated to product adoption.
|
|
- path: 'apps/studio/pages/**'
|
|
instructions: |
|
|
Studio is mid-migration from the Next.js pages router (apps/studio/pages/**)
|
|
to TanStack Start (apps/studio/routes/**). Both runtimes ship side-by-side, so
|
|
every URL served from pages/** has a mirror in routes/**. See
|
|
apps/studio/TANSTACK_MIGRATION.md for the full route map and strategy.
|
|
Leave a comment reminding the author to check whether this change needs to be
|
|
mirrored into the corresponding apps/studio/routes/** file so the two builds
|
|
don't silently drift:
|
|
- Most route files re-export the page's default export (Path A), so pure
|
|
page-body edits propagate automatically — no mirror needed.
|
|
- A mirror IS needed when the change touches something the route file
|
|
duplicates rather than imports: getLayout / layout wrapping, page title or
|
|
other props the route encodes as staticData, withAuth / auth gating, or the
|
|
route/redirect path itself.
|
|
- A brand-new page under pages/** needs a matching new route under routes/**
|
|
(and a checklist entry in apps/studio/TANSTACK_MIGRATION.md).
|
|
- Do NOT suggest deleting the pages/** file — the Next file stays load-bearing
|
|
for both runtimes until the final cleanup pass (tracked in FE-3106).
|
|
Keep this a reminder to verify, not a hard blocker: if no mirror is required,
|
|
say so briefly rather than forcing a change.
|
|
- path: '{apps,packages}/**/*.{tsx,jsx,css,mdx}'
|
|
instructions: |
|
|
When reviewing UI changes, flag these accessibility gaps. Comments are
|
|
advisory. One comment per gap. Skip test files (*.test.*, *.spec.*) and
|
|
generated files. Skip Radix/shadcn primitives imported from ui for all
|
|
checks below. Do not flag issues axe-core already catches mechanically,
|
|
such as a missing alt attribute, an empty button or link name, or
|
|
invalid ARIA.
|
|
- State changes: if sighted users can see a status change (toast,
|
|
loading/empty swap, copy confirmation, async result) and nothing
|
|
announces it, suggest aria-live="polite" or role="status". Reserve
|
|
role="alert" for urgent errors or warnings. Skip if a live region,
|
|
Radix Toast, or Sonner is already there, or if the change is
|
|
decoration only. If a live region is created in the same conditional
|
|
as its message, flag that: the region must already exist in the DOM,
|
|
then receive the update, or screen readers often announce nothing.
|
|
- Mouse interaction: flag pointer-only handlers on a non-interactive
|
|
element (div, span, or similar) with no keyboard equivalent. The
|
|
listed handlers are illustrative: onClick, onMouseEnter,
|
|
onDoubleClick, onContextMenu, onPointerDown, onPointerUp,
|
|
onTouchStart, onTouchEnd, and equivalents. Also flag hover-only UI
|
|
(content revealed with onMouseEnter or CSS :hover) that has no focus
|
|
or keyboard path.
|
|
- Animation: flag animate-*, keyframes, or JS motion with no
|
|
reduced-motion treatment. Prefer Tailwind motion-reduce: /
|
|
motion-safe:, or matchMedia('(prefers-reduced-motion: reduce)').
|
|
packages/config/css/utilities.css only zeroes out .shimmer under
|
|
reduced motion, not all animation.
|
|
- Alt text: flag generic values such as Image, Icon, Photo, Picture, or
|
|
the filename. Flag alt that starts with "image of" or "picture of".
|
|
If adjacent visible text already names the image (blog thumbnail next
|
|
to its title, icon next to its label), flag it as redundant and
|
|
recommend alt="" plus aria-hidden on the image. For a decorative SVG
|
|
next to visible text, recommend aria-hidden on the SVG. If alt is
|
|
longer than about two sentences, suggest moving the extra into a
|
|
caption, adjacent text, or aria-describedby. Do not treat a character
|
|
count as a hard fail.
|
|
- Focus visibility: flag outline-none, outline-hidden, outline: none,
|
|
outline: 0, or equivalent :focus resets that are not paired with a
|
|
focus-visible ring or outline, or with the focus-ring or focus-inset
|
|
utility.
|
|
- Color-only state: flag status, validation, or selection that is
|
|
conveyed only by color. Suggest a text label, icon, or sr-only text
|
|
in addition.
|
|
- Link purpose: flag an accessible name that is only "click here",
|
|
"read more", or "learn more" when it does not describe the
|
|
destination. Skip if aria-label or wrapping context already names
|
|
where the link goes.
|
|
|
|
# Applies our internal engineering skills (.claude/skills/) as CodeRabbit review
|
|
# guidelines. The skills are the single source of truth — they are consumed
|
|
# directly, with no copy of their content elsewhere.
|
|
#
|
|
# `applyTo` decouples where a guideline file lives from the code it governs.
|
|
# Without it, CodeRabbit scopes a guideline file to its own directory and below;
|
|
# our skills live in .claude/skills/, which contains no code, so they would never
|
|
# reach apps/studio. `applyTo` points them at the right paths instead.
|
|
knowledge_base:
|
|
code_guidelines:
|
|
filePatterns:
|
|
# Studio code conventions — React/TS, UI patterns, composition, data fetching, errors
|
|
- files: '.claude/skills/{studio-best-practices,studio-ui-patterns,vercel-composition-patterns,studio-queries,studio-error-handling,react-hook-form}/SKILL.md'
|
|
applyTo: 'apps/studio/**/*.{ts,tsx}'
|
|
# Studio unit / component test conventions
|
|
- files: '.claude/skills/{studio-testing,studio-mock-api-tests}/SKILL.md'
|
|
applyTo: 'apps/studio/**/*.test.{ts,tsx}'
|
|
# Studio end-to-end (Playwright) test conventions
|
|
- files: '.claude/skills/studio-e2e-tests/SKILL.md'
|
|
applyTo: 'e2e/studio/**/*.spec.ts'
|