ng-hub-ui-ds

ng-hub-ui 家族共享的设计令牌基础:CSS 变量 --hub-ref-*(原始值)与 --hub-sys-*(语义值),带明暗两套和 8 个主题。引入一次,整个家族就读同一份调色板。

它是什么,用来做什么

它的职责是把样式变量在家族所有库之间统一并接通。每个库都用 --hub-* 变量做主题,但并不定义它们:只是消费。这个包就是把它们连起来的唯一事实来源,于是:

  • 一份调色板同时供给 panels、forms、calendar、board……
  • 改一次主题(一个令牌),改动就到达整个家族。
  • 深色模式和 8 个主题已就绪,一个属性即可切换。
  • 你也能在自己的 CSS 里用它,这样你的界面和组件是一致的。

接通工作正按库逐个推进:下方的家族一节列出了每个库的集成状态。想找完整的令牌目录?在令牌参考里。

开始使用

完整路线:装什么、在哪里引入什么,以及每种修改该用哪套机制。ds 没有依赖(纯 CSS/SCSS),而且不引入就不会输出任何东西。

1 · 安装

ds 是基础;再加上你要用的家族库。它们都不定义调色板——全都消费 ds 的令牌。

npm install ng-hub-ui-ds
npm install ng-hub-ui-panels ng-hub-ui-forms …   # the ones you use

2 · 引入——在根部一次,且按这个顺序

/* styles.scss (application root) */

/* 1 · Tokens — ALWAYS, exactly once: the base the whole family consumes */
@use 'ng-hub-ui-ds/styles/tokens/hub-tokens';

/* 2 · Native-element reset — only if your app does not ship one already (Bootstrap Reboot…) */
@use 'ng-hub-ui-ds/styles/base/reset';

/* 3 · Utilities — opt-in: import only the sheets you use
      (Bootstrap-exact names: do NOT load them next to a global Bootstrap) */
@use 'ng-hub-ui-ds/styles/utilities/layout';
@use 'ng-hub-ui-ds/styles/utilities/text';
@use 'ng-hub-ui-ds/styles/utilities/surfaces';

/* 4 · Sheets of their own shipped by some libraries — once, path documented by each README */
@use 'ng-hub-ui-forms/styles' as hub-forms;  // shared forms chrome
@use 'ng-hub-ui-utils/styles/tooltip';       // utils tooltip

/* 5 · Mixins — when you build your own components with the same system */
@use 'ng-hub-ui-ds' as hub;
.page { @include hub.center($max: xl); }

不用 Sass 也可以:每份样式都有编译好的 .css 孪生文件——@import 'ng-hub-ui-ds/styles/tokens/hub-tokens.css';——或者通过 angular.json:

"styles": [
  "node_modules/ng-hub-ui-ds/styles/tokens/hub-tokens.css",
  "src/styles.scss"
]

3 · 修改——按改动内容选机制

我想……机制在哪里说明
改一个全局颜色(比如 primary):root { --hub-sys-color-primary: … }——重设整个家族的主题如何修改
新增一个强调色(brand、tertiary……)CSS:--hub-sys-color-brand · Sass:$hub-accents-extra如何修改
去掉我用不到的变体Sass:替换这个 map——with ($hub-accents: (primary: …, danger: …))——只会输出这些族SCSS 函数
调整间距 / 圆角 / 栅格覆盖结构令牌 --hub-ref-space-* / --hub-sys-radius-* / --hub-sys-grid-*结构层
一整套主题(dark、corporate……)[data-theme='…'] { 有差异的令牌 },再给 <html> 加上属性创建你的主题
用同一套系统构建我自己的组件混入:@include hub.stack() · hub.text-bg(brand) · hub.radius(lg)……——或者用工具类混入与样式
与 Bootstrap / Material / Tailwind 共存桥接混入:@include hub.bridge-bootstrap($mode: adopt | project)桥接
只微调某个库的某个组件它自己的 --hub-<组件>-* 钩子(局部或全局)令牌参考以及各个库自己的页面

4 · 其余的库

