@bundu/ui

中文文档
0.13.0发布于 2026/11/05MITTypeScriptES Module构建来源已验证近 30 天下载 3735

Bundu生态系统的营销UI工具包——Nyuchi实施Mzizi设计系统. 所有21个Mzizi彩色家族(7个矿物、7个遗产、7个实验性)在一个 -- -- 彩色*命名空间、9步地表梯子、连接状态t

中文使用文档
文档目录10 节
  1. 这是什么
  2. 生成, 不转录
  3. 安装
  4. 快速使用
  5. 英雄们
  6. App图案 (0. 3. 0)
  7. 产品- Dash板外壳
  8. 发现模式(Mzizi 发现标准)
  9. 构成部分合同
  10. 许可证

@bundu/ ui (英语)

Bundu生态系统的营销UI工具箱——编辑Astro的构件外加Mzizi活字牌上的Shadcn风格回放原始(所有21个彩色家族).

npm Lint License: MIT

重现 : mzizi-dev/packages-npm (英语: | 结构 : mzizi.dev (英语)


这是什么

销售站点背后的共享组件层(bundu, nyuchi, mukoko). 这是Nyuchi执行 姆齐兹 设计 - Bundu基金会的一个开放建筑项目,运营和 由Nyuchi开发。 这个包裹不是Mzizi本身.

  • Astro营销组件 —— 说 Hero, (中文(简体) ), Section, (中文(简体) ), SectionHeader, (中文(简体) ), Container, (中文(简体) ), MineralStrip, (中文(简体) ), Icon, (中文(简体) ), SocialIcon,以及 Breadcrumb (emits 有效计划.org) BreadcrumbList JSON-LD for Google rich results. (原始内容存档于2018-09-27).

  • Astro形式和媒体组件 —— 说 SegmentedControl (本地无线电), NativeSelect, (中文(简体) ), Toaster (单位:千美元)window.toast() )和 SafeAreaFrame (几何学: safeAreaBands 从软件包根中导入,以 @bundu/ui/<Name>.astro,除登记原始人 Alert, (中文(简体) ), Button, (中文(简体) ), Card, (中文(简体) ), Input, (中文(简体) ), Label, (中文(简体) ), Skeleton 财务报告和审定财务报表 StatusBadge各自保持其登记册 合同(contracts/ui/); 应用模式处于下 @bundu/ui/app/* (下关.

  • Markdown,通过建筑安全 —— 说 MarkdownRenderer (单位:千美元)@bundu/ui/MarkdownRenderer.astro, (中文(简体) ), 合同 ui/markdown-renderer) (中文(简体) ). 它解释 content 绘制成 元素,从不通过 HTML 字符串。 源代码中的 Raw HTML 显示为文本, 链接通过 方案允许列表( :links="safe"、默认值、保存 https、 https、 mailto、 电话和相对 地址; links="https" 仅保留 https; 拒绝的链接保留其单词. from="html" 或者说 "auto" 阅读编辑的丰富文本 headingBase 设置关卡 a # 标题 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你还好吧? 它从中吸取的解析器是 @bundu/ui/markdown-parse数字 : markdownBlocks(), (中文(简体) ), safeHref() 和块和内线类型, 对于代码需要树,而不是标记.

    ---
    import MarkdownRenderer from "@bundu/ui/MarkdownRenderer.astro";
    ---
    <MarkdownRenderer content={post.body} headingBase={2} />
    
  • 阴影 CVA + cn() 反应原始人 —— 说 Button, (中文(简体) ), Card, (中文(简体) ), Badge, (中文(简体) ), Input, (中文(简体) ), Textarea, (中文(简体) ), Select, (中文(简体) ), Label, (中文(简体) ), Alert, (中文(简体) ), Avatar, (中文(简体) ), Separator, (中文(简体) ), Skeleton, (中文(简体) ), Switch, (中文(简体) ), Checkbox, (中文(简体) ), Tabs, (中文(简体) ), Tooltip。 。 。 .

  • 整个Mzizi调色板 —— 说 styles/tokens.css 全部携带 21个有色家庭 在一个下 --color-* 命名空间:7个矿物,7个遗产色调,7个实验色调. 加九步地表梯(--pitch, (中文(简体) ), --void, (中文(简体) ), --base, (中文(简体) ), --surface, (中文(简体) ), --container, (中文(简体) ), --overlay, (中文(简体) ), --raised, (中文(简体) ), --scrim, (中文(简体) ), --wash)和连通性 状态三进制( r)--syncing, (中文(简体) ), --offline, (中文(简体) ), --neutral) (中文(简体) ).

  • 尾风 v3 和 v4 —— 说 styles/theme.css 是一个本地 v4 @theme 入场点; tailwind-preset.mjs 是 v3- 形状的预设, 仍在发运并仍在工作( v4 载重) 它穿过 @config) (中文(简体) ).

  • 品牌覆盖 —— 说 brand-bundu, (中文(简体) ), brand-nyuchi, (中文(简体) ), brand-mukoko, (中文(简体) ), brand-shamwari, (中文(简体) ), brand-mzizi和子应用程序 brand-events (木科克事件), brand-lingo, (中文(简体) ), brand-bushtrade, (中文(简体) ), brand-campfire, (中文(简体) ), brand-news, (中文(简体) ), brand-weather, (中文(简体) ), brand-kweli, (中文(简体) ), brand-learning 财务报告和审定财务报表 brand-circles (木科克圆. brand-nhimbe 是再出口的已贬值的别名 brand-events (nhimbe品牌已退役;事件平台为Mukoko事件). 每个重点 --primary 财务报告和审定财务报表 --ring 矿物质来自 克能生态系统表. brand-circles 另设 --brand-accent (特拉科塔语), 哪个牌子的手杖排着一个口音.

  • tokens.json ——机器可读值相同,包括每个自定义属性 对于完全无法消耗 CSS 的表面, 解为每个模式的字面六进制 : 博览会( E)mukoko-weather-mobile)和以佐藤里为主的OG-图像/电子邮件/PDF生成器.

生成, 不转录

styles/tokens.css, (中文(简体) ), styles/theme.css, (中文(简体) ), tokens.json, (中文(简体) ), tailwind-palette.mjs 和每个 styles/brand-*.css 为: 生成 以 scripts/generate-tokens.mjs 从 tokens/canon.snapshot.json,它本身是机器写 scripts/fetch-canon.mjs 从划道上 :

来源用品
https://api.mzizi.dev/api/v1/brand21个家庭,语义符号,背景阶梯,光线,品牌-矿表
mzizi-dev/mzizi-registry → lib/tokens/palette.source.ts矿物 onContainer 成对, 哪个 /v1/brand 不预测

两人在每逢交接的时候,都要互相考核。如果他们对一击有分歧, 获取失败 而不是默默地偏爱它。 这种分歧就是遗产 最后是四个不同的地铁.

十六进制值 没有 生活在数据库中。 Mzizi没有品牌或原始的象征数据 在Supabase或其他任何地方——0.1.1's tokens.css 信头说错了.

三道城门,都不得空出:

命令网络运行失败的时间
pnpm tokens:check没有每一个CI工作, prepack生成的文件与生成器不一致
pnpm canon:parity对仅CI承诺的快照已经从活的峡谷飘来飘去
pnpm canon:fetch对需求aPI和 palette.source.ts 异议

canon:parity 拒绝在CI以外运行 --force因此它不能爬入建筑物 或运行时路径。 手机回家制作一个页面的标志性软件包是一页 aPI的下午是空白的,情况不妙.

每个值都通过 CSS 自定义属性来流动 / Tailwind sords —— 从来没有生六分之一英寸 来源。 。 。 .

安装

pnpm add @bundu/ui
# peer deps (for the React primitives)
pnpm add react react-dom

快速使用

1a. 尾风v4(建议) - 一个样式表,没有 tailwind.config.mjs 完全没有:

@import "tailwindcss";
@import "@bundu/ui/styles/theme.css"; /* @imports tokens.css, adds @theme */
@import "@bundu/ui/styles/globals.css"; /* the @layer rules the Astro components use, and density.css */
@import "@bundu/ui/styles/color-scheme.css"; /* optional: follow the OS dark setting */
@import "@bundu/ui/styles/brand-nyuchi.css";
@source "../../node_modules/@bundu/ui/src"; /* v4 does not scan node_modules itself */

color-scheme.css 选择进入. tokens.css 只变暗 .dark 或者说 [data-theme="dark"],此文件在 prefers-color-scheme: dark,用于没有主题脚本的网站。 明确 data-theme="light" 仍然赢了。 在品牌覆盖前导入.

theme.css 搭载调色板、类型比例(text-display . text-caption页:1 读取宽度( r)max-w-narrow和命名的间隔,所以 globals.css是因为 @apply 规则 而组件的类解而无预设。 尾风进口 tokens.css 一次 尽管两个文件都提到它。 Astro组件使反应原生 (例如 Hero按钮,所以一个Astro网站也需要 @astrojs/react没有 client:* 他们向静态 HTML 提供指令, 并且没有JavaScript .

平地和密度. globals.css 进口 styles/density.css从 登记:正文文本 17px, 标题 14px, 每个控件上的49px击出区域( 控件可能 在桌面密度下绘制 28-40px,以及 a hit-area 覆盖保持49px命中区域, 以及作为公用事业的部件的作用大小(h-control, (中文(简体) ), h-control-sm, (中文(简体) ), h-control-lg, (中文(简体) ), size-control-icon, (中文(简体) ), h-field, (中文(简体) ), min-h-touch-min) (中文(简体) ). 这些公用设施解决了 没有它,什么都没有。 将棋子分别导入的应用程序( Q)theme.css 财务报告和审定财务报表 tokens.css,没有 globals.css必须在其后面加上:

@import "@bundu/ui/styles/theme.css";
@import "@bundu/ui/styles/density.css";

<html data-mzizi-sizes="legacy"> 恢复地板前的尺寸( 16px 身体, 12px) 标题, 48/ 56px 控件), 直到一个应用程序迁移 。 移民表:mzizi-注册 docs/sizes-and-density.md。 。 。 .

1b. 有尾风v3或v4通过 @config - 与0.1.x不变,仍然支持:

@import "tailwindcss";
@import "@bundu/ui/styles/tokens.css"; /* or globals.css for the @layer rules */
@import "@bundu/ui/styles/brand-nyuchi.css";
@config "../../tailwind.config.mjs";
// tailwind.config.mjs
import preset from "@bundu/ui/tailwind-preset";

export default {
  presets: [preset],
  content: ["./src/**/*.{astro,html,js,jsx,md,mdx,ts,tsx,vue}"],
};

2. 浏览器外部 - 博览会、佐藤里会、PDF:

import tokens from "@bundu/ui/tokens.json" with { type: "json" };

tokens.resolved.dark["--color-sodalite"]; // "#3d5afe"
tokens.color.heritage.savanna.dark; // "#e5c158"
tokens.surface.base.light; // "#f3f3f1"

3. 组件:

---
import Hero from "@bundu/ui/Hero.astro";
import Container from "@bundu/ui/Container.astro";
import MineralStrip from "@bundu/ui/MineralStrip.astro";
import Breadcrumb from "@bundu/ui/Breadcrumb.astro";
import { deriveBreadcrumbs } from "@bundu/ui";

const crumbs = deriveBreadcrumbs(Astro.url.pathname, { about: "About" }, "Nyuchi");
---

<MineralStrip />
<Hero title="Build in the open" subtitle="Bundu Ecosystem" />
<Container>
  <Breadcrumb items={crumbs} origin={Astro.site?.toString()} />
</Container>
import { Button } from "@bundu/ui/ui/button";
import { Alert, AlertTitle } from "@bundu/ui/ui/alert";

export function CTA() {
  return (
    <>
      <Alert variant="success">
        <AlertTitle>Saved</AlertTitle>
      </Alert>
      <Button variant="primary" href="/start" arrow>
        Get started
      </Button>
    </>
  );
}

英雄们

---
import Hero from "@bundu/ui/Hero.astro";
---

<!-- 0.1.x usage, unchanged: a single text column -->
<Hero
  title="Build in the open"
  subtitle="Bundu Ecosystem"
  description="One line that says what this is."
  primaryCTA={{ text: "Get started", href: "/start" }}
  secondaryCTA={{ text: "Read the docs", href: "https://docs.example.org", external: true }}
/>

<!-- Split: text beside a live demo at lg, stacked (text first) below it -->
<Hero
  layout="split"
  variant="showcase"
  badge="Beta"
  title="A short, bold headline"
  description="One line of subtext."
  primaryCTA={{ text: "Try it", href: "#demo" }}
  mediaLabel="Live demo"
>
  <div slot="media"><!-- your demo, screenshot or widget --></div>
</Hero>
Prop类型默认页:1
titlestring—— 说这个 h1。 。 。 .
subtitlestring—— 说眉从头而上.
descriptionstring—— 说分文一段.
primaryCTA{ text, href, external? }—— 说药扣.
secondaryCTA{ text, href, external? }—— 说以一箭为鬼扣.
variant"default" | "gradient" | "light" | "showcase""default"showcase 洗了这个牌子 --primary 和钴过 --background; 只有符号.
align"start" | "center""start"
layout"stack" | "split""stack"split 设置文本和 media 位置并肩从 lg。 。 。 .
badgestring—— 说头条上面的状态药丸 它被理解为权利主张,所以要准确.
mediaLabelstring—— 说媒体区域无障碍名称(role="group") (中文(简体) ).
media (分数)标记—— 说文本列旁或下方的(分块).

没有 media 插槽,没有 badge, (中文(简体) ), layout 左侧 stack 和一个0.1.x variant, (中文(简体) ), Hero 调制 字节相同 标记为0.1.1。 每一个建筑都检查过了 与公布的0.1.1 焦油球相配合.

见 建 议.md 用于完整的工具链——mzizi MCP、shadcn CLI、 21个有色人种,和"无生克"规则.

App图案 (0. 3. 0)

服务器为已登录的应用程序和控制台提供组件 @bundu/ui/app/*他们是 纯天体: 无反应( 或任何框架) 他们和没有客户JavaScript, 正如Mzizi学说有它为Astro。 过滤器 是获取表单, 调用是链接, 菜单是 <details>祝酒词被取消 带有隐藏复选框标签。 每个颜色都是一种标志, 所以光和暗 跟着 tokens.css 编号 : color-scheme.css。分类食谱与 反应原始人通过 @bundu/ui/ui/variants,所以两个建筑看起来都是一样的.

构成部分它会做什么
AppShell.astro粘性顶条( R)brand, (中文(简体) ), account 边栏导航 lg 和下面的披露, main#main
SideNav.astro附有标签和摘要的部分清单; aria-current="page" 关于当前项目; 48px目标
AccountMenu.astro签名者、 账户动作的插槽( 外观窗体、 链接) 和签出 POST 格式
PageHeader.astro这页是一页 <h1>描述,面包屑, actions 插槽
DataTable.astro真实的 <table> 带有标题和范围标题; 窄屏幕上每行一张牌; 单元格是数据而不是标记
FilterBar.astro搜索并选择过滤器为 a role="search" 获取窗体; 设置时“ 清除 ”
Pagination.astro"显示112的26-50"和上个,编号和下个链接;当一个页面足够时隐藏
DetailPanel.astro一个记录作为描述列表,一个可选的"全面记录"JSON披露,一个 actions 插槽
FormLayout.astro有标题的表单卡;卡宽时分出两个栏(容器查询);表单级别提醒; enctype 用于文件
FormField.astro可见标签和一个输入(文本、数字、日期、文件.)、文本区域或选择,并带有提示和有线错误 aria-describedby 财务报告和审定财务报表 aria-invalid· ; wide 横跨两列
StateMessage.astro空、 出错、 不配置、 不可用和装入( skeleton) 有固定措辞的状态
Toast.astro最后一项行动的结果是:一个有礼貌的居住区;在被解雇之前继续居住(WCAG 2.2.3)
StatTile.astroA 中的一个标题图 <dl>: 标签, 值 ("不可用", 从不可用 0) 以文字写成的趋势
BarChart.astro列或行为 SVG, 标题 <figure>,从不拥挤的轴线标签,以及披露下真实表格中的确切数字
Button.astro<a> 与 href,则 <button>· ; appButtonVariants,包含. destructive 财务报告和审定财务报表 destructive-outline
Badge.astroMzizi登记册 badge 合同: default, (中文(简体) ), secondary, (中文(简体) ), destructive, (中文(简体) ), outline, (中文(简体) ), ghost, (中文(简体) ), link
Card.astro, (中文(简体) ), Alert.astro, (中文(简体) ), Input.astro, (中文(简体) ), Label.astro, (中文(简体) ), Skeleton.astro这些原始的图案都是由纯洁的Astro建造的

@bundu/ui/lib/table 以纯洁的助手为后盾 DataTable, (中文(简体) ), FilterBar 财务报告和审定财务报表 Pagination数字 : parseTableQuery (URL ) 查询,被夹住), filterRows (每个字, 大小写和重音不敏感,加上精确匹配的过滤器), paginate 财务报告和审定财务报表 withParams。 。 。 .

---
import AppShell from "@bundu/ui/app/AppShell.astro";
import SideNav from "@bundu/ui/app/SideNav.astro";
import AccountMenu from "@bundu/ui/app/AccountMenu.astro";
import PageHeader from "@bundu/ui/app/PageHeader.astro";
import FilterBar from "@bundu/ui/app/FilterBar.astro";
import DataTable from "@bundu/ui/app/DataTable.astro";
import Pagination from "@bundu/ui/app/Pagination.astro";
import { filterRows, paginate, parseTableQuery, withParams } from "@bundu/ui/lib/table";

const query = parseTableQuery(Astro.url.searchParams, ["role"]);
const rows = filterRows(people, query, (p) => [p.name], (p, f) => (f === "role" ? p.role : null));
const page = paginate(rows, query.page, query.perPage);
---

<AppShell>
  <a slot="brand" href="/">Your app</a>
  <AccountMenu slot="account" name="Tendai Moyo" email="[email protected]" signOutAction="/auth/logout" />
  <SideNav slot="nav" items={[{ href: "/people", label: "People", summary: "Everyone in your family" }]} />

  <PageHeader title="People" description="Everyone in your family." />
  <FilterBar searchLabel="Search people" q={query.q} values={query.filters} clearHref={withParams(Astro.url, { q: null, role: null, page: null })} />
  <DataTable
    caption={`People, ${page.total} in all`}
    columns={[{ key: "name", label: "Name" }, { key: "role", label: "Role" }]}
    rows={page.rows.map((p) => ({ name: { text: p.name, href: `/people/${p.id}` }, role: { text: p.role, badge: "outline" } }))}
  />
  <Pagination url={Astro.url} {...page} noun="people" />
</AppShell>

他们只需要Astro和Tailwind v4 上面的设置,包括 @source 线条可以生成软件包中的类. BarChart 大小其条 作为 SVG 几何, 绝不内置 style因此,内容-安全政策不需要 style-src-attr 'unsafe-inline'。 。 。 .

DataTable 徽章( 符号){ text, badge })取注册徽章变体. 在此之前 0.3.0 控制台的拷贝使用了反应器的矿物变体 Badge· ; primary 还有 default 在这里。 记录下,一个牢房 tone (单位:千美元){ text, tone }数字 : neutral, (中文(简体) ), success, (中文(简体) ), warning, (中文(简体) ), info, (中文(简体) ), accent, (中文(简体) ), premium(中文(简体) ) 是一种状态药丸,使用固定状态颜色( p)statusToneClasses 内 @bundu/ui/ui/variants(三); tone 胜过 badge。 。 。 .

产品- Dash板外壳

应用图案制造出一个全宽的产品仪表板, 稠密的像一个 控制台,而不是像营销版那样的客房.

构成部分它会做什么
AppShell.astro整个取景口:一个固定的16.25雷姆侧边栏(workspace, (中文(简体) ), search, (中文(简体) ), nav 插槽,从下方切入一个倒塌的切换)和填充其余部分的主柱(一个薄的上边栏 brand, (中文(简体) ), actions, (中文(简体) ), account; 页面; footerLinks 编号 : footer) (中文(简体) ). 没有以页为中心的容器 。 折叠到3.5rem图标栏上(真正的复选框); collapsed 财务报告和审定财务报表 persist 保持整个页面。 64rem下方的侧边栏为一出出坎瓦斯抽屉:与波波弗API弹出式相同元素,因此"逃出"并点击外侧关闭. overlay a 时段 CommandPalette
SideNav.astrogroups (或0.3平方英尺) items),每个项目的一个图标, badge ("新"),被嵌入项在切夫龙披露下(当孩子是当前时打开),当下项被填入一金指标. 仅标签: 一个物品 description 是一个关于悬浮和键盘焦点及其 aria-describedby;在倒塌的栏杆上,工具提示也显示标签
WorkspaceSwitcher.astro产品标记( :mark a) 用于当前工作空间 <details> 工作空间和链接的列表,或当没有可切换到的纯链接主机
QuickSearch.astro + 键 CommandPalette.astro侧边栏的搜索按钮带有QQ提示打开调色板(popovertarget: 每一个导航项,分组,作为链接,并与 action a 服务器的搜索表单
TopBarAction.astro上行的图标和标签链接或按钮 (“ Ask AI ” 、“ 支持 ” ); 图标仅下方 sm 以标签为名称
Toolbar.astro + 键 ToolbarMenu.astro一个全宽的 GET 搜索框加入按钮组; ToolbarMenu 是一个 <details> 链接列表( 日期范围)
StatTiles.astro相邻一行等同 StatTile有发线分接器; StatTile 收益 info
InfoTip.astro可聚焦信息图标,其工具提示是其可访问描述
EmptyState.astro相接卡:一个标题、帮助文本和动作; StateMessage kind="empty" 用这个
BrandMark.astro克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克brand="mukoko", 蜂窝: Mzizi 注册处的光/暗图标对对, 缩放, 永不重画, 小写 sarif wordmark 和 当被问及时的哑音后缀; CSS 每个主题的右变体

@bundu/ui/app/nav 纯洁的助手们 groupNav 转弯 平面单行登记group, (中文(简体) ), parent(一) 成群结队; currentHref 选择最长的匹配格里夫; searchNav 编号 : matchesQuery 匹配每一个字,大小写和重音不敏感.

密度. Button, (中文(简体) ), Input, (中文(简体) ), FilterBar, (中文(简体) ), DataTable, (中文(简体) ), Pagination, (中文(简体) ), DetailPanel, (中文(简体) ), FormLayout, (中文(简体) ), PageHeader 财务报告和审定财务报表 StatTile 使用应用程序密度 (单位:千美元)appButtonVariants, (中文(简体) ), appInputClasses 内 @bundu/ui/ui/variants: 36px (英语) 控件, 14px文本和~40px表格行带有精细指针; 44–48px目标 和 16px 触摸输入 (pointer-coarse:) (中文(简体) ). 内向 AppShell 使用该 身体圣贤。 营销原始人不变.

文选. 两个组件各带一个小模块,两个组件均不工作 内容: AppShell (它写着崩溃的选择) persist 饼干和酒 逃脱隐藏工具提示)和 CommandPalette (QQK / Ctrl+K 快捷键, 实时) 使用已宣布的计数、 Enter 和箭头键过滤 。 键盘 cSS 无法进行快捷键和活过滤。 Astro把它们装作文件, 这样 script-src 'self' 如果应用程序不内入小脚本, CSP 将有效 (一组) vite.build.assetsInlineLimit: 0) (中文(简体) ).

---
import AppShell from "@bundu/ui/app/AppShell.astro";
import BrandMark from "@bundu/ui/app/BrandMark.astro";
import CommandPalette from "@bundu/ui/app/CommandPalette.astro";
import QuickSearch from "@bundu/ui/app/QuickSearch.astro";
import SideNav from "@bundu/ui/app/SideNav.astro";
import TopBarAction from "@bundu/ui/app/TopBarAction.astro";
import WorkspaceSwitcher from "@bundu/ui/app/WorkspaceSwitcher.astro";
import { groupNav } from "@bundu/ui/app/nav";

const groups = groupNav(
  [
    { href: "/", label: "Home", icon: "home" },
    { href: "/people", label: "People", icon: "users", group: "Identity & people", description: "Everyone in your organisation" },
    { href: "/keys", label: "API keys", group: "Developer", parent: "/dev" },
    { href: "/dev", label: "Developer", icon: "terminal", group: "Developer" },
  ],
  ["Identity & people", "Developer"],
);
---

<AppShell collapsed={Astro.cookies.get("sidebar")?.value === "collapsed"} persist="sidebar" footerLinks={[{ label: "Status", href: "https://status.example" }]}>
  <WorkspaceSwitcher slot="workspace" name="Nyuchi Africa" href="/"><BrandMark slot="mark" wordmark suffix="console" /></WorkspaceSwitcher>
  <QuickSearch slot="search" target="palette" />
  <SideNav slot="nav" groups={groups} />
  <TopBarAction slot="actions" label="Support" icon="help" href="/support" />
  <slot />
  <CommandPalette slot="overlay" id="palette" groups={groups} action="/search" />
</AppShell>

发现模式(Mzizi 发现标准)

Mukoko家族的每个公开发现和浏览页面都有一个设计: 网络上的超级应用 纯Astro,没有 客户端JavaScript,没有内置样式. 11个构成部分 @bundu/ui/discover/*数字 :

构成部分这是什么
DiscoverShell跳过链接,矿物条,头条(品牌,主导航,一个动作), <main id="main">页脚
DiscoverMeta<head> 标记:标题、机器人、犬科、开放图形、X卡、JSON-LD
DiscoverHero面包屑,眉毛,那个 <h1>,引导,然后 search 财务报告和审定财务报表 actions 插槽
DiscoverSearch获取搜索表单, 每个指针48px
CategoryChips命名导航 CategoryChip 连接
CategoryChip与计数的一类联系; current 标记它
DiscoverSection被命名的乐队:眉毛,取向,描述,"看见所有",内容
ResultGrid状态行,牌,空状态和"再加载";布局 grid, (中文(简体) ), list, (中文(简体) ), rail
DiscoverCard一张牌,变型 article, (中文(简体) ), event, (中文(简体) ), circle, (中文(简体) ), place,分享一个解剖学
LoadMore光标标记: 1 rel="next" 链接到 ?cursor=…
OpenInApp“在Mukoko打开”动作: https链接和一条线
---
import DiscoverShell from "@bundu/ui/discover/DiscoverShell.astro";
import DiscoverHero from "@bundu/ui/discover/DiscoverHero.astro";
import DiscoverSearch from "@bundu/ui/discover/DiscoverSearch.astro";
import DiscoverSection from "@bundu/ui/discover/DiscoverSection.astro";
import ResultGrid from "@bundu/ui/discover/ResultGrid.astro";
import DiscoverCard from "@bundu/ui/discover/DiscoverCard.astro";
import LoadMore from "@bundu/ui/discover/LoadMore.astro";
---
<DiscoverShell homeLabel="mukoko circles, home" nav={[{ label: "All circles", href: "/circles" }]}>
  <span slot="brand">mukoko circles</span>
  <DiscoverHero size="home" eyebrow="Mukoko Circles" title="Find your people.">
    <DiscoverSearch slot="search" label="Search circles" />
  </DiscoverHero>
  <DiscoverSection id="featured" title="Circles worth joining" seeAllHref="/circles">
    <ResultGrid label="Featured circles" summary={`${circles.length} circles`}>
      {circles.map((c) => <DiscoverCard variant="circle" href={c.href} title={c.name} initial={c.name[0]} meta={[c.members]} />)}
      <LoadMore slot="more" href={next} label="More circles" />
    </ResultGrid>
  </DiscoverSection>
</DiscoverShell>

尾风必须看到组件的类: 加 @source "../../node_modules/@bundu/ui/src"; (您 CSS 文件的路径) 之后 @bundu/ui 进口.

服务器装满了贝壳 . 每个发现组件在页面出现时也会工作 使用 {{placeholders}} 并有一个服务器填充(作为圆.mukoko.). 连锁店 Rust Worker确实如此:文本道具是纯字符串,空文本隐藏自己 状态开关( t)ResultGrid state, (中文(简体) ), LoadMore state, (中文(简体) ), DiscoverCard badgeTone, (中文(简体) ), CategoryChip current)是按类排序的属性,所以模板需要 没有逻辑.

构成部分合同

每个应用程序和发现器组件都带有合同,就像Mzizi建造的所有设备一样。 这个 合同由Mzizi登记处撰写 (单位:千美元)mzizi-dev/mzizi-registry, (中文(简体) ), contracts/(中文(简体) ) 并在此发送, 每个组件一个 JSON 文件 :

import contract from "@bundu/ui/contracts/app/side-nav.contract.json" with { type: "json" };

每个都说明部件的道具和插槽的类型、行为和命名 状态、可获取性(作用、键盘、焦点、ARIA),精度和密度 粗指针, 主题( 仅覆盖品牌符号; 布局从未因 (b) 无JavaScript的倒置和反应规则,加上 contract … end block 在Mzizi语言的条款语法中。 计划是 @bundu/ui/contracts/schema/component-contract.schema.json。 。 。 .

src/app/contracts.test.ts 使每个指定状态的每个组件 评估其合同:条款、选择器检查、密度表和 品牌覆盖规则。 跑者不能评估的条款失败,同样失败 任意内行 style 属性( 一页的 CSP 从来不需要) style-src-attr 'unsafe-inline') (中文(简体) ). contracts/app/ 这是 姆齐齐板 标准 财务报告和审定财务报表 contracts/discover/ 页:1 Mzizi 发现标准 (docs.mzizi.dev) (英语).

上游为先. 应用程序需要的组件不在这里,或更改为 换句话说,你马上过来(和合同) 一个 应用程序仅在 PR 打开、标记时保存本地副本 TODO(mzizi): <PR URL>。 。 。 .

不编辑 contracts/ 在这里。 那就换个登记册吧 pnpm contracts:fetch (或 pnpm contracts:check [ref] 比较).

许可证

麻省理工学院 Nyuchi非洲(Pvt)有限公司.

版本与发布记录

@bundu/ui 共发布 14 个版本,首次发布于 2026/07/03;过去 12 个月发布了 14 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.13.0latest2026/11/053 天前
0.12.02026/11/044 天前
0.11.02026/11/044 天前
0.10.02026/11/044 天前
0.9.02026/11/035 天前
0.8.02026/11/035 天前

关于 @bundu/ui 的常见问题

@bundu/ui 是什么?

Bundu生态系统的营销UI工具包——Nyuchi实施Mzizi设计系统. 所有21个Mzizi彩色家族(7个矿物、7个遗产、7个实验性)在一个 -- -- 彩色*命名空间、9步地表梯子、连接状态t

如何安装 @bundu/ui?

在项目目录运行 npm install @bundu/ui,或使用 pnpm add / yarn add / bun add。

@bundu/ui 支持 TypeScript 吗?

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

@bundu/ui 支持 ESM 还是 CommonJS?

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

@bundu/ui 可以商用吗?

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

@bundu/ui 的下载量有多少?

根据 npm 官方下载统计,@bundu/ui 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,735 次,日均约 125 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bundu/ui 还在维护吗?

最新版本 0.13.0 发布于 2026/11/05(3 天前);至今共发布 14 个版本,其中过去 12 个月发布了 14 个;首次发布于 2026/07/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。