CodeBlock 代码块

成段的代码,带语法着色、语言角标与复制按钮。

import { createRoot } from 'react-dom/client'
import App from './App'
import '@hina-ui/react/styles/tokens.css'

createRoot(document.getElementById('app')!).render(<App />)
tsx
import { CodeBlock } from '@hina-ui/react'

const source = `import { createRoot } from 'react-dom/client'
import App from './App'
import '@hina-ui/react/styles/tokens.css'

createRoot(document.getElementById('app')!).render(<App />)`

export default function Demo() {
  return <CodeBlock code={source} lang="tsx" className="w-full max-w-xl" />
}
tsx

用法

import { CodeBlock } from '@hina-ui/react'
ts

code 是必填属性,内容原样呈现。lang 指定语言,组件据此着色,并在右上角显示语言角标。

pnpm add @hina-ui/react
bash
import { CodeBlock } from '@hina-ui/react'

export default function Demo() {
  return <CodeBlock code="pnpm add @hina-ui/react" lang="bash" className="w-full max-w-xl" />
}
tsx

示例

角标文字

角标默认显示 lang。设置 label 可以改为文件名或其他说明,着色仍然依据 lang。

export default defineNuxtConfig({
  css: ['@hina-ui/react/styles/tokens.css'],
})
nuxt.config.ts
import { CodeBlock } from '@hina-ui/react'

const source = `export default defineNuxtConfig({
  css: ['@hina-ui/react/styles/tokens.css'],
})`

export default function Demo() {
  return <CodeBlock code={source} lang="ts" label="nuxt.config.ts" className="w-full max-w-xl" />
}
tsx

不着色

不指定 lang 时不着色,也不显示角标,代码按原样呈现。命令行输出与纯文本适合这样使用。

✔ 依赖安装完成
✔ 样式入口已就绪
  运行 pnpm dev 启动开发服务器
import { CodeBlock } from '@hina-ui/react'

const output = `✔ 依赖安装完成
✔ 样式入口已就绪
  运行 pnpm dev 启动开发服务器`

export default function Demo() {
  return <CodeBlock code={output} className="w-full max-w-xl" />
}
tsx

复制按钮

右上角默认带复制按钮。设置 copyable 为 false 可以移除它。

git switch -c feature/hina-ui
bash
import { CodeBlock } from '@hina-ui/react'

export default function Demo() {
  return (
    <CodeBlock
      code="git switch -c feature/hina-ui"
      lang="bash"
      copyable={false}
      className="w-full max-w-xl"
    />
  )
}
tsx

超长的行

代码不换行。超出宽度时在代码块内横向滚动,页面本身不会被撑宽。滚动区可以聚焦,聚焦后能用方向键滚动。

const theme = { accent: 'var(--hn-accent)', radius: 'var(--hn-radius-lg)', shadow: 'var(--hn-shadow-sm)', font: 'var(--hn-font-sans)' }
ts
import { CodeBlock } from '@hina-ui/react'

const source = `const theme = { accent: 'var(--hn-accent)', radius: 'var(--hn-radius-lg)', shadow: 'var(--hn-shadow-sm)', font: 'var(--hn-font-sans)' }`

export default function Demo() {
  return <CodeBlock code={source} lang="ts" className="w-full max-w-md" />
}
tsx

高度

使用 className 或 style 设置 height,超出高度的代码在内部纵向滚动。长行仍可横向滚动,角标和复制按钮固定在右上角。

const value1 = { name: 'Hina UI', enabled: true }
const value2 = { name: 'Hina UI', enabled: true }
const value3 = { name: 'Hina UI', enabled: true }
const value4 = { name: 'Hina UI', enabled: true }
const value5 = { name: 'Hina UI', enabled: true }
const value6 = { name: 'Hina UI', enabled: true }
const value7 = { name: 'Hina UI', enabled: true }
const value8 = { name: 'Hina UI', enabled: true }
const value9 = { name: 'Hina UI', enabled: true }
const value10 = { name: 'Hina UI', enabled: true }
const value11 = { name: 'Hina UI', enabled: true }
const value12 = { name: 'Hina UI', enabled: true }
const value13 = { name: 'Hina UI', enabled: true }
const value14 = { name: 'Hina UI', enabled: true }
const value15 = { name: 'Hina UI', enabled: true }
const value16 = { name: 'Hina UI', enabled: true }
ts
import { CodeBlock } from '@hina-ui/react'

const source = Array.from(
  { length: 16 },
  (_, index) => 'const value' + (index + 1) + " = { name: 'Hina UI', enabled: true }",
).join('\n')

export default function Demo() {
  return <CodeBlock code={source} lang="ts" className="h-48 w-full max-w-lg" />
}
tsx

设置 max-height 可以限制最大高度。内容较少时保持自然高度,超出上限后才出现纵向滚动。

const value1 = { name: 'Hina UI', enabled: true }
const value2 = { name: 'Hina UI', enabled: true }
const value3 = { name: 'Hina UI', enabled: true }
const value4 = { name: 'Hina UI', enabled: true }
const value5 = { name: 'Hina UI', enabled: true }
const value6 = { name: 'Hina UI', enabled: true }
const value7 = { name: 'Hina UI', enabled: true }
const value8 = { name: 'Hina UI', enabled: true }
const value9 = { name: 'Hina UI', enabled: true }
const value10 = { name: 'Hina UI', enabled: true }
const value11 = { name: 'Hina UI', enabled: true }
const value12 = { name: 'Hina UI', enabled: true }
const value13 = { name: 'Hina UI', enabled: true }
const value14 = { name: 'Hina UI', enabled: true }
const value15 = { name: 'Hina UI', enabled: true }
const value16 = { name: 'Hina UI', enabled: true }
ts
import { CodeBlock } from '@hina-ui/react'

const source = Array.from(
  { length: 16 },
  (_, index) => 'const value' + (index + 1) + " = { name: 'Hina UI', enabled: true }",
).join('\n')

export default function Demo() {
  return <CodeBlock code={source} lang="ts" className="max-h-48 w-full max-w-lg" />
}
tsx

预先着色

html 属性接受已经着色好的 HTML。传入之后组件不再运行着色,直接呈现该内容,code 仍用于复制。

在服务端或者构建时完成着色,可以让浏览器不必下载着色器。

const accent = '#39c5bb'
ts
import { CodeBlock } from '@hina-ui/react'

const code = `const accent = '#39c5bb'`
const html = `<span style="color:#8250df">const</span><span> accent = </span><span style="color:#0a3069">'#39c5bb'</span>`

export default function Demo() {
  return <CodeBlock code={code} html={html} lang="ts" className="w-full max-w-xl" />
}
tsx

无障碍

  • 滚动区可以聚焦,聚焦后用方向键滚动,焦点框出现在代码块外沿。
  • 滚动区的无障碍名称取自角标,未设置角标时为通用名称。
  • 复制按钮的名称为“复制代码”,复制成功后变为“已复制”。

API

Props

属性
类型
默认值
说明
code
string
—
必填。代码文本,同时用于复制
lang
string
—
语言,决定着色与角标
label
string
—
角标文字,覆盖 lang
html
string
—
预先着色好的 HTML,传入后不再着色
copyable
boolean
true
是否显示复制按钮
className
string
—
追加至根元素的类名