令牌加载之后,没有别的要配置了:每个 ng-hub-ui-* 都读 --hub-sys-*,并跟着你的覆盖自行重设主题。此外,每个组件还提供 --hub-<组件>-* 钩子用于精细调整,有些库还带自己的样式表,与令牌一起引入一次——确切路径由各自的 README 说明(例如 forms 的公共外壳,或 utils 的 tooltip/overlay,就像第 2 步的代码块那样)。每个库的集成状态见家族。

架构:两层

ref

--hub-ref-*

没有语境的原始值:色阶、间距、圆角、排版。

--hub-ref-color-blue-500
sys

--hub-sys-*

带含义的映射,组件消费的正是这一层。

--hub-sys-color-primary

黄金法则:组件只引用 sys 令牌;sys 指向 ref。改 sys 是换主题,改 ref 是调整基础调色板。

语义颜色 · 主题实时预览

这套集合是开放的:默认 9 个变体(5 个彩色 + 4 个中性),加上你自己添加的。每个强调色都暴露一组统一的角色——subtle、border-subtle、emphasis,以及对比色 on。切换主题,看整份调色板重新上色。

primary
base
subtle
border
emphasis
on
secondary
base
subtle
border
emphasis
on
success
base
subtle
border
emphasis
on
danger
base
subtle
border
emphasis
on
warning
base
subtle
border
emphasis
on
info
base
subtle
border
emphasis
on
neutral
base
subtle
border
emphasis
on
light
base
subtle
border
emphasis
on
dark
base
subtle
border
emphasis
on
提示 primary
提示 secondary
提示 success
提示 danger
提示 warning
提示 info
提示 neutral
提示 light
提示 dark

创建你的主题 · 只改基础色

只定义每个语义族的基础色。其余的(subtle、border-subtle、emphasis、on)会用 color-mix / relative color 自动推导——下面的组件会实时换色,这正是共享接线在起作用。

primary 基础色 → 推导值
base
subtle
border
emphasis
on
secondary 基础色 → 推导值
base
subtle
border
emphasis
on
success 基础色 → 推导值
base
subtle
border
emphasis
on
danger 基础色 → 推导值
base
subtle
border
emphasis
on
warning 基础色 → 推导值
base
subtle
border
emphasis
on
info 基础色 → 推导值
base
subtle
border
emphasis
on
neutral 基础色 → 推导值
base
subtle
border
emphasis
on
light 基础色 → 推导值
base
subtle
border
emphasis
on
dark 基础色 → 推导值
base
subtle
border
emphasis
on

组件实时预览

提示 primary
提示 secondary
提示 success
提示 danger
提示 warning
提示 info
提示 neutral
提示 light
提示 dark
primarysecondarysuccessdangerwarninginfoneutrallightdark
.my-theme {
  /* define ONLY the base colour of each family */
  --hub-sys-color-primary: #6d28d9;

  /* the rest derives at runtime with color-mix / relative color — nothing to maintain */
  --hub-sys-color-primary-subtle:        color-mix(in oklch, var(--hub-sys-color-primary) 12%, var(--hub-sys-surface-page));
  --hub-sys-color-primary-border-subtle: color-mix(in oklch, var(--hub-sys-color-primary) 35%, var(--hub-sys-surface-page));
  --hub-sys-color-primary-emphasis:      color-mix(in oklch, var(--hub-sys-color-primary) 80%, var(--hub-sys-color-ink));
  --hub-sys-color-primary-on:            oklch(from var(--hub-sys-color-primary) clamp(0, (0.62 - l) * 1000, 1) 0 h);
}

家族 · 集成状态

整个家族都读这些令牌。徽章表示这个库是否已接通 --hub-sys-*(会跟着设计系统换主题),还是仍待接通(之后再处理)。点任意一个即可查看它的示例。

如何修改

1. 覆盖一个令牌(CSS)——主路径

每个值都是 CSS 变量,所以换主题只需一行,并层叠到整个家族:

:root {
  --hub-sys-color-primary: #7c3aed;
  --hub-sys-color-primary-subtle: #ede9fe;
  --hub-sys-color-primary-emphasis: #5b21b6;
}

