# @iyulab/desktop-patterns 中文文档

规范地址：https://npmcn.com/package/%40iyulab/desktop-patterns/

版本：0\.13\.0
npm 元数据更新时间：2026-11-01T11:54:37.146Z
中文译文更新时间：2026-11-01T12:42:47.245Z
软件包许可：MIT

本文由上游 README 机器翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40iyulab/desktop-patterns
原文对照：https://npmcn.com/package/%40iyulab/desktop-patterns/?lang=original
项目主页：https://github.com/iyulab/desktop-patterns#readme
源码仓库：https://github.com/iyulab/desktop-patterns

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：72.9 kB，25 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：1 个
- peer 依赖：@iyulab/desktop-compact ^0\.15\.1 \|\| ^0\.16\.0
- 首次发布：2026-09-03T02:46:27.093Z
- 最新版本发布：2026-11-01T11:54:36.812Z
- 已发布版本数：29（近 12 个月 29 个）

## 中文简介

应用程序外壳和结构布局模式组装在上面 [`desktop-compact`](https://github.com/iyulab/desktop-compact)原语。框架无关的自定义元素([点燃](https://lit.dev/))，零内置字符串，每个内容区域都有一个槽。

## 安装

```sh
npm install @iyulab/desktop-patterns
```

也可以使用：`pnpm add @iyulab/desktop-patterns`、`yarn add @iyulab/desktop-patterns`、`bun add @iyulab/desktop-patterns`

## README

# desktop-patterns

应用程序外壳和结构布局模式组装在上面 [`desktop-compact`](https://github.com/iyulab/desktop-compact)原语。体系的中立者自定义 元素([点燃](https://lit.dev/))，零内置字符串，每个内容区域都有一个槽。

仅结构-原子控件（按钮，输入，对话框）属于 `desktop-compact`;本地的 平台集成（文件对话框、托盘、窗口控制）属于桌面运行时本身 适配器层，无论应用使用哪个运行时。这个包本身不调用任何平台API， 并且对任何特定的消费应用程序一无所知。

## 安装

要求节点≥22。

```bash
npm install @iyulab/desktop-patterns @iyulab/desktop-compact
```

只导入你使用的组件——每个船都是它自己的树摇子路径：

```ts
import '@iyulab/desktop-patterns/shell'
import '@iyulab/desktop-patterns/sidebar'
```

或者进口一切通过桶：

```ts
import '@iyulab/desktop-patterns'
```

## 使用

```html
<dp-shell>
  <dp-sidebar slot="sidebar" active-id="overview" header="My App" id="nav"></dp-sidebar>
  <dp-toolbar slot="toolbar" heading="My App" show-toggle></dp-toolbar>
  <dp-page>
    <h2>Overview</h2>
    <p>Main content.</p>
  </dp-page>
</dp-shell>
```

`items`/`bottomItems` 是数组，所以它们被设置为JS属性（不是普通的HTML属性）-相同 作为任何Lit自定义元素：

```ts
document.querySelector<HTMLElementTagNameMap['dp-sidebar']>('#nav')!.items = [
  { id: 'overview', icon: '■', label: 'Overview' },
]

import { desktopMinWidth } from '@iyulab/desktop-patterns/breakpoints' // no elements registered

const shell = document.querySelector('dp-shell')!
const sidebar = document.querySelector('dp-sidebar')!
const toolbar = document.querySelector('dp-toolbar')!
const wide = matchMedia(`(min-width: ${desktopMinWidth}px)`)
let collapsed = false // the consumer's own state: a wide window's sidebar folded to its rail

function sync() {
  sidebar.collapsed = collapsed && wide.matches // a drawer always shows the whole sidebar
  toolbar.expanded = wide.matches ? !collapsed : shell.sidebarOpen
}
wide.addEventListener('change', sync)
sidebar.addEventListener('dp-sidebar-select', () => {
  // consumer owns activeId / routing
})
sidebar.addEventListener('dp-sidebar-activate', () => {
  shell.sidebarOpen = false // a drawer gives way to what was picked — the place already shown included
  sync()
})
toolbar.addEventListener('dp-toolbar-toggle', () => {
  if (wide.matches) collapsed = !collapsed
  else shell.sidebarOpen = !shell.sidebarOpen
  sync()
})
shell.addEventListener('dp-shell-sidebar-close', () => { shell.sidebarOpen = false; sync() }) // backdrop, Escape
```

在桌面断点(`desktopMinWidth`， 1024px - `desktopMedia` （对于组件的样式） 侧边栏是内容上方的一个抽屉，打开时打开 `sidebar-open` 设置;在它上面 侧边栏位于内容和旁边 `sidebar-open` 改变不了什么。使用相同的工具栏开关 两种宽度：在窄窗中打开抽屉，在宽窗中折叠侧边栏 铁轨倒塌(`dp-sidebar` `collapsed`）. 打开开关 `expanded` 所以辅助技术听到了 它处于哪个状态。消费者拥有两种状态——启动时抽屉关闭，关闭时抽屉关闭 shell问（背景点击，逃离），当一个地方被选中，或一个狭窄的窗口保持覆盖。

外壳控制着窗口的高度，所以文档永远不会滚动——主内容框会滚动。 任何保存和恢复用户正在阅读的位置的操作都会到达该框 `shell.mainElement`;与 `@iyulab/router`，把它交给路由器的滚动恢复： `scrollRestoration: { container: () => document.querySelector('dp-shell')?.mainElement }`.

### 被选中的项目旁边的列表

```html
<dp-page fill max-width="full">
  <dp-list-detail>
    <nav slot="list" aria-label="People">…</nav>
    <article>…the person picked…</article>
  </dp-list-detail>
</dp-page>
```

`dp-list-detail` 把 `list` 槽位旁边默认槽位，各自滚动，列表 `--dp-list-detail-list-width` 宽度(默认情况下侧边栏的宽度——导航、列表和项目读取为 1:1:休息)。在桌面断点下面有一个窗格的空间：项目while `detail-open` 是 设置，否则列表。消费者拥有 `detail-open` -当一个项目被选中时设置它，并给予 该项目返回清除它的方式，如下所示 `desktopMinWidth`.

### 侧边栏项：链接、组、图标、动作

```ts
nav.items = [
  { id: 'overview', icon: '■', label: 'Overview', href: '/overview' }, // href → rendered as <a>
  {
    id: 'work', label: 'Work', collapsed: false,                        // a group: a disclosure over its items
    items: [{ id: 'runs', icon: '▶', label: 'Runs', href: '/runs' }],
  },
]
nav.pinnedItems = [{ id: 'settings', icon: '⚙', label: 'Settings' }]   // places kept at the foot of the rail
nav.bottomItems = [
  { id: 'dense', icon: '▤', label: 'Dense mode', pressed: false },    // a toggle: aria-pressed, owned by you
  { id: 'sign-out', icon: '⎋', label: 'Sign out' },                    // actions, not places
]
nav.setAttribute('nav-label', 'Main')                                 // names the navigation landmark
```

-   **`href`** 将项目呈现为链接，这样路由器的链接拦截器（或浏览器）就会进行导航。 `dp-sidebar-select` 仍然可以发射并且可以取消 `preventDefault()` 取消导航并保留 活动项目。修改后的单击（Ctrl/⌘/Shift/Alt，中间按钮）会在其他地方打开链接，但不选择任何内容。 项目没有 `href` 停留按钮和用户导航 `dp-sidebar-select`.
-   **组** （`{ id, label, items, icon?, collapsed? }`)渲染为一个命名的 `role="group"` 根据披露 按钮(`aria-expanded`）. 持有活动项的组始终处于打开状态。在倒塌的铁轨上，每一组 项目显示，由规则分隔。
-   **图标**：每个物品的图标是一个插槽，命名为 `icon-<id>` 项目的退路是谁的 `icon` 文本槽任何图标 元素(`<svg slot="icon-overview">`)来替换它。
-   **`dp-sidebar-activate`** 每次选择导航项时触发，活动项包括(在 `dp-sidebar-select` 当地点改变时；当这个节目被取消的时候就没有了)。关上抽屉就好了：挑着 已经显示的地方仍然意味着“带我去那里”，而且 `dp-sidebar-select` 不为它而火。
-   **固定的地方** （`pinnedItems`)坐在轨道脚下，内部和外部相同的导航地标 滚动列表。它们是这样的地方 `items` - - - - - - `dp-sidebar-select`， `aria-current`， `href` 都适用-所以a 显示的设置或帮助页面被标记为当前页面。
-   **底部的项是操作**：每次点击触发 `dp-sidebar-action` （`itemId`) -每次，所以失败的操作可以 他被重新试了一次，然后再也不动了 `aria-current`． (在0.2。他们开枪了 `dp-sidebar-select` 然后做了主动标记。)
-   **切换操作**底部的动作 `pressed` （`{ id, icon, label, pressed: true | false }`)是一种设置 打开和关闭。按钮携带 `aria-pressed`，打开按钮会得到一个安静的背景和一个重音图标 （`--dp-sidebar-pressed-bg`， `--dp-sidebar-pressed-icon-color`)，这在倒塌的铁轨上仍能看到。以…命名 设置（“密集模式”），而不是点击（“打开密集模式”）。侧边栏不会翻转它-更改值 在 `dp-sidebar-action` 并设置 `bottomItems` 再一次。

