# CodeBlock

Một khối mã để đọc và sao chép: phần đầu tùy chọn với tên tệp và ngôn ngữ, nút sao chép báo khi đã chép, số dòng, dòng được đánh dấu, và dòng dài cuộn ngang hoặc xuống dòng. Bộ tô màu nhỏ có sẵn tô TS, JS, JSON, CSS, HTML và shell bằng token màu chữ; truyền highlight để cắm bộ khác.

**Phụ thuộc:** npm: 2 trực tiếp, 4 tổng; registry: 3 trực tiếp, 3 tổng.

## Cách dùng

### Khi nào dùng

- Hiện mã để đọc hoặc chép trong tài liệu, hướng dẫn cài đặt hoặc changelog.
- Chỉ ra những dòng quan trọng của một tệp, với số dòng và dòng được đánh dấu.

### Khi nào không dùng

- Một từ hoặc tên ngắn trong câu. Dùng thẻ code trong văn bản.
- Mã người đọc sửa. Dùng trình soạn mã hoặc Textarea.
- Một log dài đang chạy. Dùng khung log cuộn.

## Biến thể

### variant

default nằm lõm trong trang hoặc card, surface nổi trên vùng lõm, plain không nền không viền, cho mã trong một panel khác.

Giá trị: `default`, `surface`, `plain`. Mặc định: `default`.

### size

Cỡ chữ mã, chiều cao dòng và padding: chữ 12, 14 hoặc 16px.

Giá trị: `sm`, `md`, `lg`. Mặc định: `md`.

## Ví dụ

### Tệp

Tên tệp và ngôn ngữ ở phần đầu, nút sao chép ở cuối.

```tsx
<CodeBlock filename="app/page.tsx" language="tsx" code={codeSampleTsx} />
```

### Số dòng và dòng được đánh dấu

highlightLines đánh dấu dòng bằng nền info và một vạch info; đếm từ startLine.

```tsx
<CodeBlock filename="app/page.tsx" language="tsx" code={codeSampleTsx} showLineNumbers highlightLines={[4, 5]} />
```

### Đoạn trích

startLine đánh số đoạn trích theo vị trí của nó trong tệp.

```tsx
<CodeBlock filename="tokens.css" language="css" code={codeSampleCss} showLineNumbers startLine={42} highlightLines={[43]} />
```

### Xuống dòng

Dòng dài mặc định cuộn ngang. showWrapButton thêm nút bật tắt; defaultWrap bắt đầu ở chế độ xuống dòng.

```tsx
<CodeBlock language="bash" code={codeSampleLong} showWrapButton />
```

### Không có phần đầu

Không có tên tệp hoặc ngôn ngữ thì nút sao chép nổi ở góc trên cuối.

```tsx
<CodeBlock language="bash" showLanguage={false} code="npx shadcn@latest add @werewolf/code-block" />
```

### Văn bản thuần

highlight={false} tắt màu; ngôn ngữ không có ngữ pháp sẵn cũng hiện thuần.

```tsx
<CodeBlock filename="notes.txt" highlight={false} code={codeSampleText} />
```

### Bộ tô màu của bạn

Truyền một hàm trả về token cho từng dòng, như hàm dựng từ kết quả của một bộ tô màu phía server.

```tsx
<CodeBlock language="sql" code={codeSampleSql} highlight={highlightSql} />
```

### Mã dài

maxHeight giới hạn chiều cao; mã cuộn cả hai chiều và nhận focus cho bàn phím.

```tsx
<CodeBlock filename="package.json" language="json" code={codeSampleJson} showLineNumbers maxHeight="160px" />
```

## Nên và không nên

### Nên

- Ghi tên tệp khi mã thuộc về một tệp, để người đọc biết dán vào đâu.
- Đánh dấu các dòng đã đổi hoặc được nhắc tới, và nói điều đó trong phần chữ.
- Để dòng dài cuộn ngang cho mã cần chép; thêm nút xuống dòng để đọc trên màn hình hẹp.

### Không nên

- Đừng đặt CodeBlock giữa câu; dùng thẻ code cho một tên hoặc lệnh ngắn.
- Đừng chỉ dựa vào màu để phân biệt dòng; dòng được đánh dấu cần chữ đi kèm.
- Đừng thêm bộ tô màu nặng chỉ để có màu; bộ có sẵn đủ cho các ngôn ngữ thường gặp, và highlight cắm bộ khác khi thật cần.

## Props

