write-example

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Writing tldraw examples

编写tldraw示例

The examples project (
apps/examples
) contains minimal demonstrations of how to use the tldraw SDK. Examples are embedded on the docs site and deployed to examples.tldraw.com.
Standards for examples in
apps/examples/src/examples
.
示例项目(
apps/examples
)包含如何使用tldraw SDK的极简演示。示例会嵌入在文档站点中,并部署到examples.tldraw.com
以下是
apps/examples/src/examples
中示例的编写规范。

Example 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-demo
    ,
    magical-wand
  • Used as the URL path for the example
  • 使用小写短横线命名法(kebab-case):
    custom-canvas
    button-demo
    magical-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

前置元数据字段

FieldDescription
titleSentence case, corresponds to folder name
componentRelative path to example file
categoryOne of the valid category IDs (see below)
priorityDisplay order within category (lower = higher)
keywordsSearch terms (avoid obvious terms like "tldraw")
字段说明
title句子式大小写,与文件夹名称对应
component示例文件的相对路径
category有效的分类ID之一(见下文)
priority分类内的展示顺序(数值越小,优先级越高)
keywords搜索关键词(避免使用“tldraw”这类显而易见的词汇)

Valid categories

有效分类

getting-started
,
configuration
,
editor-api
,
ui
,
layout
,
events
,
shapes/tools
,
collaboration
,
data/assets
,
use-cases
getting-started
configuration
editor-api
ui
layout
events
shapes/tools
collaboration
data/assets
use-cases

Example file

示例文件

Naming

命名规则

  • PascalCase ending with "Example":
    CustomCanvasExample.tsx
    ,
    ButtonExample.tsx
  • Name should correspond to the folder name and title
  • 使用帕斯卡命名法(PascalCase)并以“Example”结尾:
    CustomCanvasExample.tsx
    ButtonExample.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
    tldraw__editor
    class for full-page examples
  • Import
    tldraw/tldraw.css
    for styles
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
    style
    prop
  • 将CSS放在与示例同名的独立文件中:
    my-example.css
  • 与tldraw CSS一起导入:
    import './my-example.css'
  • 避免通过
    style
    属性使用大量内联样式

Control panels

控制面板

For examples that need buttons or controls, use the
TopPanel
component slot with
TldrawUiButton
:
tsx
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;
}
对于需要按钮或控件的示例,使用
TopPanel
组件插槽和
TldrawUiButton
tsx
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最佳实践
  • 标题切勿使用标题式大小写,应使用句子式大小写
  • 示例需保持极简且聚焦核心