每个组件都将其面向用户的文本作为纯属性/属性或插槽——没有 内置i18n层。查看每个组件的Storybook故事(`npm run storybook`)下载完整的API。

## 主题

在应用的全局样式表中导入这两个令牌表：

```ts
import '@iyulab/desktop-compact/tokens.css'
import '@iyulab/desktop-patterns/tokens.css'
```

颜色/间距/半径/排版都来自 `desktop-compact`的 `--dc-*` 令牌-这个包添加 只有结构尺寸 `desktop-compact` 对…没有概念`--dp-sidebar-width`， `--dp-sidebar-width-collapsed`， `--dp-header-height`， `--dp-list-detail-list-width`）. 每个组件都带有相同的回退 值，因此即使没有样式表也能正确呈现。

## 平台边界-阻力区域

`dp-toolbar` 暴露中立 `drag-region` 旗帜（不是本地的） `draggable`，这已经意味着 （其他的），但从不发出任何特定于平台的CSS。旗帜向主人反映 属性，但实际拖动面是专用的 `part="drag-handle"` 起动之间的垫片 组和 `actions` 槽-从来没有整个主机-所以映射永远不能达到切换 按钮或插槽操作。将该部分映射到实际的窗口拖动行为是控件的工作 平台适配器层，以及如何取决于运行时。webview在哪里尊重CSS `app-region` 属性（基于chromium的运行时，如Electron），映射是一个规则：

