Files
sim/apps/docs/components/ui/code-block.tsx
T
Waleed 3ff91f0439 improvement(docs): clean up leftovers from the code-block alignment PR (#6825)
* improvement(docs): clear leftovers from the reverted revisions

A cleanup pass over the final state. Every finding was residue from an approach
this PR tried and abandoned, or a claim that stopped being true when it did.

- Delete the copy-button svg sizing rule: a later rule sets `display: none` on
  that same element ungated, so sizing it was never observable. Superseded by
  the mask approach.
- Drop the paragraph in page.tsx arguing about a custom Shiki factory. The
  factory was deleted; nothing configures one now.
- Correct shiki-curl-json.ts, which still claimed the grammar "reaches the
  client path too". It does not — that was the justification for choosing a
  grammar over a transformer, so leaving it stated the opposite of the truth.
  Now records where it applies, where it does not, and why not to retry.
- Correct the global.css section header, which claimed the component owns the
  shell while the next rule defines it here.
- Qualify the `--copy-glyph` declarations with `:has(> svg[class*="lucide"])`,
  which the group's own comment asserts of every rule in it.
- Correct `getCode`'s TSDoc: the gutter is a `::before`, and pseudo-element
  content never reaches `textContent`, so line numbers were never what the
  clone guards. It guards transformer-emitted `.nd-copy-ignore` nodes.
- Compose `chipGeometryClass` and emcn's `ChipChevronDown` in the API example
  selector instead of restating their literals.
- Merge the duplicated `div[role="region"]` rule. The tablist pair stays split:
  biome's `noDuplicateProperties` reads a nested `@variant` setting the same
  property as a duplicate and fails the build — recorded so it is not remerged.
- Note that fumadocs ships its own gutter for `lines`-meta fences, which cannot
  be suppressed from here and would paint a second column.

* fix(docs): drop a highlighter registration that can never fire

fumadocs-openapi calls `renderCodeBlock` with a hard-coded `"json"` from both of
its call sites (`request-tabs.js:76`, `response-tabs.js:48`), so the docs
`CodeBlock` it routes through never receives a shell language. The
`getHighlighter('js', { langs: [curlJsonBodyGrammar] })` registering the
shell-scoped JSON-body injection therefore did nothing but await on every API
sample render, and the docblock claiming the grammar covers those samples was
wrong.

- Delete the call and its imports.
- State the grammar's real coverage: prose fences only, via `langs`. Both API
  reference paths are unreachable — samples are JSON, and the cURL usage tabs
  highlight client-side off fumadocs' own factory.
- Correct `code-block.tsx`'s TSDoc, which still said API samples come from
  fumadocs' own renderer. They come through this component; `UsageTab` is the
  renderer that bypasses it.
- Re-home a comment orphaned when two CSS rules merged — it had drifted onto
  the rule below and read as documenting it.
- Drop a `.nd-copy-ignore` claim about transformers emitting those nodes;
  nothing here does, and upstream parity is the reason the clone exists.
2026-08-18 15:28:02 -07:00

83 lines
3.1 KiB
TypeScript

'use client'
import { useRef } from 'react'
import { Button, cn, useCopyToClipboard } from '@sim/emcn'
import { Check, Duplicate } from '@sim/emcn/icons'
import { CodeBlock as FumadocsCodeBlock } from 'fumadocs-ui/components/codeblock'
/** Copy control for a code block — emcn's canonical icon button for a lone glyph affordance. */
function CopyButton({ getCode }: { getCode: () => string }) {
const { copied, copy } = useCopyToClipboard()
return (
<Button
type='button'
variant='quiet'
size='icon'
aria-label={copied ? 'Copied Text' : 'Copy Text'}
onClick={() => copy(getCode())}
/**
* Tailwind v4's preflight sets `button { cursor: default }`. `apps/sim` is on v3, where
* buttons keep the UA pointer, so `buttonVariants` never had to declare one — without
* this the same control feels inert here and live there.
*/
className='cursor-pointer'
>
{copied ? (
<Check className='size-[14px] text-[var(--brand-accent)]' />
) : (
<Duplicate className='size-[14px]' />
)}
</Button>
)
}
/**
* Docs code block for prose fences and the API reference's request/response samples — the MDX
* `pre` mapping and fumadocs-openapi's `renderCodeBlock` both render it.
*
* The shell — radius, hairline, fill — is not set here. A third renderer, fumadocs-openapi's
* `UsageTab`, emits these figures without going through any component, so all three share
* chrome through a `figure.shiki` rule in `global.css` instead; see the note there. What stays
* here is the copy control, and the `my-4` prose rhythm that API samples, which sit flush in
* their panel, override with `my-0`.
*/
export function CodeBlock({ title, ...props }: React.ComponentProps<typeof FumadocsCodeBlock>) {
const figureRef = useRef<HTMLElement>(null)
/**
* Reads the block's text the way fumadocs' own `CopyButton` does: from a clone, with
* `.nd-copy-ignore` nodes replaced by newlines — kept in step with upstream so a fence that
* gains such a node copies the same text there and here. (The line-number gutter is a
* `::before`, and pseudo-element content never reaches `textContent`, so it is not what this
* guards.)
*/
function getCode() {
const pre = figureRef.current?.getElementsByTagName('pre').item(0)
if (!pre) return ''
const clone = pre.cloneNode(true) as HTMLElement
clone.querySelectorAll('.nd-copy-ignore').forEach((node) => node.replaceWith('\n'))
return clone.textContent ?? ''
}
return (
<FumadocsCodeBlock
ref={figureRef}
title={title}
{...props}
className={cn('my-4', props.className)}
allowCopy={false}
/**
* The `className` fumadocs passes this render prop is deliberately neither destructured nor
* merged — its untitled-block variant carries a `backdrop-blur-lg` that goes milky over an
* opaque fill.
*/
Actions={() => (
<div className={cn('flex items-center', title ? '-me-1' : 'absolute top-2 right-2 z-[1]')}>
<CopyButton getCode={getCode} />
</div>
)}
/>
)
}