④段整套同步(六节 + P/S/F/J + 模板)+ open-design 移到技能根
一、④段整套同步(用户选候选 A)
- 新增 `references/stage-proto-doc/assets/产品文档模板.html`(16 KB/247 行,从备份拷、转 LF)。
- ④段 SKILL.md 换成备份 15:28 那版,并按模板口径改齐:
· 「产品文档框架」从「四块+一附录」改成**六节** —— 页面结构/功能清单/使用场景/操作流程/
跨页与界面状态/待确认与偏离;与模板同构,⛔ 不从空白页重写结构。
· 编号从 R/S/F 改成 **P 页面/S 场景/F 功能/J 二级功能**,各自唯一、按展示顺序通排。
· 保留旧版有价值的要求:每项功能补齐 做什么/入口在哪/输入边界/异常与恢复;重点功能三处标红;
横向流程图每步写清页面/功能/操作/完成判据。
· 完成标准「七节」→「六节」,自查清单同步换掉「需求」那批条目,补模板与配图两条。
· 路径 `designs/<项目>/` → `docs/pm/<项目>/ui/`(2 处)。
· 补回本机那条「每份产出文档开头都要有一张图」的引用(指向主 skill,段内不复述)。
- 主 skill 同步:四段结构表④行、④段沿革、画图小节(④段画页面结构图 + 用户路径)。
二、open-design 移到技能根(用户选候选 A)
- `git mv product-planning/references/stage-delivery/assets/open-design → open-design/`(4178 文件)。
- `.gitignore` 白名单加 `!/open-design/` —— 否则移出去就不再纳入版本控制。
- 引用改 11 处:路径形态 `assets/open-design/...` → `<技能根>/open-design/...`;
「随段携带的自带件」改称「同根技能」;「路径怎么找」那条改成自带件(段内相对路径)与
同根技能(`<技能根>/<技能名>/`)两类分开写。
- open-design 自己的 ATTRIBUTION.md 两处同步(它现在与 oil-ui-pro 同层)。
- 副作用(有益):命名闸门读数由 2063 降到 225 —— 此前它把 open-design 里 919 个第三方 md
当成规则一起扫了;现在只扫本包 23 个 md。已确认④段的 H1 与 4a/4b/4c 子步仍在检查范围内。
三、验收
- check_naming.py --ws E:/ProgramData/AIProject/contentm_agent = 通过 225 / 失败 0 / 提示 27。
- 活文件里 `assets/open-design` 残留 0;工作区 CRLF 文件 0。
This commit is contained in:
1 parent
fa0a9026c8
commit
5afeb6b78a
4184 files changed
+326
-70
No files matched your search
@@ -0,0 +1,136 @@
|
||||
# Cloudflare Kumo UI Design System
|
||||
|
||||
> Category: Developer Tools
|
||||
> A compact, semantic component language for modern web applications: layered neutral surfaces, precise Inter typography, accessible controls, automatic light/dark color roles, and task-appropriate chart palettes.
|
||||
|
||||
## Provenance and intended use
|
||||
|
||||
This is an **OpenDesign curated integration** of Cloudflare's Kumo UI, not an official Cloudflare-maintained OpenDesign package and not an endorsement or partnership. It is based only on Cloudflare's official sources:
|
||||
|
||||
- [Kumo documentation](https://kumo-ui.com/), including the color, accessibility, component, and chart guidance.
|
||||
- [`cloudflare/kumo`](https://github.com/cloudflare/kumo/tree/0c5832575c99988917b81cd752002e10f3dc9c7a) at commit `0c5832575c99988917b81cd752002e10f3dc9c7a`.
|
||||
- npm package `@cloudflare/kumo` version `2.9.2`.
|
||||
- Upstream license: MIT, Copyright (c) 2026 Cloudflare, Inc.
|
||||
|
||||
Use this package for developer tools, infrastructure consoles, administration surfaces, data-heavy dashboards, and product workflows that benefit from Kumo's compact component density. The package translates Kumo's semantic roles into OpenDesign's shared token contract; it does not vendor the React library, its components, or Cloudflare assets.
|
||||
|
||||
## Visual principles and atmosphere
|
||||
|
||||
Kumo interfaces are quiet, compact, and operational. Start with a near-white canvas (`--bg: oklch(98.75% 0 0)`) and white component surfaces (`--surface: #ffffff`). Use the recessed neutral (`--surface-warm: oklch(96% 0 0)`) for segmented controls, table tints, or nested regions; despite the OpenDesign slot name, this surface is neutral rather than warm.
|
||||
|
||||
Build depth with surface hierarchy, rings, and restrained shadows instead of decorative gradients. Kumo's official order is canvas → base component → elevated layer → recessed/tinted region. A `LayerCard`-style surface uses an `8px` radius, a semantic ring, and a small shadow. Keep related labels, descriptions, and actions tightly grouped; allow larger gaps only between separate tasks or sections.
|
||||
|
||||
Prefer sentence-case headings, short action-oriented labels, and content-first composition. Avoid uppercase headings, altered tracking, bold-heavy typography, oversized marketing treatments, and stacked cards inside cards. Inline icons should align with the first line of adjacent text, especially when labels can wrap.
|
||||
|
||||
## Semantic color system and themes
|
||||
|
||||
Choose tokens by role, never by the hue you happen to want. The light-mode bindings are:
|
||||
|
||||
| OpenDesign token | Kumo role | Value |
|
||||
| --- | --- | --- |
|
||||
| `--bg` | canvas | `oklch(98.75% 0 0)` |
|
||||
| `--surface` | base component | `#ffffff` |
|
||||
| `--surface-warm` | recessed compatibility tier | `oklch(96% 0 0)` |
|
||||
| `--fg` | default text | `oklch(21% 0.006 285.885)` |
|
||||
| `--muted` | subtle text | `oklch(55.6% 0 0)` |
|
||||
| `--border` | line beside elevation | `oklch(14.5% 0 0 / 0.1)` |
|
||||
| `--border-soft` | hairline between flat surfaces | `oklch(93.5% 0 0)` |
|
||||
| `--accent` | brand background | `oklch(0.5772 0.2324 260)` |
|
||||
| `--accent-hover` | brand-background hover | `oklch(48.8% 0.243 264.376)` |
|
||||
| `--success` | success indicator | `oklch(59.6% 0.145 163.225)` |
|
||||
| `--warn` | warning indicator | `oklch(73.9% 0.177 58.2)` |
|
||||
| `--danger` | error/destructive indicator | `oklch(63.7% 0.237 25.331)` |
|
||||
|
||||
Set `data-mode="dark"` to follow Kumo's native mode hook. In generated OpenDesign artifacts, `data-theme="dark"` resolves the same override. Dark mode changes semantic values rather than adding `dark:` utility variants: the canvas becomes `oklch(10% 0 0)`, component surfaces become `oklch(17% 0 0)`, primary text becomes `oklch(97% 0 0)`, and the line/hairline pair becomes `oklch(32% 0 0)` / `oklch(26.9% 0 0)`.
|
||||
|
||||
Do not substitute Cloudflare orange (`#f6821f`) for every primary control. Kumo distinguishes its orange brand text role from the blue semantic brand background used by primary actions. Use semantic status colors only when meaning is present, and use tints or neutral surfaces behind longer status copy rather than flooding an interface with solid status color.
|
||||
|
||||
## Typography and hierarchy
|
||||
|
||||
Use Inter for display and body text, with system sans-serif fallbacks. Use the system monospace stack for code, identifiers, configuration keys, and tabular technical data. Inline monospace should be optically smaller than surrounding prose, following Kumo's guidance of roughly `0.9em`.
|
||||
|
||||
The base Kumo text scale is deliberately compact:
|
||||
|
||||
| Token | Size | Typical role |
|
||||
| --- | --- | --- |
|
||||
| `--text-xs` | `12px` | captions, compact labels |
|
||||
| `--text-sm` | `13px` | dense secondary controls |
|
||||
| `--text-base` | `14px` | body, buttons, data, interactables |
|
||||
| `--text-lg` | `16px` | small heading or emphasized content |
|
||||
| `--text-xl` | `20px` | dialog or card title |
|
||||
| `--text-2xl` | `24px` | section heading |
|
||||
| `--text-3xl` | `30px` | page heading |
|
||||
| `--text-4xl` | `36px` | OpenDesign compatibility ceiling |
|
||||
|
||||
Body leading is `1.5`; display leading is `1.2`. Keep `--tracking-display: 0`: the official Kumo design skill explicitly avoids manual tracking. Use weight `600` for headings, `500` for emphasized inline text and control labels, and `400` for ordinary copy. Do not use `700` as the default emphasis mechanism.
|
||||
|
||||
## Spacing, density, radius, and layout
|
||||
|
||||
Kumo components use compact Tailwind utility spacing on a `4px` rhythm. The shared bindings are `4`, `8`, `12`, `16`, `20`, `24`, `32`, and `48px`. Related text commonly uses `4–8px`; control clusters use `8–12px`; card interiors use `16px`; distinct task groups use `24–32px`. Apply slightly less vertical than horizontal padding when that produces better optical alignment, such as `20px` horizontal with `16px` vertical.
|
||||
|
||||
Control radii map to Kumo's `rounded-sm`, `rounded-md`, and `rounded-lg` patterns: `4px`, `6px`, and `8px`; reserve `9999px` for pills, circular icon actions, and status shapes. Nested shapes within `8px` of each other must use concentric radii: outer radius equals inner radius plus the intervening padding.
|
||||
|
||||
Kumo does not publish global section or container tokens, so the following are explicitly OpenDesign compatibility bindings rather than upstream claims: section spacing is `64px` desktop, `48px` tablet, and `32px` phone; the container cap is `1200px` with `24px`, `16px`, and `12px` gutters. Treat these as starting values for product dashboards, not as Cloudflare layout specifications.
|
||||
|
||||
## Components and composition patterns
|
||||
|
||||
- **Buttons:** Default to the secondary style for ordinary actions. Reserve the primary blue treatment for the highest-emphasis action and use destructive styling only for consequential actions. Base controls are `36px` high with `8px` radii; Kumo also supports compact `20px` and `26px` sizes and a `40px` large size. Icon-only buttons require an accessible label.
|
||||
- **Fields and inputs:** Pair controls with visible labels when possible. Inputs and buttons of the same size should align. Error content must be associated with its field, and placeholder text must not replace an accessible name.
|
||||
- **Layered cards:** Use a base surface with a line ring and small shadow, or compose a restrained elevated header with a base content layer. Never nest `LayerCard` treatments inside one another.
|
||||
- **Dialogs:** Keep dialogs mounted and drive visibility through open state so entry and exit motion can complete. Use `role="alertdialog"` for destructive confirmations and critical acknowledgements; use an ordinary dialog for forms and general content. Kumo's documented widths range from `288px` to `768px`.
|
||||
- **Navigation and disclosure:** Keep active, hover, and focus states distinct. Preserve component-native keyboard behavior for menus, tabs, selects, command palettes, and collapsibles.
|
||||
- **Loading:** Disable a loading action, retain its label when useful, and show a labeled spinner. Use skeleton lines for content-shaped loading, with stable dimensions to prevent layout shift.
|
||||
|
||||
Use semantic HTML before visual styling. A button performs an in-place action; a link navigates. Heading appearance must not determine heading level: choose `h1`–`h6` according to the document outline.
|
||||
|
||||
## Interaction, focus, disabled, and loading states
|
||||
|
||||
Every interactive element needs separate default, hover, active, focus-visible, disabled, and loading behavior. For a primary action, use `--accent`, switch immediately to `--accent-hover` on hover, and use the same value for active because Kumo does not publish a separate brand-active token. White (`--accent-on`) remains the label color on the saturated action surface.
|
||||
|
||||
Use `--focus-ring` as a visible `2px` ring. Its light value is Kumo focus near-black (`oklch(15% 0 0)`); its dark value is the light neutral `oklch(93.5% 0 0)`. Do not rely on a color-only hover change as the keyboard indicator. Disabled controls retain their form, remove interaction, use an appropriate inactive/subtle foreground, and must not be communicated by opacity alone when the state would become ambiguous.
|
||||
|
||||
Hover color changes are immediate in Kumo's design guidance; do not attach the motion tokens to simple color swaps. Use `150ms` for short opacity or transform state changes and `250ms` with `cubic-bezier(0.77, 0, 0.175, 1)` for larger disclosure or sidebar movement. Loading spinners need an accessible status label, and skeletons should preserve the eventual content footprint.
|
||||
|
||||
## Data visualization and chart color use
|
||||
|
||||
Select a chart palette by the data task:
|
||||
|
||||
- **Semantic:** use attention `#FC574A`, warning `#F8A054`, success `#00A63E`, neutral `#B9D6FF`, disabled `#CBCBCB`, and skeleton `#DDDDDD` when data has status, severity, or health meaning.
|
||||
- **Categorical:** for nominal series, use the ordered light palette `#4290F0`, `#F5B647`, `#E8649D`, `#8D58EE`, `#50C3B6`, and `#D37536`. Cycle by modulo only when more series are unavoidable; prefer showing a small number of important categories.
|
||||
- **Sequential:** for one magnitude, use `#E1EAF4`, `#8EBCF6`, `#4290F0`, `#0E58B4`, and `#03254F` from low to high in light mode. Dark mode reverses prominence so higher values remain visually strongest.
|
||||
|
||||
Do not use categorical color for ordered magnitude or semantic color for unrelated series. Color alone must not encode a distinction: pair line series with dashes or markers, provide labels and legends, and ensure patterns remain legible when colors are perceived similarly.
|
||||
|
||||
## Accessibility and keyboard behavior
|
||||
|
||||
Kumo is built on Base UI and provides ARIA roles, pointer behavior, keyboard navigation, and focus management for many components, but consumers still own correct labels, contrast, document structure, and visible focus styling. Preserve the provided behavior for arrow keys, alphanumeric typeahead, `Home`, `End`, `Enter`, and `Escape` where the component supports it.
|
||||
|
||||
Associate labels and errors with form controls. Add `aria-label` or `aria-labelledby` when no visible label exists, including icon-only controls. Supply alternative text for meaningful images and do not claim blanket WCAG conformance: verify actual foreground/background pairings in the generated interface. Keep focus indicators visible on every background, and restore focus appropriately when overlays close.
|
||||
|
||||
Use more than color to communicate errors, success, selection, and chart series. Avoid disabled text on a surface if contrast becomes unreadable. Preserve native button, link, table, form, and heading semantics instead of rebuilding them with generic containers.
|
||||
|
||||
## Motion and reduced motion
|
||||
|
||||
Motion should explain a state change, not decorate the interface. Kumo uses `150ms` transitions for dialogs, switches, popovers, and small state changes, while its sidebar defaults to `250ms` with the easing stored in `--ease-standard`. Keep collapsing content at a stable intrinsic width or height so text does not reflow during the exit.
|
||||
|
||||
Respect `prefers-reduced-motion: reduce`. This package sets `--motion-fast` and `--motion-base` to `0ms` in reduced-motion mode. Generated components must also stop continuous decorative motion, replace smooth scrolling with immediate movement, and preserve all information when an animation is removed. A necessary progress indicator may remain functional, but it still needs a textual status that does not depend on motion.
|
||||
|
||||
## Do and avoid
|
||||
|
||||
**Do**
|
||||
|
||||
- Use semantic surface, text, border, status, and focus roles so light and dark modes stay synchronized.
|
||||
- Keep content text at `14px`, headings sentence-cased, and emphasis at medium or semibold weights.
|
||||
- Group related content tightly and separate independent tasks with clear space or a hairline.
|
||||
- Use rings with shadows, concentric radii, and a single primary action per decision point.
|
||||
- Align icons with the first line of text and give icon-only controls accessible names.
|
||||
- Match chart color systems to semantic, categorical, or sequential data tasks.
|
||||
|
||||
**Avoid**
|
||||
|
||||
- Raw palette colors when a semantic role exists, or manual `dark:` variants that bypass the theme.
|
||||
- Uppercase headings, altered letter spacing, default bold (`700`) text, or oversized marketing typography.
|
||||
- Slow hover color transitions, ornamental motion, or animations that ignore reduced-motion preferences.
|
||||
- Borders combined indiscriminately with shadows; use Kumo's line/hairline ring hierarchy.
|
||||
- Nested LayerCards, conditional dialog mounting, placeholder-only form labels, or unlabeled icon buttons.
|
||||
- Claiming that OpenDesign's compatibility section/layout bindings are official Kumo tokens.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Cloudflare Kumo UI Usage
|
||||
|
||||
Agent-facing guidance for the OpenDesign curated integration of Cloudflare Kumo UI.
|
||||
|
||||
## Read Order
|
||||
|
||||
1. Read this file for the package contract and source boundary.
|
||||
2. Read `DESIGN.md` for Kumo's visual intent, semantic roles, component patterns, and accessibility guidance.
|
||||
3. Paste the complete `tokens.css` into the first artifact `<style>` block before writing component CSS.
|
||||
4. Read `components.manifest.json` for the compact inventory, then inspect `components.html` when selectors or interaction states matter.
|
||||
5. Use the `preview/` pages for quick color, typography, spacing, and radius checks.
|
||||
6. Consult `source/evidence.md` before making an upstream-fidelity claim.
|
||||
|
||||
## Design Highlights
|
||||
|
||||
- Use semantic surface roles to move from a near-white canvas through base, recessed, and elevated layers.
|
||||
- Keep product text compact: `14px` is the default content size, with sentence-case headings and restrained semibold emphasis.
|
||||
- Use the blue semantic brand background for primary actions; do not replace it with Cloudflare orange.
|
||||
- Prefer line rings and small shadows to decorative gradients or heavy elevation.
|
||||
- Use Kumo's native `data-mode="dark"` hook; `data-theme="dark"` is included only for OpenDesign artifact compatibility.
|
||||
- Treat the section, container, and extended heading tokens as OpenDesign compatibility bindings, not upstream Kumo tokens.
|
||||
|
||||
## Do
|
||||
|
||||
- Choose tokens by semantic role and keep raw colors inside the canonical token block.
|
||||
- Default ordinary actions to secondary buttons and reserve the primary treatment for the main decision.
|
||||
- Preserve visible labels, native semantics, keyboard behavior, focus-visible rings, and non-color status cues.
|
||||
- Reuse the fixture's buttons, fields, status badge, layer card, and data layout before introducing a new pattern.
|
||||
- Keep loading controls disabled and labeled, and preserve layout dimensions while content loads.
|
||||
- Respect reduced-motion preferences and keep information available without animation.
|
||||
|
||||
## Avoid
|
||||
|
||||
- Avoid presenting this package as official, endorsed, or maintained by Cloudflare.
|
||||
- Avoid raw Tailwind palette colors, manual `dark:` variants, uppercase headings, altered tracking, or default `700` weight.
|
||||
- Avoid nested LayerCards, placeholder-only field labels, unlabeled icon buttons, or color-only status communication.
|
||||
- Avoid long hover transitions; Kumo color changes are immediate and larger state motion stays brief.
|
||||
- Avoid editing `components.manifest.json` by hand; it is derived from `components.html` and `tokens.css`.
|
||||
@@ -0,0 +1,198 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Cloudflare Kumo UI - reference components</title>
|
||||
<meta name="description" content="Reference fixture for the OpenDesign Cloudflare Kumo UI integration: compact semantic surfaces, precise controls, visible states, and operational data density." />
|
||||
<style>
|
||||
:root {
|
||||
--bg: oklch(98.75% 0 0);
|
||||
--surface: #ffffff;
|
||||
--surface-warm: oklch(96% 0 0);
|
||||
--fg: oklch(21% 0.006 285.885);
|
||||
--fg-2: var(--fg);
|
||||
--muted: oklch(55.6% 0 0);
|
||||
--meta: var(--muted);
|
||||
--border: oklch(14.5% 0 0 / 0.1);
|
||||
--border-soft: oklch(93.5% 0 0);
|
||||
--accent: oklch(0.5772 0.2324 260);
|
||||
--accent-on: #ffffff;
|
||||
--accent-hover: oklch(48.8% 0.243 264.376);
|
||||
--accent-active: var(--accent-hover);
|
||||
--success: oklch(59.6% 0.145 163.225);
|
||||
--warn: oklch(73.9% 0.177 58.2);
|
||||
--danger: oklch(63.7% 0.237 25.331);
|
||||
--font-display: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-body: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--text-xs: 12px;
|
||||
--text-sm: 13px;
|
||||
--text-base: 14px;
|
||||
--text-lg: 16px;
|
||||
--text-xl: 20px;
|
||||
--text-2xl: 24px;
|
||||
--text-3xl: 30px;
|
||||
--text-4xl: 36px;
|
||||
--leading-body: 1.5;
|
||||
--leading-tight: 1.2;
|
||||
--tracking-display: 0;
|
||||
--space-1: 4px;
|
||||
--space-2: 8px;
|
||||
--space-3: 12px;
|
||||
--space-4: 16px;
|
||||
--space-5: 20px;
|
||||
--space-6: 24px;
|
||||
--space-8: 32px;
|
||||
--space-12: 48px;
|
||||
--section-y-desktop: 64px;
|
||||
--section-y-tablet: 48px;
|
||||
--section-y-phone: 32px;
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 6px;
|
||||
--radius-lg: 8px;
|
||||
--radius-pill: 9999px;
|
||||
--elev-flat: none;
|
||||
--elev-ring: 0 0 0 1px var(--border);
|
||||
--elev-raised: 0 1px 2px 0 oklch(0% 0 0 / 0.08);
|
||||
--focus-ring: 0 0 0 2px oklch(15% 0 0);
|
||||
--motion-fast: 150ms;
|
||||
--motion-base: 250ms;
|
||||
--ease-standard: cubic-bezier(0.77, 0, 0.175, 1);
|
||||
--container-max: 1200px;
|
||||
--container-gutter-desktop: 24px;
|
||||
--container-gutter-tablet: 16px;
|
||||
--container-gutter-phone: 12px;
|
||||
}
|
||||
|
||||
[data-theme="dark"],
|
||||
[data-mode="dark"] {
|
||||
--bg: oklch(10% 0 0);
|
||||
--surface: oklch(17% 0 0);
|
||||
--surface-warm: oklch(15% 0 0);
|
||||
--fg: oklch(97% 0 0);
|
||||
--fg-2: var(--fg);
|
||||
--muted: oklch(70.8% 0 0);
|
||||
--meta: var(--muted);
|
||||
--border: oklch(32% 0 0);
|
||||
--border-soft: oklch(26.9% 0 0);
|
||||
--accent: color-mix(in oklch, oklch(0.5772 0.2324 260), black 10%);
|
||||
--accent-on: #ffffff;
|
||||
--accent-hover: oklch(48.8% 0.243 264.376);
|
||||
--accent-active: var(--accent-hover);
|
||||
--success: oklch(76.5% 0.177 163.223);
|
||||
--warn: oklch(64.5% 0.168 50);
|
||||
--danger: oklch(57.7% 0.245 27.325);
|
||||
--elev-raised: 0 1px 2px 0 oklch(0% 0 0 / 0.3);
|
||||
--focus-ring: 0 0 0 2px oklch(93.5% 0 0);
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
html, body { margin: 0; min-height: 100%; }
|
||||
body { background: var(--bg); color: var(--fg); font: 400 var(--text-base) / var(--leading-body) var(--font-body); }
|
||||
button, input { font: inherit; }
|
||||
button { cursor: pointer; }
|
||||
button:disabled { cursor: not-allowed; }
|
||||
.page { min-height: 100vh; padding-block: var(--section-y-desktop); }
|
||||
.container { width: min(100% - (2 * var(--container-gutter-desktop)), var(--container-max)); margin-inline: auto; }
|
||||
.stack-2 { display: grid; gap: var(--space-2); }
|
||||
.stack-4 { display: grid; gap: var(--space-4); }
|
||||
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }
|
||||
h1, h2, h3, p { margin: 0; }
|
||||
h1, h2, h3 { font-family: var(--font-display); line-height: var(--leading-tight); letter-spacing: var(--tracking-display); }
|
||||
h1 { font-size: var(--text-3xl); font-weight: 600; }
|
||||
h2 { font-size: var(--text-lg); font-weight: 600; }
|
||||
h3 { font-size: var(--text-base); font-weight: 600; }
|
||||
.eyebrow { color: var(--muted); font-size: var(--text-sm); }
|
||||
.lead { max-width: 68ch; color: var(--fg-2); font-size: var(--text-lg); }
|
||||
.layout-grid { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(260px, 0.7fr); gap: var(--space-6); margin-top: var(--space-8); }
|
||||
.panel { overflow: hidden; border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--elev-ring), var(--elev-raised); }
|
||||
.panel-header { padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border-soft); }
|
||||
.panel-body { padding: var(--space-5); }
|
||||
.status-badge { display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-2); border-radius: var(--radius-pill); background: var(--surface-warm); color: var(--fg-2); font-size: var(--text-xs); font-weight: 500; }
|
||||
.status-badge::before { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--success); content: ""; }
|
||||
.btn { display: inline-flex; min-height: 36px; align-items: center; justify-content: center; gap: var(--space-2); padding-inline: var(--space-3); border: 1px solid transparent; border-radius: var(--radius-lg); font-weight: 500; }
|
||||
.btn:focus-visible, input:focus-visible, a:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
||||
.btn-primary { background: var(--accent); color: var(--accent-on); }
|
||||
.btn-primary:hover, .btn-primary:active { background: var(--accent-hover); }
|
||||
.btn-secondary { border-color: var(--border); background: var(--surface); color: var(--fg); }
|
||||
.btn-secondary:hover { background: var(--surface-warm); }
|
||||
.btn-danger { background: var(--danger); color: var(--accent-on); }
|
||||
.btn:disabled { border-color: var(--border-soft); background: var(--surface-warm); color: var(--muted); }
|
||||
.btn-loading::before { width: 12px; height: 12px; border: 2px solid currentcolor; border-right-color: transparent; border-radius: var(--radius-pill); animation: spin var(--motion-base) linear infinite; content: ""; }
|
||||
.actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
|
||||
.field { display: grid; gap: var(--space-2); }
|
||||
.field label { font-size: var(--text-sm); font-weight: 500; }
|
||||
.field input { width: 100%; min-height: 36px; padding-inline: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); color: var(--fg); }
|
||||
.field input:hover { border-color: var(--muted); }
|
||||
.field input[aria-invalid="true"] { border-color: var(--danger); }
|
||||
.field-error { color: var(--danger); font-size: var(--text-xs); }
|
||||
.metric-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-block: 1px solid var(--border-soft); }
|
||||
.metric { padding: var(--space-4); border-right: 1px solid var(--border-soft); }
|
||||
.metric:last-child { border-right: 0; }
|
||||
.metric strong { display: block; font-size: var(--text-xl); font-weight: 600; }
|
||||
.metric span { color: var(--muted); font-size: var(--text-sm); }
|
||||
.activity-list { display: grid; margin: 0; padding: 0; list-style: none; }
|
||||
.activity-item { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border-soft); }
|
||||
.activity-item:last-child { border-bottom: 0; }
|
||||
.activity-icon { display: grid; width: 28px; height: 28px; place-items: center; border-radius: var(--radius-md); background: var(--surface-warm); color: var(--accent); font-family: var(--font-mono); font-size: var(--text-xs); }
|
||||
.activity-meta { color: var(--muted); font-size: var(--text-xs); }
|
||||
.text-link { color: var(--accent); font-weight: 500; text-decoration: none; }
|
||||
.text-link:hover { text-decoration: underline; }
|
||||
kbd { padding: 2px var(--space-1); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-warm); box-shadow: 0 1px 0 var(--border); font: 500 var(--text-xs) / 1.4 var(--font-mono); }
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
@media (max-width: 800px) { .layout-grid { grid-template-columns: 1fr; } .metric-grid { grid-template-columns: 1fr; } .metric { border-right: 0; border-bottom: 1px solid var(--border-soft); } .metric:last-child { border-bottom: 0; } }
|
||||
@media (max-width: 639px) { .page { padding-block: var(--section-y-phone); } .container { width: min(100% - (2 * var(--container-gutter-phone)), var(--container-max)); } .row-between { align-items: flex-start; flex-direction: column; } }
|
||||
@media (prefers-reduced-motion: reduce) { .btn-loading::before { animation: none; border-right-color: currentcolor; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="page">
|
||||
<div class="container">
|
||||
<header class="stack-2">
|
||||
<p class="eyebrow">Cloudflare Kumo UI</p>
|
||||
<h1>Network operations</h1>
|
||||
<p class="lead">A compact reference surface using semantic layers, clear states, and task-focused controls.</p>
|
||||
</header>
|
||||
<section class="layout-grid" aria-label="Reference components">
|
||||
<article class="panel">
|
||||
<header class="panel-header row-between">
|
||||
<div class="stack-2"><h2>Service overview</h2><p class="activity-meta">Updated moments ago</p></div>
|
||||
<span class="status-badge">Operational</span>
|
||||
</header>
|
||||
<div class="metric-grid">
|
||||
<div class="metric"><strong>99.99%</strong><span>Availability</span></div>
|
||||
<div class="metric"><strong>18 ms</strong><span>Edge latency</span></div>
|
||||
<div class="metric"><strong>42</strong><span>Active zones</span></div>
|
||||
</div>
|
||||
<ul class="activity-list">
|
||||
<li class="activity-item"><span class="activity-icon" aria-hidden="true">A</span><div><h3>API gateway</h3><p class="activity-meta">Healthy in every region</p></div><a class="text-link" href="#api">Inspect</a></li>
|
||||
<li class="activity-item"><span class="activity-icon" aria-hidden="true">W</span><div><h3>Workers deployment</h3><p class="activity-meta">Version 24 is serving traffic</p></div><kbd>G</kbd></li>
|
||||
<li class="activity-item"><span class="activity-icon" aria-hidden="true">D</span><div><h3>DNS analytics</h3><p class="activity-meta">No anomalies detected</p></div><a class="text-link" href="#dns">Open</a></li>
|
||||
</ul>
|
||||
</article>
|
||||
<aside class="panel">
|
||||
<header class="panel-header"><h2>Configure alert</h2></header>
|
||||
<div class="panel-body stack-4">
|
||||
<div class="field">
|
||||
<label for="alert-name">Alert name</label>
|
||||
<input id="alert-name" value="Latency threshold" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="threshold">Threshold</label>
|
||||
<input id="threshold" aria-invalid="true" aria-describedby="threshold-error" value="" placeholder="Milliseconds" />
|
||||
<p id="threshold-error" class="field-error">Enter a threshold.</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="btn btn-primary" type="button">Save alert</button>
|
||||
<button class="btn btn-secondary" type="button">Cancel</button>
|
||||
<button class="btn btn-danger" type="button">Delete</button>
|
||||
<button class="btn btn-loading" type="button" disabled aria-busy="true">Saving</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,467 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"brandId": "cloudflare-kumo",
|
||||
"source": {
|
||||
"componentsHtml": "components.html",
|
||||
"tokensCss": "tokens.css"
|
||||
},
|
||||
"fixture": {
|
||||
"title": "Cloudflare Kumo UI - reference components",
|
||||
"description": "Reference fixture for the OpenDesign Cloudflare Kumo UI integration: compact semantic surfaces, precise controls, visible states, and operational data density.",
|
||||
"styleBlockCount": 1,
|
||||
"selectorCount": 59,
|
||||
"classCount": 27,
|
||||
"elementCount": 25
|
||||
},
|
||||
"tokens": {
|
||||
"declared": [
|
||||
"--accent",
|
||||
"--accent-active",
|
||||
"--accent-hover",
|
||||
"--accent-on",
|
||||
"--bg",
|
||||
"--border",
|
||||
"--border-soft",
|
||||
"--container-gutter-desktop",
|
||||
"--container-gutter-phone",
|
||||
"--container-gutter-tablet",
|
||||
"--container-max",
|
||||
"--danger",
|
||||
"--ease-standard",
|
||||
"--elev-flat",
|
||||
"--elev-raised",
|
||||
"--elev-ring",
|
||||
"--fg",
|
||||
"--fg-2",
|
||||
"--focus-ring",
|
||||
"--font-body",
|
||||
"--font-display",
|
||||
"--font-mono",
|
||||
"--leading-body",
|
||||
"--leading-tight",
|
||||
"--meta",
|
||||
"--motion-base",
|
||||
"--motion-fast",
|
||||
"--muted",
|
||||
"--radius-lg",
|
||||
"--radius-md",
|
||||
"--radius-pill",
|
||||
"--radius-sm",
|
||||
"--section-y-desktop",
|
||||
"--section-y-phone",
|
||||
"--section-y-tablet",
|
||||
"--space-1",
|
||||
"--space-12",
|
||||
"--space-2",
|
||||
"--space-3",
|
||||
"--space-4",
|
||||
"--space-5",
|
||||
"--space-6",
|
||||
"--space-8",
|
||||
"--success",
|
||||
"--surface",
|
||||
"--surface-warm",
|
||||
"--text-2xl",
|
||||
"--text-3xl",
|
||||
"--text-4xl",
|
||||
"--text-base",
|
||||
"--text-lg",
|
||||
"--text-sm",
|
||||
"--text-xl",
|
||||
"--text-xs",
|
||||
"--tracking-display",
|
||||
"--warn"
|
||||
],
|
||||
"referenced": [
|
||||
"--accent",
|
||||
"--accent-hover",
|
||||
"--accent-on",
|
||||
"--bg",
|
||||
"--border",
|
||||
"--border-soft",
|
||||
"--container-gutter-desktop",
|
||||
"--container-gutter-phone",
|
||||
"--container-max",
|
||||
"--danger",
|
||||
"--elev-raised",
|
||||
"--elev-ring",
|
||||
"--fg",
|
||||
"--fg-2",
|
||||
"--focus-ring",
|
||||
"--font-body",
|
||||
"--font-display",
|
||||
"--font-mono",
|
||||
"--leading-body",
|
||||
"--leading-tight",
|
||||
"--motion-base",
|
||||
"--muted",
|
||||
"--radius-lg",
|
||||
"--radius-md",
|
||||
"--radius-pill",
|
||||
"--radius-sm",
|
||||
"--section-y-desktop",
|
||||
"--section-y-phone",
|
||||
"--space-1",
|
||||
"--space-2",
|
||||
"--space-3",
|
||||
"--space-4",
|
||||
"--space-5",
|
||||
"--space-6",
|
||||
"--space-8",
|
||||
"--success",
|
||||
"--surface",
|
||||
"--surface-warm",
|
||||
"--text-3xl",
|
||||
"--text-base",
|
||||
"--text-lg",
|
||||
"--text-sm",
|
||||
"--text-xl",
|
||||
"--text-xs",
|
||||
"--tracking-display"
|
||||
],
|
||||
"unusedDeclared": [
|
||||
"--accent-active",
|
||||
"--container-gutter-tablet",
|
||||
"--ease-standard",
|
||||
"--elev-flat",
|
||||
"--meta",
|
||||
"--motion-fast",
|
||||
"--section-y-tablet",
|
||||
"--space-12",
|
||||
"--text-2xl",
|
||||
"--text-4xl",
|
||||
"--warn"
|
||||
],
|
||||
"undeclaredReferenced": []
|
||||
},
|
||||
"selectors": [
|
||||
".actions",
|
||||
".activity-icon",
|
||||
".activity-item",
|
||||
".activity-item:last-child",
|
||||
".activity-list",
|
||||
".activity-meta",
|
||||
".btn",
|
||||
".btn-danger",
|
||||
".btn-loading::before",
|
||||
".btn-primary",
|
||||
".btn-primary:active",
|
||||
".btn-primary:hover",
|
||||
".btn-secondary",
|
||||
".btn-secondary:hover",
|
||||
".btn:disabled",
|
||||
".btn:focus-visible",
|
||||
".container",
|
||||
".eyebrow",
|
||||
".field",
|
||||
".field input",
|
||||
".field input:hover",
|
||||
".field input[aria-invalid=\"true\"]",
|
||||
".field label",
|
||||
".field-error",
|
||||
".layout-grid",
|
||||
".lead",
|
||||
".metric",
|
||||
".metric span",
|
||||
".metric strong",
|
||||
".metric-grid",
|
||||
".metric:last-child",
|
||||
".page",
|
||||
".panel",
|
||||
".panel-body",
|
||||
".panel-header",
|
||||
".row-between",
|
||||
".stack-2",
|
||||
".stack-4",
|
||||
".status-badge",
|
||||
".status-badge::before",
|
||||
".text-link",
|
||||
".text-link:hover",
|
||||
"[data-mode=\"dark\"]",
|
||||
"[data-theme=\"dark\"]",
|
||||
"*",
|
||||
"*::after",
|
||||
"*::before",
|
||||
"a:focus-visible",
|
||||
"body",
|
||||
"button",
|
||||
"button:disabled",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"html",
|
||||
"input",
|
||||
"input:focus-visible",
|
||||
"kbd",
|
||||
"p"
|
||||
],
|
||||
"classes": [
|
||||
"actions",
|
||||
"activity-icon",
|
||||
"activity-item",
|
||||
"activity-list",
|
||||
"activity-meta",
|
||||
"btn",
|
||||
"btn-danger",
|
||||
"btn-loading",
|
||||
"btn-primary",
|
||||
"btn-secondary",
|
||||
"container",
|
||||
"eyebrow",
|
||||
"field",
|
||||
"field-error",
|
||||
"layout-grid",
|
||||
"lead",
|
||||
"metric",
|
||||
"metric-grid",
|
||||
"page",
|
||||
"panel",
|
||||
"panel-body",
|
||||
"panel-header",
|
||||
"row-between",
|
||||
"stack-2",
|
||||
"stack-4",
|
||||
"status-badge",
|
||||
"text-link"
|
||||
],
|
||||
"elements": [
|
||||
"a",
|
||||
"article",
|
||||
"aside",
|
||||
"body",
|
||||
"button",
|
||||
"div",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"head",
|
||||
"header",
|
||||
"html",
|
||||
"input",
|
||||
"kbd",
|
||||
"label",
|
||||
"li",
|
||||
"main",
|
||||
"meta",
|
||||
"p",
|
||||
"section",
|
||||
"span",
|
||||
"strong",
|
||||
"style",
|
||||
"title",
|
||||
"ul"
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"id": "buttons",
|
||||
"label": "Buttons and calls to action",
|
||||
"present": true,
|
||||
"selectors": [
|
||||
".btn",
|
||||
".btn-danger",
|
||||
".btn-loading::before",
|
||||
".btn-primary",
|
||||
".btn-primary:active",
|
||||
".btn-primary:hover",
|
||||
".btn-secondary",
|
||||
".btn-secondary:hover",
|
||||
".btn:disabled",
|
||||
".btn:focus-visible",
|
||||
"button",
|
||||
"button:disabled"
|
||||
],
|
||||
"classes": [
|
||||
"btn",
|
||||
"btn-danger",
|
||||
"btn-loading",
|
||||
"btn-primary",
|
||||
"btn-secondary"
|
||||
],
|
||||
"elements": [
|
||||
"button"
|
||||
],
|
||||
"tokenReferences": [
|
||||
"--accent",
|
||||
"--accent-on",
|
||||
"--border",
|
||||
"--danger",
|
||||
"--fg",
|
||||
"--motion-base",
|
||||
"--radius-lg",
|
||||
"--radius-pill",
|
||||
"--space-2",
|
||||
"--space-3",
|
||||
"--surface"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "inputs",
|
||||
"label": "Form fields and controls",
|
||||
"present": true,
|
||||
"selectors": [
|
||||
".field",
|
||||
".field input",
|
||||
".field input:hover",
|
||||
".field input[aria-invalid=\"true\"]",
|
||||
".field label",
|
||||
".field-error",
|
||||
"input",
|
||||
"input:focus-visible"
|
||||
],
|
||||
"classes": [
|
||||
"field",
|
||||
"field-error"
|
||||
],
|
||||
"elements": [
|
||||
"input",
|
||||
"label"
|
||||
],
|
||||
"tokenReferences": [
|
||||
"--border",
|
||||
"--danger",
|
||||
"--fg",
|
||||
"--radius-lg",
|
||||
"--space-2",
|
||||
"--space-3",
|
||||
"--surface"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cards",
|
||||
"label": "Cards and panels",
|
||||
"present": true,
|
||||
"selectors": [
|
||||
".panel",
|
||||
".panel-body",
|
||||
".panel-header"
|
||||
],
|
||||
"classes": [
|
||||
"panel",
|
||||
"panel-body",
|
||||
"panel-header"
|
||||
],
|
||||
"elements": [],
|
||||
"tokenReferences": [
|
||||
"--border-soft",
|
||||
"--space-4",
|
||||
"--space-5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "badges",
|
||||
"label": "Badges, chips, and status labels",
|
||||
"present": true,
|
||||
"selectors": [],
|
||||
"classes": [
|
||||
"status-badge"
|
||||
],
|
||||
"elements": [],
|
||||
"tokenReferences": []
|
||||
},
|
||||
{
|
||||
"id": "links",
|
||||
"label": "Links and inline actions",
|
||||
"present": true,
|
||||
"selectors": [
|
||||
"a:focus-visible"
|
||||
],
|
||||
"classes": [],
|
||||
"elements": [
|
||||
"a"
|
||||
],
|
||||
"tokenReferences": []
|
||||
},
|
||||
{
|
||||
"id": "keyboard",
|
||||
"label": "Keyboard hints",
|
||||
"present": true,
|
||||
"selectors": [
|
||||
"kbd"
|
||||
],
|
||||
"classes": [],
|
||||
"elements": [
|
||||
"kbd"
|
||||
],
|
||||
"tokenReferences": [
|
||||
"--border",
|
||||
"--font-mono",
|
||||
"--radius-sm",
|
||||
"--space-1",
|
||||
"--surface-warm",
|
||||
"--text-xs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "icons",
|
||||
"label": "Icon slots",
|
||||
"present": false,
|
||||
"selectors": [],
|
||||
"classes": [],
|
||||
"elements": [],
|
||||
"tokenReferences": []
|
||||
},
|
||||
{
|
||||
"id": "typography",
|
||||
"label": "Typography scale and text utilities",
|
||||
"present": true,
|
||||
"selectors": [
|
||||
".eyebrow",
|
||||
".lead",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3"
|
||||
],
|
||||
"classes": [
|
||||
"eyebrow",
|
||||
"lead"
|
||||
],
|
||||
"elements": [
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"p"
|
||||
],
|
||||
"tokenReferences": [
|
||||
"--font-display",
|
||||
"--leading-tight",
|
||||
"--muted",
|
||||
"--text-lg",
|
||||
"--text-sm",
|
||||
"--tracking-display"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "layout",
|
||||
"label": "Layout primitives",
|
||||
"present": true,
|
||||
"selectors": [
|
||||
".container",
|
||||
".row-between",
|
||||
".stack-2",
|
||||
".stack-4"
|
||||
],
|
||||
"classes": [
|
||||
"container",
|
||||
"layout-grid",
|
||||
"metric-grid",
|
||||
"row-between",
|
||||
"stack-2",
|
||||
"stack-4"
|
||||
],
|
||||
"elements": [
|
||||
"header",
|
||||
"main",
|
||||
"section"
|
||||
],
|
||||
"tokenReferences": [
|
||||
"--space-2",
|
||||
"--space-4"
|
||||
]
|
||||
}
|
||||
],
|
||||
"literals": {
|
||||
"colorExpressions": 15,
|
||||
"pixelValues": 25,
|
||||
"hardcodedFontFamilies": 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"schemaVersion": "od-design-system-project/v1",
|
||||
"id": "cloudflare-kumo",
|
||||
"name": "Cloudflare Kumo UI",
|
||||
"category": "Developer Tools",
|
||||
"description": "Cloudflare's component system for modern web apps, with semantic light and dark tokens, compact typography, layered neutral surfaces, accessible controls, and chart-ready color guidance.",
|
||||
"source": {
|
||||
"type": "bundled",
|
||||
"origin": "OpenDesign curated integration of https://github.com/cloudflare/kumo at 0c5832575c99988917b81cd752002e10f3dc9c7a (@cloudflare/kumo 2.9.2, MIT)"
|
||||
},
|
||||
"files": {
|
||||
"design": "DESIGN.md",
|
||||
"tokens": "tokens.css",
|
||||
"components": "components.html"
|
||||
},
|
||||
"usage": "USAGE.md",
|
||||
"componentsManifest": "components.manifest.json",
|
||||
"importMode": "normalized",
|
||||
"craft": {
|
||||
"applies": [],
|
||||
"suggested": [
|
||||
"color",
|
||||
"accessibility-baseline"
|
||||
],
|
||||
"exemptions": []
|
||||
},
|
||||
"preview": {
|
||||
"dir": "preview",
|
||||
"pages": [
|
||||
{
|
||||
"path": "preview/colors.html",
|
||||
"role": "colors",
|
||||
"title": "Colors"
|
||||
},
|
||||
{
|
||||
"path": "preview/typography.html",
|
||||
"role": "typography",
|
||||
"title": "Typography"
|
||||
},
|
||||
{
|
||||
"path": "preview/spacing.html",
|
||||
"role": "spacing",
|
||||
"title": "Spacing"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sourceFiles": {
|
||||
"evidence": "source/evidence.md"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Cloudflare Kumo UI colors</title>
|
||||
<link rel="stylesheet" href="../tokens.css" />
|
||||
<style>
|
||||
body { margin: 0; background: var(--bg); color: var(--fg); font-family: var(--font-body); }
|
||||
main { max-width: var(--container-max); margin: 0 auto; padding: var(--space-12) var(--container-gutter-desktop); }
|
||||
h1 { margin: 0; font-size: var(--text-2xl); line-height: var(--leading-tight); }
|
||||
.intro { margin: var(--space-2) 0 var(--space-6); color: var(--muted); font-size: var(--text-base); }
|
||||
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--space-4); }
|
||||
.swatch { overflow: hidden; border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--elev-ring), var(--elev-raised); }
|
||||
.color { height: 92px; background: var(--value); }
|
||||
.meta { padding: var(--space-3); color: var(--muted); font-size: var(--text-sm); }
|
||||
strong { display: block; margin-bottom: var(--space-1); color: var(--fg); font-weight: 600; }
|
||||
code { font-family: var(--font-mono); font-size: var(--text-xs); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>Semantic color roles</h1>
|
||||
<p class="intro">Use roles, not raw palette names. Toggle the document's <code>data-mode</code> to review dark mode.</p>
|
||||
<section class="grid" aria-label="Color tokens">
|
||||
<article class="swatch" style="--value: var(--bg)"><div class="color"></div><div class="meta"><strong>Canvas</strong><code>--bg</code></div></article>
|
||||
<article class="swatch" style="--value: var(--surface)"><div class="color"></div><div class="meta"><strong>Base surface</strong><code>--surface</code></div></article>
|
||||
<article class="swatch" style="--value: var(--surface-warm)"><div class="color"></div><div class="meta"><strong>Recessed surface</strong><code>--surface-warm</code></div></article>
|
||||
<article class="swatch" style="--value: var(--fg)"><div class="color"></div><div class="meta"><strong>Default text</strong><code>--fg</code></div></article>
|
||||
<article class="swatch" style="--value: var(--muted)"><div class="color"></div><div class="meta"><strong>Subtle text</strong><code>--muted</code></div></article>
|
||||
<article class="swatch" style="--value: var(--border-soft)"><div class="color"></div><div class="meta"><strong>Hairline</strong><code>--border-soft</code></div></article>
|
||||
<article class="swatch" style="--value: var(--accent)"><div class="color"></div><div class="meta"><strong>Brand action</strong><code>--accent</code></div></article>
|
||||
<article class="swatch" style="--value: var(--success)"><div class="color"></div><div class="meta"><strong>Success</strong><code>--success</code></div></article>
|
||||
<article class="swatch" style="--value: var(--warn)"><div class="color"></div><div class="meta"><strong>Warning</strong><code>--warn</code></div></article>
|
||||
<article class="swatch" style="--value: var(--danger)"><div class="color"></div><div class="meta"><strong>Danger</strong><code>--danger</code></div></article>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,53 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Cloudflare Kumo UI spacing</title>
|
||||
<link rel="stylesheet" href="../tokens.css" />
|
||||
<style>
|
||||
body { margin: 0; background: var(--bg); color: var(--fg); font-family: var(--font-body); }
|
||||
main { max-width: var(--container-max); margin: 0 auto; padding: var(--space-12) var(--container-gutter-desktop); }
|
||||
h1, h2 { margin: 0; line-height: var(--leading-tight); font-weight: 600; }
|
||||
h1 { font-size: var(--text-2xl); }
|
||||
h2 { margin-bottom: var(--space-4); font-size: var(--text-lg); }
|
||||
.intro { margin: var(--space-2) 0 var(--space-8); color: var(--muted); }
|
||||
.layout { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-8); }
|
||||
.stack { display: grid; gap: var(--space-3); }
|
||||
.row { display: grid; grid-template-columns: 96px 1fr; align-items: center; gap: var(--space-4); color: var(--muted); font-size: var(--text-sm); }
|
||||
.bar { height: var(--space-3); width: var(--size); border-radius: var(--radius-sm); background: var(--accent); }
|
||||
.radii { display: grid; grid-template-columns: repeat(2, minmax(120px, 1fr)); gap: var(--space-4); }
|
||||
.radius { min-height: 96px; display: grid; place-items: center; background: var(--surface); color: var(--fg-2); font: 400 var(--text-xs) / 1.4 var(--font-mono); box-shadow: var(--elev-ring), var(--elev-raised); }
|
||||
@media (max-width: 700px) { .layout { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>Spacing and radius</h1>
|
||||
<p class="intro">A compact 4px rhythm and concentric control radii support dense product workflows.</p>
|
||||
<div class="layout">
|
||||
<section>
|
||||
<h2>Spacing scale</h2>
|
||||
<div class="stack">
|
||||
<div class="row"><span>4px</span><div class="bar" style="--size: var(--space-1)"></div></div>
|
||||
<div class="row"><span>8px</span><div class="bar" style="--size: var(--space-2)"></div></div>
|
||||
<div class="row"><span>12px</span><div class="bar" style="--size: var(--space-3)"></div></div>
|
||||
<div class="row"><span>16px</span><div class="bar" style="--size: var(--space-4)"></div></div>
|
||||
<div class="row"><span>24px</span><div class="bar" style="--size: var(--space-6)"></div></div>
|
||||
<div class="row"><span>32px</span><div class="bar" style="--size: var(--space-8)"></div></div>
|
||||
<div class="row"><span>48px</span><div class="bar" style="--size: var(--space-12)"></div></div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Radius scale</h2>
|
||||
<div class="radii">
|
||||
<div class="radius" style="border-radius: var(--radius-sm)">4px / sm</div>
|
||||
<div class="radius" style="border-radius: var(--radius-md)">6px / md</div>
|
||||
<div class="radius" style="border-radius: var(--radius-lg)">8px / lg</div>
|
||||
<div class="radius" style="border-radius: var(--radius-pill)">pill</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,35 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Cloudflare Kumo UI typography</title>
|
||||
<link rel="stylesheet" href="../tokens.css" />
|
||||
<style>
|
||||
body { margin: 0; background: var(--bg); color: var(--fg); font-family: var(--font-body); }
|
||||
main { max-width: 760px; margin: 0 auto; padding: var(--space-12) var(--container-gutter-desktop); }
|
||||
h1 { margin: 0; font-size: var(--text-2xl); line-height: var(--leading-tight); font-weight: 600; }
|
||||
.intro { margin: var(--space-2) 0 var(--space-8); color: var(--muted); font-size: var(--text-base); }
|
||||
.samples { display: grid; gap: var(--space-5); }
|
||||
.sample { display: grid; grid-template-columns: 88px 1fr; align-items: baseline; gap: var(--space-4); padding-bottom: var(--space-4); border-bottom: 1px solid var(--border-soft); }
|
||||
.label { color: var(--muted); font: 400 var(--text-xs) / 1.4 var(--font-mono); }
|
||||
.text { margin: 0; font-size: var(--size); line-height: var(--leading-body); }
|
||||
.heading { font-weight: 600; line-height: var(--leading-tight); }
|
||||
.code { font-family: var(--font-mono); font-size: var(--text-sm); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>Compact type hierarchy</h1>
|
||||
<p class="intro">Inter with sentence case, zero manual tracking, and restrained medium or semibold emphasis.</p>
|
||||
<section class="samples" aria-label="Typography samples">
|
||||
<div class="sample"><span class="label">12px / xs</span><p class="text" style="--size: var(--text-xs)">Deployment metadata and captions</p></div>
|
||||
<div class="sample"><span class="label">13px / sm</span><p class="text" style="--size: var(--text-sm)">Dense secondary controls and supporting labels</p></div>
|
||||
<div class="sample"><span class="label">14px / base</span><p class="text" style="--size: var(--text-base)">Default product content, controls, and data</p></div>
|
||||
<div class="sample"><span class="label">16px / lg</span><p class="text heading" style="--size: var(--text-lg)">Service overview</p></div>
|
||||
<div class="sample"><span class="label">24px / 2xl</span><p class="text heading" style="--size: var(--text-2xl)">Network operations</p></div>
|
||||
<div class="sample"><span class="label">mono</span><p class="text code">wrangler deploy --env production</p></div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,29 @@
|
||||
# Cloudflare Kumo UI Source Evidence
|
||||
|
||||
## Source Scope
|
||||
|
||||
This package is an OpenDesign curated integration based only on public, official Cloudflare sources. It does not vendor `@cloudflare/kumo`, Cloudflare logos, fonts, screenshots, or React components, and it does not imply endorsement or partnership.
|
||||
|
||||
## Pinned Upstream Revision
|
||||
|
||||
- Repository: <https://github.com/cloudflare/kumo>
|
||||
- Commit: [`0c5832575c99988917b81cd752002e10f3dc9c7a`](https://github.com/cloudflare/kumo/tree/0c5832575c99988917b81cd752002e10f3dc9c7a)
|
||||
- Package: [`@cloudflare/kumo` 2.9.2](https://github.com/cloudflare/kumo/releases/tag/%40cloudflare/kumo%402.9.2)
|
||||
- Documentation: <https://kumo-ui.com/>
|
||||
- License: [MIT](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/LICENSE), Copyright (c) 2026 Cloudflare, Inc.
|
||||
|
||||
## Evidence Map
|
||||
|
||||
| Package guidance | Official source |
|
||||
| --- | --- |
|
||||
| Semantic light/dark colors and `data-mode` theming | [Color documentation](https://kumo-ui.com/colors/) and [`theme-generator/config.ts`](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo/scripts/theme-generator/config.ts) |
|
||||
| Inter typography, compact content, sentence case, and restrained emphasis | [Kumo design skill](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/skills/kumo-design/SKILL.md) and [Text documentation source](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo-docs-astro/src/pages/components/text.mdx) |
|
||||
| Button sizes, variants, loading, and focus behavior | [Button documentation](https://kumo-ui.com/components/button/) and [Button source](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo/src/components/button/button.tsx) |
|
||||
| Layered surfaces, rings, radii, and restrained shadows | [LayerCard source](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo/src/components/layer-card/layer-card.tsx) |
|
||||
| Labels, errors, keyboard behavior, and consumer accessibility duties | [Accessibility documentation](https://kumo-ui.com/accessibility/) and [Input source](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo/src/components/input/input.tsx) |
|
||||
| Semantic, categorical, and sequential chart palettes | [Chart color documentation](https://kumo-ui.com/charts/colors/) and [chart Color source](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo/src/components/chart/Color.ts) |
|
||||
| Dialog, loading, skeleton, and reduced-motion patterns | [Dialog source](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo/src/components/dialog/dialog.tsx), [Loader source](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo/src/components/loader/loader.tsx), and [`theme-kumo.css`](https://github.com/cloudflare/kumo/blob/0c5832575c99988917b81cd752002e10f3dc9c7a/packages/kumo/src/styles/theme-kumo.css) |
|
||||
|
||||
## Adaptation Boundary
|
||||
|
||||
Direct upstream semantic values are recorded in `tokens.css` comments and explained in `DESIGN.md`. OpenDesign's shared token schema requires additional layout slots that Kumo does not publish; those compatibility bindings are identified explicitly and should not be cited as Cloudflare specifications. The reference fixture is original OpenDesign markup that demonstrates the normalized token contract rather than a copy of an upstream example.
|
||||
@@ -0,0 +1,123 @@
|
||||
/* Cloudflare Kumo UI — OpenDesign semantic bindings.
|
||||
* Official sources:
|
||||
* - https://kumo-ui.com/colors/
|
||||
* - https://github.com/cloudflare/kumo/tree/0c5832575c99988917b81cd752002e10f3dc9c7a
|
||||
* - packages/kumo/scripts/theme-generator/config.ts at that commit
|
||||
*
|
||||
* Upstream token values are adapted from @cloudflare/kumo 2.9.2,
|
||||
* Copyright (c) 2026 Cloudflare, Inc., licensed under the MIT License.
|
||||
* This is an OpenDesign curated integration, not an official Cloudflare package.
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Kumo canvas, component base, and recessed surface. */
|
||||
--bg: oklch(98.75% 0 0);
|
||||
--surface: #ffffff;
|
||||
--surface-warm: oklch(96% 0 0);
|
||||
|
||||
/* Kumo default and subtle text. B-slots collapse where Kumo has no matching tier. */
|
||||
--fg: oklch(21% 0.006 285.885);
|
||||
--fg-2: var(--fg);
|
||||
--muted: oklch(55.6% 0 0);
|
||||
--meta: var(--muted);
|
||||
|
||||
/* Kumo line and hairline roles. */
|
||||
--border: oklch(14.5% 0 0 / 0.1);
|
||||
--border-soft: oklch(93.5% 0 0);
|
||||
|
||||
/* Kumo brand background and its documented hover state. */
|
||||
--accent: oklch(0.5772 0.2324 260);
|
||||
--accent-on: #ffffff;
|
||||
--accent-hover: oklch(48.8% 0.243 264.376);
|
||||
--accent-active: var(--accent-hover);
|
||||
|
||||
/* Kumo solid semantic indicators. */
|
||||
--success: oklch(59.6% 0.145 163.225);
|
||||
--warn: oklch(73.9% 0.177 58.2);
|
||||
--danger: oklch(63.7% 0.237 25.331);
|
||||
|
||||
/* Inter is used by Kumo's official documentation and Figma resources. */
|
||||
--font-display: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-body: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
|
||||
/* Kumo's compact 12/13/14/16 scale, extended with its inherited Tailwind heading steps. */
|
||||
--text-xs: 12px;
|
||||
--text-sm: 13px;
|
||||
--text-base: 14px;
|
||||
--text-lg: 16px;
|
||||
--text-xl: 20px;
|
||||
--text-2xl: 24px;
|
||||
--text-3xl: 30px;
|
||||
--text-4xl: 36px;
|
||||
--leading-body: 1.5;
|
||||
--leading-tight: 1.2;
|
||||
--tracking-display: 0;
|
||||
|
||||
/* OpenDesign compatibility bindings aligned to Kumo's 4px utility rhythm. */
|
||||
--space-1: 4px;
|
||||
--space-2: 8px;
|
||||
--space-3: 12px;
|
||||
--space-4: 16px;
|
||||
--space-5: 20px;
|
||||
--space-6: 24px;
|
||||
--space-8: 32px;
|
||||
--space-12: 48px;
|
||||
--section-y-desktop: 64px;
|
||||
--section-y-tablet: 48px;
|
||||
--section-y-phone: 32px;
|
||||
|
||||
/* Kumo control radii map to Tailwind sm/md/lg; pills stay fully rounded. */
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 6px;
|
||||
--radius-lg: 8px;
|
||||
--radius-pill: 9999px;
|
||||
|
||||
/* Ring-led elevation mirrors Kumo LayerCard composition. */
|
||||
--elev-flat: none;
|
||||
--elev-ring: 0 0 0 1px var(--border);
|
||||
--elev-raised: 0 1px 2px 0 oklch(0% 0 0 / 0.08);
|
||||
--focus-ring: 0 0 0 2px oklch(15% 0 0);
|
||||
|
||||
/* 150ms states/dialogs and the 250ms sidebar motion are upstream values. */
|
||||
--motion-fast: 150ms;
|
||||
--motion-base: 250ms;
|
||||
--ease-standard: cubic-bezier(0.77, 0, 0.175, 1);
|
||||
|
||||
/* OpenDesign layout bindings preserve Kumo's compact dashboard density. */
|
||||
--container-max: 1200px;
|
||||
--container-gutter-desktop: 24px;
|
||||
--container-gutter-tablet: 16px;
|
||||
--container-gutter-phone: 12px;
|
||||
}
|
||||
|
||||
/* Kumo uses data-mode="dark". The data-theme selector keeps generated Open
|
||||
* Design artifacts compatible with the repository's standard theme hook. */
|
||||
[data-theme="dark"],
|
||||
[data-mode="dark"] {
|
||||
--bg: oklch(10% 0 0);
|
||||
--surface: oklch(17% 0 0);
|
||||
--surface-warm: oklch(15% 0 0);
|
||||
--fg: oklch(97% 0 0);
|
||||
--fg-2: var(--fg);
|
||||
--muted: oklch(70.8% 0 0);
|
||||
--meta: var(--muted);
|
||||
--border: oklch(32% 0 0);
|
||||
--border-soft: oklch(26.9% 0 0);
|
||||
--accent: color-mix(in oklch, oklch(0.5772 0.2324 260), black 10%);
|
||||
--accent-on: #ffffff;
|
||||
--accent-hover: oklch(48.8% 0.243 264.376);
|
||||
--accent-active: var(--accent-hover);
|
||||
--success: oklch(76.5% 0.177 163.223);
|
||||
--warn: oklch(64.5% 0.168 50);
|
||||
--danger: oklch(57.7% 0.245 27.325);
|
||||
--elev-raised: 0 1px 2px 0 oklch(0% 0 0 / 0.3);
|
||||
--focus-ring: 0 0 0 2px oklch(93.5% 0 0);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
:root {
|
||||
--motion-fast: 0ms;
|
||||
--motion-base: 0ms;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user