| Tên | Kiểu | Giá trị | Mặc định | Mô tả |
| --- | --- | --- | --- | --- |
| `code` (bắt buộc) | `string` |  |  | Mã, dạng văn bản thuần. Đây là thứ nút sao chép chép đi. |
| `language` | `string` |  |  | Ngôn ngữ, như tsx, json, css, html hoặc bash. Hiện ở phần đầu và chọn ngữ pháp có sẵn. |
| `filename` | `string` |  |  | Tên tệp ở đầu phần đầu, như app/page.tsx. Nó cũng đặt tên cho vùng code. |
| `showLanguage` | `boolean` |  | `true` | Hiện ngôn ngữ ở phần đầu. |
| `variant` | `enum` | `default`, `surface`, `plain` | `default` | default nằm lõm trong trang hoặc card, surface nổi trên vùng lõm, plain không nền không viền, cho mã trong một panel khác. |
| `size` | `enum` | `sm`, `md`, `lg` | `md` | Cỡ chữ mã, chiều cao dòng và padding: chữ 12, 14 hoặc 16px. |
| `showLineNumbers` | `boolean` |  | `false` | Đánh số từng dòng. |
| `startLine` | `number` |  | `1` | Số của dòng đầu tiên, cho một đoạn trích từ giữa tệp. |
| `highlightLines` | `number[]` |  |  | Các số dòng được đánh dấu bằng nền info, đếm từ startLine. |
| `wrap` | `boolean` |  |  | Dòng dài xuống dòng thay vì cuộn ngang, khi được điều khiển. |
| `defaultWrap` | `boolean` |  | `false` | Trạng thái xuống dòng ban đầu khi không được điều khiển. |
| `onWrapChange` | `(wrap: boolean) => void` |  |  | Được gọi khi nút xuống dòng được nhấn. |
| `showWrapButton` | `boolean` |  | `false` | Hiện nút bật tắt xuống dòng. |
| `showCopyButton` | `boolean` |  | `true` | Hiện nút sao chép. |
| `onCopy` | `(code: string) => void` |  |  | Được gọi với mã sau khi chép xong. |
| `highlight` | `boolean \| CodeBlockHighlighter` |  | `true` | true dùng bộ tô màu có sẵn, false tắt màu, hoặc một hàm trả về token cho từng dòng. |
| `maxHeight` | `string` |  |  | Chiều cao tối đa của phần mã, như 320px; phần thừa cuộn dọc. |
| `labels` | `{ copy?: string; copied?: string; copyFailed?: string; wrap?: string; highlighted?: string; region?: string }` |  |  | Tên các nút, thông báo và chữ đọc cho dòng được đánh dấu và vùng mã. Mặc định: Copy code, Copied, Couldn't copy, Wrap lines, (highlighted), Code. Tiếng Việt: Sao chép mã, Đã sao chép, Không sao chép được, Xuống dòng, (đánh dấu), Mã. |

## Cấu tạo

| Phần | Mô tả |
| --- | --- |
| `root` | figure: một panel lõm, surface hoặc plain chứa phần đầu và mã. |
| `header` | figcaption: tên tệp và ngôn ngữ ở đầu, các nút ở cuối, trên một đường kẻ nhạt. |
| `name` | Tên tệp, chữ monospace, cắt bằng dấu ba chấm. |
| `label` | Ngôn ngữ, như tsx, bằng chữ secondary. |
| `actions` | Nút xuống dòng và nút sao chép, Button icon ghost cỡ sm. Không có phần đầu thì chúng nổi ở góc trên cuối. |
| `content` | Thẻ pre cuộn ngang khi dòng dài. Nó nhận focus để bàn phím cuộn được. |
| `line` | Một dòng mã. Dòng được đánh dấu có nền info suốt chiều rộng cuộn. |
| `lineNumber` | Số dòng, chữ secondary, căn phải. Chuyển sang chữ info trên dòng được đánh dấu. |

## Khả năng truy cập

Role: `figure`

| Phím | Hành động |
| --- | --- |
| `Tab` | Chuyển tới nút xuống dòng và nút sao chép, rồi tới phần mã, cuộn được bằng phím mũi tên khi dòng dài tràn ra. |
| `Enter / Space` | Trên nút sao chép, chép mã. Trên nút xuống dòng, bật hoặc tắt xuống dòng. |

- Có tên tệp hoặc ngôn ngữ thì figure được đặt tên bằng phần đầu, nên mã được đọc là EN `app/page.tsx tsx`.
- Nút sao chép tên EN `Copy code`. Sau khi chép, tên chuyển thành EN `Copied` trong hai giây và một vùng status thông báo.
- Nút xuống dòng là nút nhấn giữ (aria-pressed), tên EN `Wrap lines`.
- Số dòng bị ẩn khỏi trình đọc màn hình và khỏi vùng chọn, nên khi chép chỉ có mã.
- Dòng được đánh dấu hiện bằng nền info. Hãy nói ý nghĩa của nó trong phần chữ; màu không tới được mọi người đọc.

## Cài đặt

```bash
npx werewolf-ui add code-block
```

Chạy `npx werewolf-ui init` một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem [Cài đặt](https://www.werewolf-ui.dev/vi/docs/installation.md) để biết yêu cầu và cách cài qua registry.