2. 添加你自己的强调色

定义一个 --hub-sys-color-<名称> 族,接受语义变体的组件无需改动就会用上它。就在这里试试:

brand 提示——背景、文字和边框都由强调色经 color-mix 推导而来。
:root {
  --hub-sys-color-brand: #9333ea;
  --hub-sys-color-brand-subtle: #f3e8ff;
  --hub-sys-color-brand-border-subtle: #d8b4fe;
  --hub-sys-color-brand-emphasis: #6b21a8;
}

<!-- in any component that accepts a semantic variant -->
<hub-panel appearance="alert" variant="brand">Brand alert</hub-panel>

只写 --hub-sys-color-brand 就已经可用(其余由组件用 color-mix 推导)。需要精确色调时再定义完整的族。

……或者在开放 map 里预先定义(Sass)

若使用 Sass,请在引入这个包之前用 $hub-accents-extra 扩展开放的强调色 map。只有 ds 会重新编译——各个库都不会——而且每个新变体都会自动得到完整的族(subtle · border-subtle · emphasis · on):

// Add your own variants — this recompiles the ds only, never the libraries.
@use 'ng-hub-ui-ds/styles/tokens/hub-tokens' with (
  $hub-accents-extra: (
    brand:    #ff6b00,
    accent:   #00b8d9,
    tertiary: #9c36b5
  )
);
// brand · accent · tertiary get subtle · border-subtle · emphasis · on automatically.

3. 创建你自己的主题

[data-theme='corporate'] {
  --hub-sys-color-primary: #0033a0;
  --hub-sys-surface-page: #fbfcff;
  --hub-sys-text-primary: #0a1f44;
  /* …the rest of the tokens that differ from the base */
}

4. ……或者用 hub.theme() 一次搞定(Sass)

一个用于局部主题化的混入:只把改动以 map 传进去,它就按规范名称输出变量。挂在每个令牌下的一切——sys 别名、角色族、工具类、组件——都会沿着 var() 链自行重新推导:

@use 'ng-hub-ui-ds' as hub;

/* change ONLY spacing step 3 — gap-3, .p-3, sys-gap-3, components… all move with it */
:root { @include hub.theme($space: (3: 1.25rem)); }

