Files
Miranda LimonczenkoandClaude Sonnet 5 320111b06b fix(docs): replace hardcoded heading tags in 4 shared components (#48456)
Closes DOCS-1261

_WAVE plugin shows headers creating jumps in hierarchy. Preview on the
left:_
<img width="1022" height="417" alt="Screenshot 2026-07-29 at 2 42 07 PM"
src="https://github.com/user-attachments/assets/f5e3bd09-8dbf-45e3-8a7f-70d7334fd25b"
/>

<img width="408" height="663" alt="Screenshot 2026-07-29 at 2 44 33 PM"
src="https://github.com/user-attachments/assets/6b952a81-40e5-4a9d-b08a-190c71575cac"
/>



## Problem

Four shared components in `apps/docs` render a hardcoded heading tag no
matter where they're used:

- `NamedCodeBlock` renders a code block's filename as an `<h6>`
- `ProjectConfigVariables` renders a variable label as an `<h6>`
- `StepHikeCompact.Details` renders a step title as an `<h3>`
- `IconPanel` renders its title as an `<h5>`

Since these are fixed, they often land in the wrong spot in a page's
heading order (like an h6 right after an h2), which breaks navigation
for screen reader users. This showed up in the [header hierarchy triage
report](https://app.notion.com/p/supabase/Playwright-E2E-Triage-Reports-3ab5004b775f81e3bc60d058fa5a02c1)
— fixing these 4 components alone resolves 72 of the 159 heading-order
violations found.

## Solution

Swapped the heading tag in each component for a `<span>` with the same
classes. None of these are really "headings" for the content that
follows, so they shouldn't be in the tag tree at all.

The one wrinkle: this codebase applies heading font weight/family
through a global CSS rule keyed off the tag name (h1-h6), not something
the tag gives you for free. So each span now sets that styling
explicitly, plus a margin to match what was there before. Nothing else
changed — same classes, same layout.

## Manual testing

Staging preview:
https://docs-git-ui-header-hierarchy-supabase.vercel.app

Check that each one still looks right:
-
[NamedCodeBlock](https://docs-git-ui-header-hierarchy-supabase.vercel.app/docs/guides/self-hosting/docker)
— filenames above the code blocks
-
[ProjectConfigVariables](https://docs-git-ui-header-hierarchy-supabase.vercel.app/docs/guides/auth/quickstarts/react-native)
— the "Project URL" / "Publishable key" labels (this page also has a
`NamedCodeBlock` inside the numbered steps)
-
[StepHikeCompact](https://docs-git-ui-header-hierarchy-supabase.vercel.app/docs/guides/database/beekeeper-studio)
— the step titles ("Create a new connection", etc.)
-
[IconPanel](https://docs-git-ui-header-hierarchy-supabase.vercel.app/docs/guides/resources)
— the "Auth0" / "Firebase Auth" panel titles under "Migrate to Supabase"

I also ran typecheck, lint, and the docs test suite locally — all green.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Style**
* Updated headings and labels across documentation and UI components for
more consistent typography.
* Improved spacing, font weight, and block-level layout for project
variables, step details, code tabs, and icon panels.
  * Preserved existing text content and conditional display behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 18:25:23 +00:00

125 lines
2.7 KiB
TypeScript

import { FC, PropsWithChildren } from 'react'
import { cn } from 'ui'
interface IStep {
title: string
step: number | string
}
interface IStepHikeCompactSubcomponents {
Step: FC<IStep>
Details: FC<IDetails>
Code: FC<ICode>
}
interface IDetails {
title?: string
fullWidth?: boolean
}
interface ICode {}
interface IStepHikeCompact {
title: string
}
const StepHikeCompact: FC<PropsWithChildren<IStepHikeCompact>> & IStepHikeCompactSubcomponents = ({
children,
title,
}) => {
return <div className="py-8">{children}</div>
}
const Step: FC<PropsWithChildren<IStep>> = ({ children, title, step }) => {
return (
<div className="relative pb-8 group">
<div
className="
absolute
w-px
left-[11px]
pt-1
h-full
"
>
<div
className="
absolute
w-full
h-full
py-1
bg-border-control
group-last:bg-transparent
"
></div>
</div>
<div
className="
absolute
left-0
flex gap-3 items-center
not-prose
"
>
<div className="flex items-center gap-6">
<div
className="border bg-surface-100
border-control flex items-center justify-center rounded-full
w-6 h-6 text-xs text-foreground font-normal font-mono
dropshadow-sm
"
>
{step}
</div>
</div>
</div>
<div
className={cn(
'ml-12 flex min-w-0 flex-col',
'[&_[data-step-hike=details]+[data-step-hike=code]]:mt-6',
'[&_[data-step-hike=details]:not(:has(+[data-step-hike=code]))]:mb-6',
'[&_[data-step-hike=code]]:mb-6',
'[&_[data-step-hike=code]:last-child]:mb-0'
)}
>
{children}
</div>
</div>
)
}
const Details: FC<PropsWithChildren<IDetails>> = ({ children, title, fullWidth = false }) => {
return (
<div
data-step-hike="details"
className={cn(
'min-w-0',
'[&_p:last-child]:mb-0 [&_ul:last-child]:mb-0 [&_ol:last-child]:mb-0',
fullWidth && 'w-full'
)}
>
{title && (
<span className="block mt-0 mb-[18px] text-foreground text-base font-heading font-semibold">
{title}
</span>
)}
{children}
</div>
)
}
const Code: FC<PropsWithChildren<ICode>> = ({ children }) => {
return (
<div
data-step-hike="code"
className="not-prose min-w-0 w-full [&_.shiki]:!my-0 [&_.shiki-wrapper]:!my-0"
>
{children}
</div>
)
}
StepHikeCompact.Step = Step
StepHikeCompact.Details = Details
StepHikeCompact.Code = Code
export default StepHikeCompact