```css
dp-toolbar[drag-region]::part(drag-handle) {
  -webkit-app-region: drag;
}
```

而从指针事件或标记属性开始窗口拖动的运行时则会执行此操作 同样的部分，不在主机上。

`dp-shell` 不标记任何自己的拖动区域-它对插入的内容没有意见 `toolbar`，因此拖拽句柄的所有权完全保留在那里呈现的任何东西(通常是 `dp-toolbar`）。

## 组件

| 组件 | 描述 |
| --- | --- |
| `dp-page` | 具有居中、最大宽度列的可滚动内容区域——每个视图呈现到的页面主体。与 `fill` 它不滚动，并且它的列与区域一样高，对于滚动其自己的部分的视图（打开的项旁边的列表） |
| `dp-list-detail` | 一个列表旁边的项目从中选择（主-细节）-每个窗格滚动自己；在1024px以下，每次一个窗格 `detail-open` 设置 |
| `dp-sidebar` | App-shell导航栏-展开/折叠状态，可选的固定底部组，a `footer` 任何消费者想要的频道 |
| `dp-toolbar` | 应用程序外壳标题栏 `heading`/`subtitle`一个可选的侧边栏开关（窄窗口中的抽屉，宽窗口中的折叠），一个右侧 `actions` 槽 |
| `dp-shell` | 顶层布局构成 `sidebar`/`toolbar`/`banner`/main-content区域，在1024px的断点下面有一个响应式抽屉（背景+覆盖侧边栏） |
| `dp-shortcut-overlay` | 只显示键盘快捷键帮助面板- a `shortcuts` 列表+ `open` 国旗;没有注册/绑定基础设施（仍然是消费者的） |

运行 `npm run storybook` 以交互方式浏览每个组件，包括 `dp-shell` 构成真正的 `dp-sidebar`+`dp-toolbar`+`dp-page` 在一起。

## 可访问性

每个组件都附带一个可访问性测试，作为其测试套件的一部分(`npm test`）. 地标性建筑 遵循ARIA APG惯例- `dp-sidebar` 使用语义 `<nav>` （没有冗余的主机级角色）， `dp-shortcut-overlay` 使用 `role="dialog"` 与 `aria-labelledby` 指向其可见的标题。

## 开发

```bash
npm install
npm test              # @web/test-runner, real Chromium
npm run typecheck
npm run guard          # platform-neutrality scan (src/ must not call or name a platform API)
npm run build          # per-component ESM output, type declarations
npm run storybook      # interactive component browser
```

`tsc` 是TypeScript 7 (`@typescript/native`),而 `typescript` 解析为 `@typescript/typescript6`： TypeScript 7还没有JavaScript编译器API，而声明build会读取一个。别名是 一次 `vite-plugin-dts` 仅在TypeScript 7上运行。

`@iyulab/desktop-compact` 是一个 **同行** 依赖：这个包读取它的 `--dc-*` 令牌，但从不 导入它的代码，这样使用者安装一个副本，两个包共享它。常规依赖 会给消费者一个更新的吗 `desktop-compact` 次要的第二个，未使用的副本嵌套在此 包中。

## 许可证

麻省理工学院

## 常见问题

### @iyulab/desktop-patterns 是什么？

应用程序外壳和结构布局模式组装在上面 desktop-compact原语。框架无关的自定义元素\(点燃\)，零内置字符串，每个内容区域都有一个槽。

### 如何安装 @iyulab/desktop-patterns？

在项目目录运行 npm install @iyulab/desktop-patterns，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@iyulab/desktop-compact（^0\.15\.1 \|\| ^0\.16\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @iyulab/desktop-patterns 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @iyulab/desktop-patterns 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @iyulab/desktop-patterns 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @iyulab/desktop-patterns 可以商用吗？

@iyulab/desktop-patterns 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @iyulab/desktop-patterns 还在维护吗？

最新版本 0\.13\.0 发布于 2026/11/01（2 天前）；至今共发布 29 个版本，其中过去 12 个月发布了 29 个；首次发布于 2026/09/03。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

