feat(docs): o11y agent setup stepper (#50962)

## Problem

on monitoring agent pages the prompt lives in a "prompt" tab next to
agent ones, while each agent tab ended with "paste the prompt" users
have to work out that the prompt is sitting in that previous tab

## Solution

this pr is a proposal to set agent setup as a two stepper `1` for the
prompt panel `2` holds the agent tabs:

- extracts prompt into a first step
- moves agent tabs within their own step
- polishes agent docs to match recent ui updates
- sets `prompt` as an anchor link within agent tabs 

| state | preview |
| -------|------|
| before | <img width="823" height="452" alt="image"
src="https://github.com/user-attachments/assets/a6a01832-ea73-48c1-b31d-25a0ef970e4e"
/> |
| after | <img width="823" height="716" alt="image"
src="https://github.com/user-attachments/assets/f5014ad0-1555-4578-b4b1-5bf2733b4d37"
/> |

<!--
## Preview links

If relevant, include links to changed pages for easy review access.

Copy the preview base URL from the Vercel bot comment on this PR. Use
the following table as an example template.

| Site | Live | Preview | Search for |
| -------------- |
-------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------
| ----------------------------- |
| WWW | [/blog/your-post](https://supabase.com/blog/your-post) |
[/blog/your-post](https://zone-www-dot-com-git-branch-name-supabase.vercel.app/blog/your-post)
| unique phrase from the change |
| Docs |
[/docs/guides/your-page](https://supabase.com/docs/guides/your-page) |
[/docs/guides/your-page](https://docs-git-branch-name-supabase.vercel.app/docs/guides/your-page)
| unique phrase from the change |
| Studio | [/dashboard](https://supabase.com/dashboard) |
[/dashboard](https://studio-git-branch-name-supabase.vercel.app/dashboard)
| unique phrase from the change |
| Design system | [/design-system](https://supabase.com/design-system) |
[/design-system](https://design-system-git-branch-name-supabase.vercel.app/design-system)
| unique phrase from the change |
| UI library | [/library](https://supabase.com/library) |
[/library](https://ui-library-git-branch-name-supabase.vercel.app/library)
| unique phrase from the change |
| Knowledge base |
[/kb/guides/your-page](https://supabase.com/kb/guides/your-page) |
[/kb/guides/your-page](https://kb-git-branch-name-supabase.vercel.app/kb/guides/your-page)
| unique phrase from the change |
-->

<!-- ## Additional context

Optionally add any other context or screenshots.

-->

## Review instructions

Provide a clear numbered procedure that the PR reviewer can walk
through.

1. visit
[/automate-with-agents/health](https://docs-git-docs-agent-setup-stepper-supabase.vercel.app/docs/guides/observability/automate-with-agents/health#set-up-the-agent)

## Checklist

Check all before review:

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)


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

* **New Features**
* Agent setup instructions are organized into prompt-copying and
scheduling steps, with links to harness documentation.
  * Code tabs support icons and controlled selection.
  * Source code samples support adjustable footer notches.
* **Bug Fixes**
  * Step numbers now display the correct shadow.
* Links to page anchors now scroll to, focus, and highlight their
targets, while respecting reduced-motion preferences.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Anthony Lio authored and GitHub committed 2026-09-28 17:28:11 +03:00
1 parent f0e0865acc
commit 4a9b4b0a9e
9 files changed
+221 -88

No files matched your search

+11 -8
View File
@@ -7,16 +7,18 @@ interface IStep {
}
interface IStepHikeCompactSubcomponents {
Step: FC<IStep>
Details: FC<IDetails>
Code: FC<ICode>
Step: FC<PropsWithChildren<IStep>>
Details: FC<PropsWithChildren<IDetails>>
Code: FC<PropsWithChildren<ICode>>
}
interface IDetails {
title?: string
fullWidth?: boolean
}
interface ICode {}
interface ICode {
className?: string
}
interface IStepHikeCompact {
title: string
@@ -65,7 +67,7 @@ const Step: FC<PropsWithChildren<IStep>> = ({ children, title, step }) => {
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
drop-shadow-sm
"
>
{step}
@@ -107,7 +109,7 @@ const Details: FC<PropsWithChildren<IDetails>> = ({ children, title, fullWidth =
)
}
const Code: FC<PropsWithChildren<ICode>> = ({ children }) => {
const Code: FC<PropsWithChildren<ICode>> = ({ children, className }) => {
// Not `not-prose`: steps interleave labels and admonitions with their code samples, and
// stripping prose leaves that text unstyled and flush against the samples.
return (
@@ -118,7 +120,8 @@ const Code: FC<PropsWithChildren<ICode>> = ({ children }) => {
// `Step` spaces the block as a whole, so samples don't carry margins of their own...
'[&_.shiki]:!my-0 [&_.shiki-wrapper]:!my-0',
// ...but back-to-back samples have no prose between them to separate them.
'[&_.shiki+.shiki]:!mt-6'
'[&_.shiki+.shiki]:!mt-6',
className
)}
>
{children}
@@ -129,4 +132,4 @@ const Code: FC<PropsWithChildren<ICode>> = ({ children }) => {
StepHikeCompact.Step = Step
StepHikeCompact.Details = Details
StepHikeCompact.Code = Code
export default StepHikeCompact
export { StepHikeCompact }
+5 -3
View File
@@ -26,6 +26,8 @@ export type MonitoringAgentHarnessSetup = {
const WEEKDAY_LABELS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as const
const DAY_LABELS = ['12am', '6am', '12pm', '6pm'] as const
export const AGENT_PROMPT_ANCHOR = 'agent-prompt'
const MCP_STEP =
'Connect the [Supabase MCP server](/docs/guides/ai-tools/mcp) with `project_ref` and `read_only=true`.'
@@ -103,7 +105,7 @@ export function getMonitoringAgentHarnesses(agent: MonitoringAgent): MonitoringA
isSubHourly
? 'In the Claude Code Desktop app, open **Routines**, click **New routine**, and choose **Local**.'
: 'Open [Claude routines](https://claude.ai/code/routines) or run `/schedule` in Claude Code.',
`Name it ${agent.name}. Paste the prompt. Set the schedule to ${cadence}.`,
`Name it ${agent.name}. Paste the [prompt](#${AGENT_PROMPT_ANCHOR}). Set the schedule to ${cadence}.`,
],
note: isSubHourly
? 'Cloud routines have a 1-hour minimum. Use a [Desktop scheduled task](https://code.claude.com/docs/en/desktop-scheduled-tasks) for this cadence.'
@@ -119,7 +121,7 @@ export function getMonitoringAgentHarnesses(agent: MonitoringAgent): MonitoringA
steps: [
MCP_STEP,
'Open **Scheduled** in the ChatGPT desktop app, or ask Codex to create a standalone scheduled task.',
`Name it ${agent.name}. Paste the prompt. Set the schedule to ${cadence}. Each run should start a new chat.`,
`Name it ${agent.name}. Paste the [prompt](#${AGENT_PROMPT_ANCHOR}). Set the schedule to ${cadence}. Each run should start a new chat.`,
],
},
{
@@ -132,7 +134,7 @@ export function getMonitoringAgentHarnesses(agent: MonitoringAgent): MonitoringA
steps: [
MCP_STEP,
'Create an automation in the Agents Window, at [cursor.com/automations](https://cursor.com/automations), or with the `/automate` skill.',
`Name it ${agent.name}. Use a scheduled trigger (${cadence}, cron \`${cron}\`). Paste the prompt. Keep the agent read-only, with no repository.`,
`Name it ${agent.name}. Use a scheduled trigger (${cadence}, cron \`${cron}\`). Paste the [prompt](#${AGENT_PROMPT_ANCHOR}). Keep the agent read-only, with no repository.`,
],
},
]
@@ -1,7 +1,7 @@
'use client'
import Link from 'next/link'
import { type PropsWithChildren, type ReactNode } from 'react'
import { type CSSProperties, type PropsWithChildren, type ReactNode } from 'react'
import {
cn,
DropdownMenu,
@@ -26,18 +26,27 @@ interface SingleSourceProps {
interface SourceFrameProps {
footer: ReactNode
notchWidth?: number
}
const SOURCE_FOOTER_CLASSES = cn(
'not-prose absolute right-0 bottom-0 z-1 flex h-8 w-29.25 items-center gap-2 px-3 whitespace-nowrap',
export const SOURCE_FOOTER_CLASSES = cn(
'not-prose absolute right-0 bottom-0 z-1 flex h-8 w-(--source-notch-width) items-center gap-2 px-3 whitespace-nowrap',
'text-xs text-foreground-lighter no-underline transition-colors hover:text-foreground',
'focus-inset rounded-md'
)
const SOURCE_NOTCH_OUTLINE =
'M0 39.5A7.5 7.5 0 0 0 7.5 32V16A8.5 8.5 0 0 1 16 7.5H117A7.5 7.5 0 0 0 124.5 0'
const DEFAULT_NOTCH_WIDTH = 117
const SOURCE_NOTCH_FOCUS_RING = 'M0 41A9 9 0 0 0 9 32V16A7 7 0 0 1 16 9H117A9 9 0 0 0 126 0'
const getNotchOutline = (width: number): string =>
`M0 39.5A7.5 7.5 0 0 0 7.5 32V16A8.5 8.5 0 0 1 16 7.5H${width}A7.5 7.5 0 0 0 ${width + 7.5} 0`
const getNotchFocusRing = (width: number): string =>
`M0 41A9 9 0 0 0 9 32V16A7 7 0 0 1 16 9H${width}A9 9 0 0 0 ${width + 9} 0`
const getNotchMask = (width: number): string =>
`url("data:image/svg+xml,${encodeURIComponent(
`<svg xmlns='http://www.w3.org/2000/svg' width='${width + 10}' height='42'><path d='M0 40A8 8 0 0 0 8 32V16A8 8 0 0 1 16 8H${width}A8 8 0 0 0 ${width + 8} 0H${width + 10}V42H0Z'/></svg>`
)}")`
const getSourcePath = (source: string | URL): string => {
const [, org, repo, , , ...path] = new URL(source).pathname.split('/')
@@ -123,24 +132,38 @@ function SingleSource({ children, source }: PropsWithChildren<SingleSourceProps>
)
}
function SourceFrame({ children, footer }: PropsWithChildren<SourceFrameProps>) {
export function SourceFrame({
children,
footer,
notchWidth = DEFAULT_NOTCH_WIDTH,
}: PropsWithChildren<SourceFrameProps>) {
const outline = getNotchOutline(notchWidth)
const notchStyle = {
'--source-notch-width': `${notchWidth}px`,
'--source-notch-mask': getNotchMask(notchWidth),
'--source-notch-mask-width': `${notchWidth + 10}px`,
} as CSSProperties
return (
<div className="group/source code-sample-source shiki-wrapper relative w-full [&_.shiki]:pb-8 [&_.shiki]:shadow-none!">
<div
style={notchStyle}
className="group/source code-sample-source shiki-wrapper relative w-full [&_.shiki]:pb-8 [&_.shiki]:shadow-none!"
>
<div className="codeblock-drop-shadow relative has-[.code-scroll:focus-visible]:z-1">
{children}
</div>
<svg
aria-hidden
width="125"
width={notchWidth + 8}
height="40"
viewBox="0 0 125 40"
viewBox={`0 0 ${notchWidth + 8} 40`}
fill="none"
className="pointer-events-none absolute right-0 bottom-0 z-1 overflow-visible"
>
<path d={SOURCE_NOTCH_OUTLINE} className="stroke-background-200" />
<path d={SOURCE_NOTCH_OUTLINE} className="stroke-border" />
<path d={outline} className="stroke-background-200" />
<path d={outline} className="stroke-border" />
<path
d={SOURCE_NOTCH_FOCUS_RING}
d={getNotchFocusRing(notchWidth)}
strokeWidth={2}
className="hidden stroke-ring group-has-[.code-scroll:focus-visible]/source:inline"
/>
@@ -1,9 +1,15 @@
import { Children, isValidElement, type PropsWithChildren } from 'react'
import { Children, isValidElement, type PropsWithChildren, type ReactNode } from 'react'
import { cn, TabsIndicator, TabsList, Tabs as TabsRoot, TabsTrigger } from 'ui'
interface CodeTabPanelProps {
id: string
label?: string
icon?: ReactNode
}
interface CodeTabsProps {
value?: string
onValueChange?: (value: string) => void
}
export function NamedCodeBlock({ name, children }: PropsWithChildren<{ name: string }>) {
@@ -31,12 +37,14 @@ export function NamedCodeBlock({ name, children }: PropsWithChildren<{ name: str
)
}
export function CodeTabs({ children }: PropsWithChildren) {
export function CodeTabs({ children, value, onValueChange }: PropsWithChildren<CodeTabsProps>) {
const tabs = Children.toArray(children).filter(isValidElement<CodeTabPanelProps>)
return (
<TabsRoot
defaultValue={tabs[0]?.props.id}
value={value}
onValueChange={onValueChange}
className="group/code-tabs shiki-wrapper w-full isolate [&_.shiki]:my-0!"
>
<TabsList
@@ -51,7 +59,10 @@ export function CodeTabs({ children }: PropsWithChildren) {
value={tab.props.id}
className="relative z-1 rounded-md py-2 text-xs data-[state=active]:shadow-none"
>
<span className="px-3">{tab.props.label ?? tab.props.id}</span>
<span className="flex items-center gap-2 px-3 [&_img]:size-3.5">
{tab.props.icon}
{tab.props.label ?? tab.props.id}
</span>
</TabsTrigger>
))}
<TabsIndicator
+1 -1
View File
@@ -19,7 +19,7 @@ import { ProjectConfigVariables } from '~/components/ProjectConfigVariables'
import { RealtimeLimitsEstimator } from '~/components/RealtimeLimitsEstimator'
import { RegionsList, SmartRegionsList } from '~/components/RegionsList'
import { SharedData } from '~/components/SharedData'
import StepHikeCompact from '~/components/StepHikeCompact'
import { StepHikeCompact } from '~/components/StepHikeCompact'
import Table from '~/components/Table'
import { TerraformProviderSchema } from '~/components/TerraformProviderSchema'
import { WrapperDashboardIntegration } from '~/components/WrapperDashboardIntegration'
+143 -54
View File
@@ -1,28 +1,66 @@
'use client'
import { StepHikeCompact } from '~/components/StepHikeCompact'
import {
AGENT_PROMPT_ANCHOR,
getMonitoringAgent,
getMonitoringAgentHarnesses,
type MonitoringAgentHarnessSetup,
} from '~/data/monitoring-agents.utils'
import { Sparkles } from 'lucide-react'
import { useTheme } from 'next-themes'
import { type ReactNode } from 'react'
import { SOURCE_FOOTER_CLASSES, SourceFrame } from '~/features/directives/CodeSample.client'
import { CodeTabs } from '~/features/directives/CodeTabs.components'
import Image from 'next/image'
import { useState, type MouseEvent, type ReactNode } from 'react'
import ReactMarkdown from 'react-markdown'
import { ConnectionIcon } from 'ui-patterns/McpUrlBuilder'
import { cn } from 'ui'
import { getMcpClientIconSrc } from 'ui-patterns/McpUrlBuilder'
import { AiPrompt } from './AiPrompt'
import { PromptCode } from './PromptPanel'
import { TabPanel, Tabs } from './Tabs'
import { TabPanel } from './Tabs'
import { useTabsWithQueryParams } from './useTabsWithQueryParams'
type AgentSetupProps = {
id: string
}
type HarnessProps = {
harness: MonitoringAgentHarnessSetup
}
const DOCS_NOTCH_WIDTH = 100
const PROMPT_FLASH_DURATION = 1600
const handleInPageLinkClick = (event: MouseEvent<HTMLAnchorElement>) => {
const target = document.getElementById(event.currentTarget.hash.slice(1))
if (!target) return
event.preventDefault()
const { hash } = event.currentTarget
if (window.location.hash !== hash) window.history.pushState(null, '', hash)
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
target.scrollIntoView({ behavior: prefersReducedMotion ? 'auto' : 'smooth', block: 'center' })
target.focus({ preventScroll: true })
const brand = getComputedStyle(target).getPropertyValue('--brand-default')
target.animate([{ outlineColor: `hsl(${brand})` }, { outlineColor: `hsl(${brand} / 0)` }], {
duration: PROMPT_FLASH_DURATION,
easing: 'ease-out',
})
}
const markdownComponents = {
p: ({ children }: { children?: ReactNode }) => <>{children}</>,
a: ({ href, children }: { href?: string; children?: ReactNode }) => {
if (!href) return <>{children}</>
if (href.startsWith('#')) {
return (
<a href={href} onClick={handleInPageLinkClick} className="text-primary hover:underline">
{children}
</a>
)
}
const external = /^(?:[a-z][a-z0-9+\-.]*:|\/\/)/i.test(href)
return (
<a
@@ -37,9 +75,107 @@ const markdownComponents = {
code: PromptCode,
}
function HarnessBody({ harness }: { harness: MonitoringAgentHarnessSetup }) {
function AgentSetup({ id }: AgentSetupProps) {
const agent = getMonitoringAgent(id)
const harnesses = getMonitoringAgentHarnesses(agent)
const { queryTab, onTabSelected } = useTabsWithQueryParams({
tabIds: harnesses.map((harness) => harness.key),
queryGroup: 'agent-setup',
})
const [selectedHarness, setSelectedHarness] = useState<string>(harnesses[0].key)
const activeHarness = queryTab ?? selectedHarness
const handleHarnessChange = (key: string) => {
setSelectedHarness(key)
onTabSelected(key)
}
return (
<StepHikeCompact title={`Set up ${agent.name}`}>
<StepHikeCompact.Step step={1} title="Copy the prompt">
<StepHikeCompact.Details title="Copy the prompt" />
<StepHikeCompact.Code className="mt-0!">
<div
id={AGENT_PROMPT_ANCHOR}
tabIndex={-1}
className="rounded-lg outline-2 outline-offset-4 outline-transparent"
>
<AiPrompt id={agent.promptId} telemetry={{ source: 'agent_setup' }} />
</div>
</StepHikeCompact.Code>
</StepHikeCompact.Step>
<StepHikeCompact.Step step={2} title="Schedule it in your agent">
<StepHikeCompact.Details title="Schedule it in your agent" />
<StepHikeCompact.Code className="mt-0!">
<CodeTabs value={activeHarness} onValueChange={handleHarnessChange}>
{harnesses.map((harness) => (
<TabPanel
key={harness.key}
id={harness.key}
label={harness.label}
icon={<HarnessIcon harness={harness} />}
>
<SourceFrame
notchWidth={DOCS_NOTCH_WIDTH}
footer={
<a
href={harness.docsUrl}
target="_blank"
rel="noreferrer noopener"
aria-label={`View ${harness.label} docs`}
className={cn(SOURCE_FOOTER_CLASSES, 'pl-2')}
>
<HarnessIcon harness={harness} />
View docs
</a>
}
>
<HarnessBody harness={harness} />
</SourceFrame>
</TabPanel>
))}
</CodeTabs>
</StepHikeCompact.Code>
</StepHikeCompact.Step>
</StepHikeCompact>
)
}
function HarnessIcon({ harness }: HarnessProps) {
const getSrc = (useDarkVariant: boolean) =>
getMcpClientIconSrc({
icon: harness.icon,
useDarkVariant,
hasDistinctDarkIcon: harness.hasDistinctDarkIcon,
})
if (!harness.hasDistinctDarkIcon) {
return <Image src={getSrc(false)} alt="" width={14} height={14} className="size-3.5 shrink-0" />
}
return (
<>
<Image
src={getSrc(false)}
alt=""
width={14}
height={14}
className="size-3.5 shrink-0 dark:hidden"
/>
<Image
src={getSrc(true)}
alt=""
width={14}
height={14}
className="hidden size-3.5 shrink-0 dark:block"
/>
</>
)
}
function HarnessBody({ harness }: HarnessProps) {
return (
<div className="code-sample-surface rounded-lg border border-default bg-200 px-5 pt-4 pb-10 text-sm [&>:first-child]:mt-0 [&>:last-child]:mb-0">
<p>{harness.intro}</p>
<ol>
{harness.steps.map((step) => (
@@ -53,54 +189,7 @@ function HarnessBody({ harness }: { harness: MonitoringAgentHarnessSetup }) {
<ReactMarkdown components={markdownComponents}>{harness.note}</ReactMarkdown>
</p>
)}
<p>
<a
href={harness.docsUrl}
className="text-primary hover:underline"
target="_blank"
rel="noreferrer noopener"
>
{harness.label} docs
</a>
</p>
</>
)
}
function AgentSetup({ id }: AgentSetupProps) {
const agent = getMonitoringAgent(id)
const harnesses = getMonitoringAgentHarnesses(agent)
const { resolvedTheme } = useTheme()
const theme = resolvedTheme?.includes('dark') ? 'dark' : 'light'
return (
<Tabs
defaultActiveId="prompt"
type="underlined"
size="small"
wrappable
queryGroup="agent-setup"
>
<TabPanel id="prompt" label="Prompt" icon={<Sparkles size={14} />}>
<AiPrompt id={agent.promptId} telemetry={{ source: 'agent_setup' }} />
</TabPanel>
{harnesses.map((harness) => (
<TabPanel
key={harness.key}
id={harness.key}
label={harness.label}
icon={
<ConnectionIcon
theme={theme}
connection={harness.icon}
hasDistinctDarkIcon={harness.hasDistinctDarkIcon}
/>
}
>
<HarnessBody harness={harness} />
</TabPanel>
))}
</Tabs>
</div>
)
}
@@ -21,7 +21,8 @@ describe('AgentSetup markdown schema', () => {
it('serializes the prompt and harness setup for a registered agent', () => {
const markdown = AgentSetup({ props: { id: 'health' } })
expect(markdown).toContain('**Prompt**')
expect(markdown).toContain('**Step 1: Copy the prompt**')
expect(markdown).toContain('**Step 2: Schedule it in your agent**')
expect(markdown).toContain('You are "Health monitor"')
expect(markdown).toContain('```text')
expect(markdown).toContain('**Claude**')
@@ -29,6 +30,8 @@ describe('AgentSetup markdown schema', () => {
expect(markdown).toContain('**Cursor**')
expect(markdown).toContain('claude.ai/code/routines')
expect(markdown).toContain('`0 * * * *`')
expect(markdown).toContain('Paste the prompt.')
expect(markdown).not.toContain('](#')
expect(markdown).toContain('[Claude docs](https://code.claude.com/docs/en/routines)')
expect(markdown).toContain('[Codex docs](https://developers.openai.com/codex/app/automations)')
expect(markdown).toContain('[Cursor docs](https://cursor.com/docs/cloud-agent/automations)')
@@ -9,8 +9,10 @@ type HandlerContext = {
props: Record<string, unknown>
}
const IN_PAGE_LINK = /\[([^\]]+)\]\(#[^)]+\)/g
function renderMarkdownSteps(steps: string[]): string {
return steps.map((step, index) => `${index + 1}. ${step}`).join('\n')
return steps.map((step, index) => `${index + 1}. ${step.replace(IN_PAGE_LINK, '$1')}`).join('\n')
}
export function AgentSetup({ props }: HandlerContext): string {
@@ -19,7 +21,8 @@ export function AgentSetup({ props }: HandlerContext): string {
const harnesses = getMonitoringAgentHarnesses(agent)
const sections = [
`**Prompt**\n\n${toMarkdown({ type: 'code', lang: 'text', value: prompt }).trimEnd()}`,
`**Step 1: Copy the prompt**\n\n${toMarkdown({ type: 'code', lang: 'text', value: prompt }).trimEnd()}`,
'**Step 2: Schedule it in your agent**',
...harnesses.map((harness) => {
const parts = [`**${harness.label}**`, harness.intro, renderMarkdownSteps(harness.steps)]
if (harness.note) parts.push(harness.note)
+2 -3
View File
@@ -130,11 +130,10 @@
filter: var(--drop-shadow-codeblock, none);
}
.code-sample-source .shiki {
.code-sample-source :is(.shiki, .code-sample-surface) {
mask:
linear-gradient(#000 0 0),
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='127' height='42'%3E%3Cpath d='M0 40A8 8 0 0 0 8 32V16A8 8 0 0 1 16 8H117A8 8 0 0 0 125 0H127V42H0Z'/%3E%3C/svg%3E")
right -2px bottom -2px / 127px 42px no-repeat;
var(--source-notch-mask) right -2px bottom -2px / var(--source-notch-mask-width) 42px no-repeat;
mask-composite: exclude;
mask-clip: no-clip;
}