/* or a whole theme, scopeable to [data-theme] or to a subtree */
[data-theme='compact'] {
  @include hub.theme(
    $space: (3: 0.75rem, 4: 1rem),
    $radius: (md: 0.25rem),
    $accents: (primary: #0f766e, brand: #ff6b00)
  );
}

SCSS 函数:内部是怎么生成的

语义颜色族不是手写的:强调色集合是一个带 !default 的开放 map,整个族由对 map.keys($hub-accents) 的 @each 推导而来。所以加一个颜色(或者九个)是统一的,也没有样板代码:map 里的每个键都会自动获得自己的族。

// The accent set is an OPEN map with !default — add as many as you want.
$hub-accents: (
  primary: …, secondary: …, success: …, danger: …, warning: …,
  info: …, neutral: …, light: …, dark: …
) !default;

// The family is derived ONCE in :root, iterating EVERY key of the map,
// so any accent you add gets its family for free.
@mixin hub-color-derive() {
  @each $name in map.keys($hub-accents) {
    --hub-sys-color-#{$name}-subtle:   color-mix(in oklch, var(--hub-sys-color-#{$name}) 12%, var(--hub-sys-surface-page));
    --hub-sys-color-#{$name}-emphasis: color-mix(in oklch, var(--hub-sys-color-#{$name}) 80%, var(--hub-sys-color-ink));
    --hub-sys-color-#{$name}-on:       oklch(from var(--hub-sys-color-#{$name}) clamp(0, (0.62 - l) * 1000, 1) 0 h);
  }
}

大多数情况下你不需要动 SCSS:覆盖 CSS 变量就能完成换主题和新增强调色。map 加混入是内部机制,向这个包贡献代码时才有用。

结构层 · 令牌实时预览

除了颜色,ds 还定义了一层规范的结构:间距刻度(--hub-ref-space-*)、尺寸与分数(--hub-sys-size-*)、栅格(--hub-sys-grid-columns、槽宽)以及语义化的 gap 刻度(--hub-sys-gap-*)。下面的一切都由这些变量绘制。

间距刻度 · --hub-ref-space-0…7

space-0
space-1
space-2
space-3
space-4
space-5
space-6
space-7

gap 刻度 · --hub-sys-gap-0…5

gap-0
ABC
gap-1
ABC
gap-2
ABC
gap-3
ABC
gap-4
ABC
gap-5
ABC

宽度分数 · --hub-sys-size-*

size-1-21/2
size-1-31/3
size-2-32/3
size-1-41/4
size-3-43/4
size-fullfull

auto-fit 栅格 + 容器宽度

col 1col 2col 3col 4col 5col 6
max-sm
max-md
max-lg
max-xl
max-xxl
/* Canonical structural tokens (ref → sys) */
gap: var(--hub-sys-gap-3);                  /* spacing scale */
padding-inline: var(--hub-ref-space-4);
max-width: var(--hub-sys-container-max-width-lg);
grid-template-columns: repeat(var(--hub-sys-grid-columns), minmax(0, 1fr));

/* Layout mixins */
@use 'ng-hub-ui-ds' as hub;
.page    { @include hub.center($max: xl); }
.toolbar { @include hub.cluster($gap: 2); }
.cards   { @include hub.grid($min: 16rem, $gap: 3); }

/* Opt-in utilities (Bootstrap naming, 3 sheets) */
@use 'ng-hub-ui-ds/styles/utilities/layout';    // .d-flex .gap-3 .ms-auto .position-* .ratio-*
@use 'ng-hub-ui-ds/styles/utilities/text';      // .fs-3 .fw-bold .text-truncate .text-muted
@use 'ng-hub-ui-ds/styles/utilities/surfaces';  // .bg-* .border .rounded .shadow .opacity-*

混入与样式

ds 的 Sass API:消费规范令牌的辅助工具——不写死间距,也不写死颜色。用命名空间引入:@use 'ng-hub-ui-ds' as hub。工具类样式表就是用这些混入构建的,所以修改或扩展某种行为,就是用混入铸造你自己的类。下面每个演示都基于真实的混入构建;完整目录在最后。

每个混入都有等价的工具类;下面的演示使用 ds 的真实类(.cluster、.stack……)——本页没有重新套用任何混入。

hub.cluster() · .cluster——会换行的一行

首页产品价格联系更多

hub.stack() · .stack——一列

区块 1区块 2区块 3

hub.grid() · .grid-auto——auto-fit 栅格

12345678

hub.center() · .center——居中容器

居中的内容(max-width xl)
@use 'ng-hub-ui-ds' as hub;

.toolbar { @include hub.cluster($gap: 2); }          // a row that wraps
.feed    { @include hub.stack($gap: 3); }            // a column
.cards   { @include hub.grid($min: 8rem, $gap: 2); } // auto-fit grid
.page    { @include hub.center($max: sm); }          // centred wrapper

完整目录

混入参数说明
主题
hub.theme()$accents, $space, $gap, $radius, $shadow, $font-*, $line-height, $tokens一次调用完成局部主题化:只把改动以 map 传进去,它输出规范变量;由此派生的部分会自行重新推导。
断点
hub.media-breakpoint-up()$name, $breakpoints: $hub-breakpoints从该断点起的移动优先媒体查询(sm 576 · md 768 · lg 992 · xl 1200 · xxl 1400)。
hub.media-breakpoint-down()$name, $breakpoints: $hub-breakpoints低于该断点的媒体查询。
布局
hub.stack()$gap: 3, $align: stretch带令牌 gap 的 flex 列。
hub.cluster()$gap: 2, $align: center, $justify: flex-start会换行的 flex 行。
hub.grid()$min: 16rem, $gap: 4指定单元格最小宽度的 auto-fit 栅格。
hub.grid-fixed()$cols: 12, $gap: 4N 个固定列的栅格。
hub.row()$gap: 312 条轨道的行(--hub-sys-grid-columns)。
hub.col()$span: 12跨越 row() 中 $span 条轨道的单元格。
hub.offset()$n: 0让 col() 从第 $n + 1 条轨道开始(即 Bootstrap 的 offset);0 表示重置。
hub.center()$max: xl, $pad: 3按容器 max-width 居中的包装器。
排版
hub.font-family()$family: basebase | display | mono。
hub.font-size()$size: base1–6(标题刻度)或 xs | sm | base | lg。
hub.font-weight()$weight: baselight | base | medium | semibold | bold。
hub.line-height()$height: base1 | sm | base | lg。
hub.text-color()$variant: body开放 map 中的强调色、body 或 muted;可用 --hub-text-opacity 调淡。
hub.link-color()$variant: primary强调色链接,悬停用 -emphasis,下划线带不透明度(--hub-link-underline-opacity)。
hub.text-truncate()—单行截断并加省略号。
hub.text-break()—折断过长的词和 URL,避免溢出。
表面
hub.bg()$variant: body, $subtle: false强调色背景(或其 subtle 色调)、body 或 transparent;可用 --hub-bg-opacity 调淡。
hub.text-bg()$variant: primary强调色背景 + 保证对比度的 -on 前景色。
hub.border()$width: 1px, $color: …使用默认边框令牌的实线边框。
hub.border-color()$variant: primary取自开放 map 中某个强调色的边框颜色。
hub.radius()$size: mdnone | sm | md | lg | xl | xxl | pill | circle。
hub.shadow()$size: mdnone | sm | md | lg | inset。
辅助类
hub.focus-ring()—使用 --hub-sys-focus-ring-* 令牌的焦点环。
hub.visually-hidden()—在视觉上隐藏,同时对屏幕阅读器保持可读。
hub.stretched-link()—把链接的可点击区域扩展到它已定位的祖先元素。
hub.ratio()$x: 16, $y: 9用原生 aspect-ratio 实现固定比例。
hub.clearfix()—清除浮动(::after)。
桥接
hub.bridge-bootstrap()$mode: adopt | project采用 --bs-* 的主题,或把主题投射到它上面。
hub.bridge-material()$mode: adopt | project对 --mat-sys-* 同理(Angular Material 3)。
hub.bridge-tailwind()$mode: adopt | project对 --color-* 同理(Tailwind v4 @theme)。
hub.bridge-open-props()$mode: adoptOpen Props 色阶的别名。

工具类

按需引入的类,包裹同一层,名称与 Bootstrap 完全一致——可直接替换,但不要在同一个文档里同时加载这些样式表和全局的 Bootstrap。共三份:layout(display/flex、grid、间距、尺寸、定位、helpers——就是这些小节)、text(「文本」一节)和 surfaces(「表面」一节)。演示用的是真实类:

.cluster .gap-2

一二三四

.grid-auto .gap-2

ABCDEF

尺寸 · .w-50 · .w-25 · .w-auto

w-50w-25w-auto
// three opt-in sheets — import only the ones you use
@use 'ng-hub-ui-ds/styles/utilities/layout';    // layout, spacing, position, helpers
@use 'ng-hub-ui-ds/styles/utilities/text';      // typography and text
@use 'ng-hub-ui-ds/styles/utilities/surfaces';  // backgrounds, borders, radii, shadows

<div class="cluster gap-2"> … </div>
<div class="grid-auto gap-2"> … </div>
<div class="w-50">half</div>
<div class="vh-100 min-vh-100">viewport height</div>

Flexbox

一整套 display 与 flexbox 工具类,命名与 Bootstrap 完全一致。演示使用 ds 的真实类。

justify-content · .justify-content-*——主轴

.justify-content-start
ABC
.justify-content-end
ABC
.justify-content-center
ABC
.justify-content-between
ABC
.justify-content-around
ABC
.justify-content-evenly
ABC

align-items · .align-items-*——交叉轴

.align-items-start
smmdlg
.align-items-center
smmdlg
.align-items-end
smmdlg
.align-items-stretch
smmdlg
.align-items-baseline
smmdlg

flex-direction · .flex-column

行 1行 2行 3

flex-fill / flex-grow-0——伸展与固定

.flex-fill(会伸展).flex-grow-0

响应式 · .flex-md-row · .align-items-md-center

整个 flex 家族都有按断点的变体。移动端是一列,从 md 起是居中的一行——调整窗口宽度看看:

一二三

竖向分隔 · .vr

左右
<!-- display + direction / wrap -->
<div class="d-flex flex-wrap gap-2"> … </div>
<div class="d-flex flex-column"> … </div>

<!-- main axis (justify) and cross axis (align) -->
<div class="d-flex justify-content-between align-items-center"> … </div>

<!-- grow / pin -->
<div class="d-flex gap-2">
  <span class="flex-fill">grows</span>
  <span class="flex-grow-0">fixed</span>
</div>

<!-- responsive: a column on mobile, a top-aligned row from md up -->
<div class="d-flex flex-column flex-md-row align-items-md-start"> … </div>

<!-- vertical divider -->
<div class="d-flex gap-3">left <span class="vr"></span> right</div>

列、宽度与间距

12 列栅格(.row + .col-1…12 + .offset-1…11,由 --hub-sys-grid-columns 驱动)、宽度,以及带方向的 padding/margin。每个演示都用真实的工具类。

列 · .row + .col-N

col-6
col-6
col-4
col-4
col-4
col-3
col-3
col-6
col-8
col-4
col-12
col-2
col-2
col-2
col-2
col-2
col-2

偏移 · .offset-N

单元格从同一栅格的第 n + 1 条轨道开始(grid-column-start);带断点时写 .offset-md-8,而 .offset-md-0 会恢复自动排布。

col-4 offset-4
col-3 offset-9

宽度 · .w-25 / 50 / 75 / 100 / auto

w-25w-25
w-50w-50
w-75w-75
w-100w-100
w-autow-auto

Padding · .p-1…5(四边)

p-1
p-2
p-3
p-4
p-5

按轴的 padding · .px-* / .py-*

px-4 · py-1
px-2 · py-4
px-5 · py-3

Margin · .m-1…5(放在参照框里看)

m-1
m-2
m-3
m-4
m-5

按轴的 margin · .mx-* / .my-*

mx-4
my-3

响应式 · .col-md-6 · .d-lg-none · .p-sm-3

移动优先的变体(sm 576 · md 768 · lg 992 · xl 1200 · xxl 1400)覆盖 display、列与偏移、间距、gap 以及整个 flex 家族(.flex-md-row、.justify-content-md-center、.align-items-md-start、.order-lg-*……)。调整窗口宽度——这些单元格是 .col-12 .col-md-6 .col-xl-3:

col-12 · md-6 · xl-3
col-12 · md-6 · xl-3
col-12 · md-6 · xl-3
col-12 · md-6 · xl-3
<!-- mobile-first: 1 column → 2 at ≥768px → 4 at ≥1200px -->
<div class="row">
  <div class="col-12 col-md-6 col-xl-3">…</div>
</div>
<div class="d-none d-lg-flex">desktop only</div>
<section class="p-2 p-md-4">padding that grows with the viewport</section>

// breakpoints as a mixin — for any other utility or your own CSS
@use 'ng-hub-ui-ds' as hub;
@include hub.media-breakpoint-up(md) { .sidebar { width: 18rem; } }
<!-- 12-column grid: every row adds up to 12 -->
<div class="row">
  <div class="col-6">col-6</div>
  <div class="col-6">col-6</div>
</div>
<div class="row">
  <div class="col-4">col-4</div>
  <div class="col-4">col-4</div>
  <div class="col-4">col-4</div>
</div>

<!-- offset: .col-4.offset-8 starts on track 9 (offset-{bp}-0 resets it) -->
<div class="row">
  <div class="col-4 offset-md-8">col-4 offset-md-8</div>
</div>

<!-- widths · directional padding and margin -->
<div class="w-50">w-50</div>
<div class="p-3">1rem of padding on all four sides</div>
<div class="px-4 py-2">padding-inline 1.5rem · padding-block .5rem</div>
<div class="mx-3">margin-inline 1rem</div>

文本

排版与文本工具类,命名与 Bootstrap 完全一致,构建在排版混入之上(hub.font-size()、hub.font-weight()、hub.text-color()……):每个取值都解析为令牌,所以覆盖令牌就会重设工具类的主题——用混入还能铸造你自己的变体。

字号 · .fs-1…6 · 标题 · .h1…6

.fs-1示例标题
.fs-2示例标题
.fs-3示例标题
.fs-4示例标题
.fs-5示例标题
.fs-6示例标题

.fs-* 只改字号;.h1…6 会套用标题的整套排版(字号 + 加粗 + 紧凑行高 + 外边距)但不带语义——<div class="h5"> 读起来就像 <h5>:

.h1
示例标题
.h2
示例标题
.h3
示例标题
.h4
示例标题
.h5
示例标题
.h6
示例标题

字重 · .fw-* · 字形 · .fst-italic

.fw-light字重来自令牌——light
.fw-normal字重来自令牌——normal
.fw-medium字重来自令牌——medium
.fw-semibold字重来自令牌——semibold
.fw-bold字重来自令牌——bold
.fst-italic斜体

对齐 · .text-start / .text-center / .text-end

.text-start
.text-center
.text-end

Transform · 装饰 · 字体族

.text-uppercase.text-capitalize.text-decoration-underline.text-decoration-line-through.font-monospace

等宽数字 · .font-tabular-nums

比例数字让每个数位有各自的宽度,所以 1 比 0 窄,两个金额的个位会落在不同位置。金额列是自上而下比较着读的:看看两边的小数点各自落在哪里。

默认
1.111,11 €
9.087,70 €
11,10 €
777.777,77 €
.font-tabular-nums
1.111,11 €
9.087,70 €
11,10 €
777.777,77 €

截断 · .text-truncate

一段足够长的文字,长到放不进十六 rem,会以省略号截断。

行高 · .lh-1 / .lh-sm / .lh-base / .lh-lg

.lh-1两行文字,足以看清刻度上每一档所给的行高。
.lh-sm两行文字,足以看清刻度上每一档所给的行高。
.lh-base两行文字,足以看清刻度上每一档所给的行高。
.lh-lg两行文字,足以看清刻度上每一档所给的行高。

颜色 · .text-primary … .text-muted

primarysecondarysuccessdangerwarninginfoneutrallightdarkbodymuted

文字不透明度 · .text-opacity-* · 链接 · .link-*

255075100
// import the sheet once
@use 'ng-hub-ui-ds/styles/utilities/text';

<h2 class="fs-3 fw-semibold">Headline</h2>
<p class="text-muted lh-lg">Secondary copy with generous leading</p>
<span class="text-uppercase fw-medium">label</span>
<td class="text-end font-monospace">1.234,56 €</td>
<p class="text-truncate" style="max-width: 16rem">Truncated with an ellipsis…</p>

// …or mint variants of your own with the mixins
@use 'ng-hub-ui-ds' as hub;
.card__title { @include hub.font-size(4); @include hub.font-weight(semibold); }
.card__meta  { @include hub.text-color(muted); @include hub.text-truncate(); }

表面

背景、边框、圆角、阴影与不透明度,命名与 Bootstrap 完全一致,构建在表面混入之上(hub.bg()、hub.text-bg()、hub.radius()、hub.shadow()……)以及 --hub-sys-color-* / --hub-sys-radius-* / --hub-sys-shadow-* 这些令牌。

背景 · .bg-* 与 .bg-*-subtle

背景 + 保证对比度 · .text-bg-*

primarysecondarysuccessdangerwarninginfoneutrallightdark

边框 · .border · .border-{variant} · .border-1…5

borderprimarydanger · 3去掉上下边

圆角 · .rounded-0…3 · .rounded-pill · .rounded-circle

012345pill1:1

阴影 · .shadow-sm / .shadow / .shadow-lg

smmdlg

不透明度 · .opacity-*(整个元素)· .bg-opacity-*(仅背景)

255075100
bg-10bg-25bg-50bg-75bg-100
// import the sheet once
@use 'ng-hub-ui-ds/styles/utilities/surfaces';

<hub-badge color="success">active</hub-badge>
<div class="bg-warning-subtle border border-warning rounded-3 p-3">notice</div>
<div class="bg-body rounded shadow-lg p-4">raised card</div>

// …or mint variants of your own with the mixins
@use 'ng-hub-ui-ds' as hub;
.card        { @include hub.bg(body); @include hub.radius(lg); @include hub.shadow(sm); }
.card--brand { @include hub.text-bg(brand); }  // any accent of the open map

定位与辅助类

position/inset、overflow、order、float、可见性、z-index、object-fit 和交互——外加行为辅助类(.visually-hidden、.stretched-link、.ratio-*、.clearfix)。全部使用 Bootstrap 的确切命名。

定位 · .position-* + .top/.start/.translate-middle

比例 · .ratio .ratio-16x9

1x1
4x3
16x9
21x9

Overflow · 交互 · 横向间距

一个装了超出容量内容的区块:overflow-auto 会加上内部滚动,而不是撑破页面布局。
user-select-nonepe-nonems-auto

焦点环 · .focus-ring

由 --hub-sys-focus-ring-* 令牌驱动的焦点环——点击或按 Tab:

无障碍 · .visually-hidden

这一段里有一句在视觉上隐藏、但会被屏幕阅读器读出的文字:仅供辅助技术使用(查看 DOM 就能看到)。

<!-- badge positioned over the corner of its container -->
<div class="position-relative">
  …
  <span class="position-absolute top-0 start-100 translate-middle text-bg-danger rounded-pill px-2">9+</span>
</div>

<!-- media at a fixed ratio -->
<div class="ratio ratio-16x9"><iframe src="…"></iframe></div>

<!-- whole card clickable + screen-reader-only text -->
<div class="position-relative">
  <a href="…" class="stretched-link">See more<span class="visually-hidden"> about surfaces</span></a>
</div>

<!-- push with auto margins inside a flex row -->
<nav class="d-flex gap-2"><span>logo</span><a class="ms-auto">login</a></nav>

通往其他系统的桥

把 hub 与现场框架连起来的按需混入。不调用就零成本。通过 $mode 有两个方向:adopt(hub 采用宿主的主题)与 project(hub 把自己的主题投射到宿主上)。

@use 'ng-hub-ui-ds' as hub;

/* "I have Bootstrap and I want hub to adopt its palette" */
:root { @include hub.bridge-bootstrap($mode: adopt); }

/* "I want to tint Material and Tailwind with MY hub theme" */
:root { @include hub.bridge-material($mode: project); }
:root { @include hub.bridge-tailwind($mode: project); }
混入系统adoptproject
hub.bridge-bootstrapBootstrap 5.3+读取 --bs-*着色 --bs-* 以及槽宽/圆角
hub.bridge-materialAngular Material 3读取 --mat-sys-*着色 --mat-sys-*(color/on 成对)
hub.bridge-tailwindTailwind v4读取 --color-*为 @theme 输出 --color-*
hub.bridge-open-propsOpen Props色阶别名 —

速查表

我想……怎么做
使用调色板@use '…/hub-tokens'
改一个全局颜色:root { --hub-sys-color-primary: … }
添加自己的变体with ($hub-accents-extra: (brand: …))
有对比度的文字color: var(--hub-sys-color-primary-on)
布局(混入 / 工具类)@include hub.center() · .stack
文本(混入 / 工具类)@include hub.font-size(3) · .fs-3 .fw-bold .text-muted
表面(混入 / 工具类)@include hub.text-bg(brand) · .bg-primary-subtle .rounded .shadow
定位 / 辅助类.position-absolute .top-0 · .ratio-16x9 · .visually-hidden
响应式.col-md-6 · .flex-md-row · .offset-md-8 · @include hub.media-breakpoint-up(md)
桥接 Bootstrap/Material@include hub.bridge-bootstrap($mode: adopt)
创建主题[data-theme='<name>'] { … }
局部主题化(Sass)@include hub.theme($space: (3: 1.25rem), $accents: (primary: …))