write-example
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWriting tldraw examples
编写tldraw示例
The examples project () contains minimal demonstrations of how to use the tldraw SDK. Examples are embedded on the docs site and deployed to examples.tldraw.com.
apps/examplesStandards for examples in .
apps/examples/src/examples以下是中示例的编写规范。
apps/examples/src/examplesExample structure
示例结构
Each example lives in its own folder:
apps/examples/src/examples/
└── my-example/
├── README.md # Required metadata
├── MyExampleExample.tsx # Main example file
└── my-example.css # Optional styles每个示例都存放在独立的文件夹中:
apps/examples/src/examples/
└── my-example/
├── README.md # 必填元数据
├── MyExampleExample.tsx # 主示例文件
└── my-example.css # 可选样式文件Folder name
文件夹命名
- Lowercase kebab-case: ,
custom-canvas,button-demomagical-wand - Used as the URL path for the example
- 使用小写短横线命名法(kebab-case):、
custom-canvas、button-demomagical-wand - 会作为示例的URL路径
README.md
README.md
Required frontmatter format:
md
---
title: Example title
component: ./ExampleFile.tsx
category: category-id
priority: 1
keywords: [keyword1, keyword2]
---
One-line summary of what this example demonstrates.
---
Detailed explanation of the example. Include code snippets here if they help explain concepts not obvious from the example code itself.必填的前置元数据格式:
md
---
title: 示例标题
component: ./ExampleFile.tsx
category: 分类ID
priority: 1
keywords: [keyword1, keyword2]
---
该示例演示内容的单行摘要。
---
示例的详细说明。如果有有助于解释示例代码中不明显概念的代码片段,可以在此处添加。Frontmatter fields
前置元数据字段
| Field | Description |
|---|---|
| title | Sentence case, corresponds to folder name |
| component | Relative path to example file |
| category | One of the valid category IDs (see below) |
| priority | Display order within category (lower = higher) |
| keywords | Search terms (avoid obvious terms like "tldraw") |
| 字段 | 说明 |
|---|---|
| title | 句子式大小写,与文件夹名称对应 |
| component | 示例文件的相对路径 |
| category | 有效的分类ID之一(见下文) |
| priority | 分类内的展示顺序(数值越小,优先级越高) |
| keywords | 搜索关键词(避免使用“tldraw”这类显而易见的词汇) |
Valid categories
有效分类
getting-startedconfigurationeditor-apiuilayouteventsshapes/toolscollaborationdata/assetsuse-casesgetting-startedconfigurationeditor-apiuilayouteventsshapes/toolscollaborationdata/assetsuse-casesExample file
示例文件
Naming
命名规则
- PascalCase ending with "Example": ,
CustomCanvasExample.tsxButtonExample.tsx - Name should correspond to the folder name and title
- 使用帕斯卡命名法(PascalCase)并以“Example”结尾:、
CustomCanvasExample.tsxButtonExample.tsx - 名称应与文件夹名称和标题对应
Structure
结构
tsx
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
export default function MyExampleExample() {
return (
<div className="tldraw__editor">
<Tldraw />
</div>
)
}Requirements:
- Must have a default export React component
- Use class for full-page examples
tldraw__editor - Import for styles
tldraw/tldraw.css
tsx
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
export default function MyExampleExample() {
return (
<div className="tldraw__editor">
<Tldraw />
</div>
)
}要求:
- 必须有一个默认导出的React组件
- 全屏示例需使用类
tldraw__editor - 需导入以引入样式
tldraw/tldraw.css
Layout
布局
- Full page: wrap in
<div className="tldraw__editor"> - Inset: see existing examples for page layout patterns
- 全屏:包裹在中
<div className="tldraw__editor"> - 嵌入:参考现有示例的页面布局模式
Styles
样式
- Put CSS in a separate file named after the example:
my-example.css - Import alongside tldraw CSS:
import './my-example.css' - Avoid extensive inline styles via the prop
style
- 将CSS放在与示例同名的独立文件中:
my-example.css - 与tldraw CSS一起导入:
import './my-example.css' - 避免通过属性使用大量内联样式
style
Control panels
控制面板
For examples that need buttons or controls, use the component slot with :
TopPanelTldrawUiButtontsx
import { Tldraw, TldrawUiButton, useEditor } from 'tldraw'
import 'tldraw/tldraw.css'
import './my-example.css'
function MyControls() {
const editor = useEditor()
return (
<div className="tlui-menu my-controls">
<TldrawUiButton type="normal" onClick={() => editor.zoomIn()}>
Zoom in
</TldrawUiButton>
<TldrawUiButton type="normal" onClick={() => editor.zoomOut()}>
Zoom out
</TldrawUiButton>
</div>
)
}
export default function MyExampleExample() {
return (
<div className="tldraw__editor">
<Tldraw components={{ TopPanel: MyControls }} />
</div>
)
}CSS for control panels:
css
.my-controls {
display: flex;
flex-wrap: wrap;
margin: 8px;
}对于需要按钮或控件的示例,使用组件插槽和:
TopPanelTldrawUiButtontsx
import { Tldraw, TldrawUiButton, useEditor } from 'tldraw'
import 'tldraw/tldraw.css'
import './my-example.css'
function MyControls() {
const editor = useEditor()
return (
<div className="tlui-menu my-controls">
<TldrawUiButton type="normal" onClick={() => editor.zoomIn()}>
放大
</TldrawUiButton>
<TldrawUiButton type="normal" onClick={() => editor.zoomOut()}>
缩小
</TldrawUiButton>
</div>
)
}
export default function MyExampleExample() {
return (
<div className="tldraw__editor">
<Tldraw components={{ TopPanel: MyControls }} />
</div>
)
}控制面板的CSS示例:
css
.my-controls {
display: flex;
flex-wrap: wrap;
margin: 8px;
}Comments
注释
Use footnote format with numbered references:
tsx
import { Tldraw, type TLComponents } from 'tldraw'
import 'tldraw/tldraw.css'
// [1]
const components: TLComponents = {
PageMenu: null,
}
export default function CustomComponentsExample() {
return (
<div className="tldraw__editor">
{/* [2] */}
<Tldraw components={components} />
</div>
)
}
/*
[1]
Define component overrides outside the React component so they're static.
If defined inside, use useMemo to prevent recreation on every render.
[2]
Pass component overrides via the components prop.
*/使用带编号引用的脚注格式:
tsx
import { Tldraw, type TLComponents } from 'tldraw'
import 'tldraw/tldraw.css'
// [1]
const components: TLComponents = {
PageMenu: null,
}
export default function CustomComponentsExample() {
return (
<div className="tldraw__editor">
{/* [2] */}
<Tldraw components={components} />
</div>
)
}
/*
[1]
在React组件外部定义组件覆写,确保其为静态属性。
如果在组件内部定义,请使用useMemo防止每次渲染时重新创建。
[2]
通过components属性传递组件覆写配置。
*/Example types
示例类型
Tight examples
精简示例
- Narrow focus on a specific SDK feature
- Minimal styling
- Meant to be read, not used
- Remove any extraneous code
- 聚焦于特定SDK功能
- 样式极简
- 以可读性为核心,而非实用性
- 移除所有无关代码
Use-case examples
场景化示例
- Show a recognizable user experience
- Prioritize clarity and completeness
- Category:
use-cases
- 展示可识别的用户体验
- 优先保证清晰性和完整性
- 分类:
use-cases
Additional files
额外文件
- Split complex code into separate files if it distracts from the example's purpose
- Example: complex input component in
Input.tsx - Keep the main example file focused on demonstrating the concept
- 如果复杂代码会分散示例核心概念的注意力,可将其拆分到独立文件中
- 示例:将复杂输入组件放在中
Input.tsx - 保持主示例文件聚焦于演示核心概念
Important
注意事项
- Follow React and TypeScript best practices
- Never use title case for titles - use sentence case
- Keep examples minimal and focused
- 遵循React和TypeScript最佳实践
- 标题切勿使用标题式大小写,应使用句子式大小写
- 示例需保持极简且聚焦核心