Nasaq
Components

CodeBlock variants

Code in tabs (pnpm npm yarn, curl JS Python), a copy menu for AI assistants, and a one-line command with a direct copy button. Composes CodeBlock.

PreviewOpen ↗

Code

import { CodeTabs, packageManagerTabs } from "@fadymondy/nasaq/web";export function Install() {  return <CodeTabs syncKey="pm" aiCopy tabs={packageManagerTabs("@nasaq/web")} />;}

Developer Tools · stable

Live examples and controls: CodeBlock variants in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/code-block-variants.json

Three ways to present code that build on CodeBlock without changing it. CodeTabs shows one snippet in several forms (package managers, languages) and copies the visible one. CodeBlockAI and CodeCopyMenu add a copy menu: Copy code, Copy as Markdown, and a ready prompt for Claude, ChatGPT or Cursor, with links that open the assistant with the prompt filled in. CommandSnippet is a one-line command with a copy button that is always visible. Every panel is a real CodeBlock, so highlighting, line numbers and left-to-right code in Arabic pages come for free.

When to use

  • Install and quick-start docs where the reader picks their package manager or language.
  • Snippets a reader will hand to an AI assistant (the menu builds the prompt for them).
  • A single terminal command to copy: npm i @nasaq/web.

When not to use

Import

import { CodeTabs, CodeBlockAI, CommandSnippet, packageManagerTabs } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"

Quick start

import { CodeTabs, packageManagerTabs } from "@fadymondy/nasaq/web";

export function Install() {
  return <CodeTabs syncKey="pm" aiCopy tabs={packageManagerTabs("@nasaq/web")} />;
}

Anatomy

CodeTabs          data-slot="code-tabs"           <div dir="ltr">
├─ tab list       (Tabs)                          pnpm | npm | yarn | bun
└─ panel          CodeBlock                       one per tab, copy button or copy menu in the header
CodeBlockAI       CodeBlock with copyAction=CodeCopyMenu
CodeCopyMenu      data-slot="code-copy-menu"      split button + DropdownMenu
CommandSnippet    data-slot="command-snippet"     <div dir="ltr"> prompt + command + CopyButton

API

CodeTabs

PropTypeDefaultDescription
tabsCodeTab[]required{ value?, label, code, language?, filename? }.
value? / defaultValue? / onValueChange?stringfirst tabControlled or uncontrolled selection.
syncKey?stringnoneBlocks sharing a key switch together (choose pnpm once, every install block follows).
title?stringnoneText before the tabs, e.g. a filename.
aiCopy?boolean | { instruction?, targets?, openLinks?, onCopy? }falseUse the AI copy menu instead of the copy button.
lineNumbers?booleanfalseGutter numbers.
preClassName?stringnoneClasses for the scrolling <pre>.
label?string"Code variants" / "صيغ الشيفرة"Accessible name of the tab list.
labels?Partial<CodeVariantLabels>built-in en/arTranslations.

CodeBlockAI

Everything CodeBlock takes, plus instruction?, targets? (["claude","chatgpt","cursor"]), openLinks? (default true), onCopy?(kind, text, target?) and menuLabels?.

CodeCopyMenu

The split button on its own: code, language?, filename?, instruction?, targets?, openLinks?, onCopy?, labels?. Pass it to CodeBlock as copyAction.

CommandSnippet

PropTypeDefaultDescription
commandstringrequiredThe command. A leading $ is dropped from the copy.
prompt?string | false"$"Glyph shown before the command, never copied.
onCopy?(command: string) => voidnoneAfter a successful copy.
label?string"Command" / "أمر"Accessible name of the command region.

Helpers

packageManagerTabs(pkg, { dev?, global?, managers? }), execTabs(command, { managers? }), installCommand, execCommand, toMarkdown(code, language?, filename?), buildPrompt({ code, language, filename, instruction, target }), aiLink(target, prompt) (a URL, or null when the prompt is too long for a link), stripPrompt. All pure functions.

Examples

Languages

<CodeTabs
  tabs={[
    { label: "curl", language: "bash", code: 'curl -H "Authorization: Bearer $KEY" https://api.example.com/v1/me' },
    { label: "JavaScript", language: "js", code: 'const me = await fetch("/v1/me").then((r) => r.json());' },
    { label: "Python", language: "python", code: 'me = requests.get("https://api.example.com/v1/me").json()' },
  ]}
/>

Copy for AI

<CodeBlockAI language="ts" filename="retry.ts" instruction="Explain this and add jitter." code={source} />

Accessibility

KeyAction
Arrow keysMove between tabs
TabTab list, code region, then the copy control
Enter / SpaceCopy, or open the menu on the chevron
EscCloses the menu
  • Tabs and the menu are Base UI, so roles, roving focus and focus return are handled.
  • Copy results are announced in a live region.
  • The "open in" items are links that open in a new tab; they say so in their label.

RTL & i18n

  • Code, tab labels and commands are dir="ltr" inside Arabic pages. The menu and its labels follow the page.
  • Built-in strings in English and Arabic; override with labels.
  • Very long prompts do not fit a link: the prompt is copied instead and the message says so.
  • Assistant names are shown as text; no logos are bundled.

Styling & tokens

  • Surfaces and borders: bg-nq-surface-soft, border-border, rounded-control. Hover uses bg-nq-hover, focus outline-nq-focus.
  • Slots: code-tabs, code-copy-menu, command-snippet.

Do / Don't

  • Do give related install blocks the same syncKey.
  • Do set instruction so the prompt says what you want done.
  • Don't put secrets in a snippet that offers "open in": the code goes into the link.
  • Don't use tabs for more than about five variants.

Lab

https://docs.nasaqui.com/?path=/docs/components-developer-tools-code-block-variants--docs

On this page