@q1travel/design-system 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -450,7 +450,7 @@ These components ship in the package. Compose from this list before writing new
450
450
 
451
451
  **Identity and media.** Avatar, AvatarGroup, Book, Browser, BrowserDots, BrowserControls, BrowserAddress, BrowserTabs, BrowserPlaceholder, Phone, Video, ThemeSwitcher, ProductLockup, Q1travelSymbol.
452
452
 
453
- - ProductLockup combines a product icon, product name, and brand endorsement into one identity mark. The endorsement is smaller and uses secondary text color.
453
+ - ProductLockup combines a product icon, product name, and brand endorsement into one identity mark. The endorsement is smaller and uses secondary text color. Pass only the brand name through `brand`; the component renders "by" itself.
454
454
 
455
455
  **Text utilities.** Code, CodeInline, CodeTokens, CodeBlock, Snippet, Kbd, MiddleTruncate, TextWithCopyButton.
456
456
 
@@ -450,7 +450,7 @@ These components ship in the package. Compose from this list before writing new
450
450
 
451
451
  **Identity and media.** Avatar, AvatarGroup, Book, Browser, BrowserDots, BrowserControls, BrowserAddress, BrowserTabs, BrowserPlaceholder, Phone, Video, ThemeSwitcher, ProductLockup, Q1travelSymbol.
452
452
 
453
- - ProductLockup combines a product icon, product name, and brand endorsement into one identity mark. The endorsement is smaller and uses secondary text color.
453
+ - ProductLockup combines a product icon, product name, and brand endorsement into one identity mark. The endorsement is smaller and uses secondary text color. Pass only the brand name through `brand`; the component renders "by" itself.
454
454
 
455
455
  **Text utilities.** Code, CodeInline, CodeTokens, CodeBlock, Snippet, Kbd, MiddleTruncate, TextWithCopyButton.
456
456
 
@@ -118,6 +118,24 @@ Examples:
118
118
  Shipped today for the `.form-control` skin: `--q1-input-bg`, `--q1-input-border`,
119
119
  `--q1-input-fg`, `--q1-input-border-focus`, `--q1-input-focus-ring`.
120
120
 
121
+ Shipped for `Table` rows, defined in `tokens.css` for both themes:
122
+
123
+ | Token | Light | Dark | Derivation |
124
+ | --- | --- | --- | --- |
125
+ | `--q1-table-row-bg` | `#ffffff` | `#121212` | `var(--q1-color-bg-canvas)` |
126
+ | `--q1-table-row-bg-hover` | `#f6f6f6` | `#1f1f1f` | `--q1-color-bg-hover` flattened onto the canvas (text-primary at 4% light, 6% dark) |
127
+ | `--q1-table-row-bg-selected` | `#f1efff` | `#1f1e38` | `var(--q1-color-bg-selected)` |
128
+ | `--q1-table-row-bg-selected-hover` | `#edebfa` | `#25243d` | text-primary at half the hover strength (2% light, 3% dark) over the selected surface |
129
+
130
+ Every value is opaque. Table cells, not rows, carry the background and read it from the row, so a
131
+ sticky column always paints the same color as the rest of its row and never lets scrolled content
132
+ show through; row states swap the value instead of stacking a translucent layer. The half-strength
133
+ selected hover keeps `--q1-color-text-muted` at or above 4.5:1. `check-contrast-contract` recomputes
134
+ each derivation and checks the three text levels against all four values. Unlike the input tokens they
135
+ ship with values, because the pre-mixed colors exist nowhere else; `Table` still reads each one with
136
+ a fallback (`bg-canvas`, `bg-subtle`, `bg-selected`) so a stylesheet without them keeps an opaque
137
+ row. A table on a surface other than the canvas overrides all four on the table or its container.
138
+
121
139
  Every component token MUST declare a fallback to the semantic token it replaces, so a
122
140
  consumer that defines none of them sees no change. A component token without a fallback
123
141
  turns an opt-in customisation surface into a required one: the first consumer to upgrade
@@ -1381,15 +1381,15 @@ export declare type PillProps = {
1381
1381
 
1382
1382
  export declare type PopoverLayout = 'vertical' | 'horizontal';
1383
1383
 
1384
- export declare function ProductLockup({ name, icon, endorsement, size, className, 'aria-label': ariaLabel, ...rest }: ProductLockupProps): JSX.Element;
1384
+ export declare function ProductLockup({ name, icon, brand, size, className, 'aria-label': ariaLabel, ...rest }: ProductLockupProps): JSX.Element;
1385
1385
 
1386
1386
  export declare type ProductLockupProps = {
1387
1387
  /** 产品名称,以文字渲染,随主题承色。 */
1388
1388
  name: string;
1389
1389
  /** 产品图标,视为装饰,不参与朗读。默认为品牌符号。 */
1390
1390
  icon?: ReactNode;
1391
- /** 背书文字。 */
1392
- endorsement?: string;
1391
+ /** 背书品牌名,渲染为「by {brand}」。 */
1392
+ brand?: string;
1393
1393
  size?: ProductLockupSize;
1394
1394
  } & Omit<HTMLAttributes<HTMLSpanElement>, 'children' | 'role'>;
1395
1395
 
@@ -4664,24 +4664,25 @@ function hi(e) {
4664
4664
  function Bs({
4665
4665
  name: e,
4666
4666
  icon: t,
4667
- endorsement: r = "by 奇异旅行",
4667
+ brand: r = "奇异旅行",
4668
4668
  size: o = "md",
4669
4669
  className: i,
4670
4670
  "aria-label": s,
4671
4671
  ...a
4672
4672
  }) {
4673
+ const l = `by ${r}`;
4673
4674
  return /* @__PURE__ */ w(
4674
4675
  "span",
4675
4676
  {
4676
4677
  ...a,
4677
4678
  role: "img",
4678
- "aria-label": s ?? `${e} ${r}`,
4679
+ "aria-label": s ?? `${e} ${l}`,
4679
4680
  className: ie("q1-product-lockup", `q1-product-lockup--${o}`, i ?? ""),
4680
4681
  children: [
4681
4682
  /* @__PURE__ */ n("span", { className: "q1-product-lockup__icon", "aria-hidden": "true", children: t ?? /* @__PURE__ */ n(hi, {}) }),
4682
4683
  /* @__PURE__ */ n("span", { className: "q1-product-lockup__name", children: e }),
4683
4684
  /* @__PURE__ */ n(mi, { orientation: "vertical", className: "q1-product-lockup__divider" }),
4684
- /* @__PURE__ */ n("span", { className: "q1-product-lockup__endorsement", children: r })
4685
+ /* @__PURE__ */ n("span", { className: "q1-product-lockup__endorsement", children: l })
4685
4686
  ]
4686
4687
  }
4687
4688
  );
@@ -125,6 +125,15 @@
125
125
  --q1-color-bg-overlay: var(--q1-color-background-100);
126
126
  --q1-color-bg-hover: color-mix(in srgb, var(--q1-color-text-primary) 4%, transparent);
127
127
  --q1-color-bg-selected: var(--q1-color-primary-100);
128
+ /* 表格行底色:单元格自带不透明底色,行状态只换取值,固定列与普通列同色、永不透出下层。
129
+ 半透明的 bg-hover 不能直接用于固定列——叠在已有底色的行上会双层加深。以下取值为预混结果:
130
+ hover = bg-hover(text-primary 4%)叠在 bg-canvas 上;selected = bg-selected(本身不透明);
131
+ selected-hover = bg-hover 半强度(2%)叠在 bg-selected 上,整强度会把 text-muted 压到 AA 以下。
132
+ 推导与对比度由 check-contrast-contract 锁定;改表面色或悬停强度须同步重算。 */
133
+ --q1-table-row-bg: var(--q1-color-bg-canvas);
134
+ --q1-table-row-bg-hover: #f6f6f6;
135
+ --q1-table-row-bg-selected: var(--q1-color-bg-selected);
136
+ --q1-table-row-bg-selected-hover: #edebfa;
128
137
  --q1-color-bg-inverse: var(--q1-color-gray-1000);
129
138
  --q1-color-text-on-inverse: var(--q1-color-background-100);
130
139
  --q1-color-bg-media: #0a0a0a;
@@ -406,6 +415,9 @@
406
415
  --q1-color-bg-overlay: var(--q1-color-gray-300);
407
416
  --q1-color-bg-hover: color-mix(in srgb, var(--q1-color-text-primary) 6%, transparent);
408
417
  --q1-color-bg-selected: #1f1e38;
418
+ /* 暗色预混:hover = text-primary 6% 叠在 bg-canvas 上;selected-hover 取半强度 3%。 */
419
+ --q1-table-row-bg-hover: #1f1f1f;
420
+ --q1-table-row-bg-selected-hover: #25243d;
409
421
  --q1-color-bg-inverse: var(--q1-color-gray-1000);
410
422
  --q1-color-text-on-inverse: #0a0a0a;
411
423
  --q1-color-bg-media: #0a0a0a;
@@ -1909,6 +1921,21 @@
1909
1921
  font-weight: var(--q1-font-weight-medium);
1910
1922
  }
1911
1923
 
1924
+ /* 底色落在单元格上而不是行上:消费方把某列设为 position: sticky 时,它与同行其余单元格读同一个
1925
+ 不透明值,横向滚动不透底,悬停也不会在行底色之上再叠一层。行状态只改 --table-cell-bg。 */
1926
+ .table tbody tr {
1927
+ --table-cell-bg: var(--q1-table-row-bg, var(--q1-color-bg-canvas));
1928
+ }
1929
+
1930
+ .table tbody td,
1931
+ .table tbody th {
1932
+ background: var(--table-cell-bg);
1933
+ }
1934
+
1935
+ .table tbody tr:has(.table__checkbox-control input:checked) {
1936
+ --table-cell-bg: var(--q1-table-row-bg-selected, var(--q1-color-bg-selected));
1937
+ }
1938
+
1912
1939
  .table__head--hidden {
1913
1940
  position: absolute;
1914
1941
  width: 1px;
@@ -1942,7 +1969,7 @@
1942
1969
  position: sticky;
1943
1970
  top: 0;
1944
1971
  z-index: 1;
1945
- background: var(--q1-color-bg-canvas);
1972
+ background: var(--q1-table-row-bg, var(--q1-color-bg-canvas));
1946
1973
  }
1947
1974
 
1948
1975
  .table__sort {
@@ -1994,8 +2021,35 @@
1994
2021
  cursor: not-allowed;
1995
2022
  }
1996
2023
 
2024
+ /* 焦点环画在单元格上:单元格自带不透明底色,行上的阴影或 outline 会被单元格底色、
2025
+ 以及消费方的 sticky 列盖住。每格画上下两边,首末格补外侧一边,拼成整行的一圈。 */
1997
2026
  .table tbody tr[tabindex='0']:focus-visible {
1998
2027
  outline: none;
2028
+ }
2029
+
2030
+ .table tbody tr[tabindex='0']:focus-visible > * {
2031
+ --table-focus-edge: inset 0 2px 0 var(--q1-color-action-primary), inset 0 -2px 0 var(--q1-color-action-primary);
2032
+ box-shadow: var(--table-focus-edge);
2033
+ }
2034
+
2035
+ .table tbody tr[tabindex='0']:focus-visible > :first-child {
2036
+ box-shadow: var(--table-focus-edge), inset 2px 0 0 var(--q1-color-action-primary);
2037
+ }
2038
+
2039
+ .table tbody tr[tabindex='0']:focus-visible > :last-child {
2040
+ box-shadow: var(--table-focus-edge), inset -2px 0 0 var(--q1-color-action-primary);
2041
+ }
2042
+
2043
+ .table tbody tr[tabindex='0']:focus-visible > :first-child:dir(rtl) {
2044
+ box-shadow: var(--table-focus-edge), inset -2px 0 0 var(--q1-color-action-primary);
2045
+ }
2046
+
2047
+ .table tbody tr[tabindex='0']:focus-visible > :last-child:dir(rtl) {
2048
+ box-shadow: var(--table-focus-edge), inset 2px 0 0 var(--q1-color-action-primary);
2049
+ }
2050
+
2051
+ /* 整行只有一格(跨列的空态、加载行)时首末是同一格,四边都要画。 */
2052
+ .table tbody tr[tabindex='0']:focus-visible > :first-child:last-child {
1999
2053
  box-shadow: inset 0 0 0 2px var(--q1-color-action-primary);
2000
2054
  }
2001
2055
 
@@ -2005,12 +2059,26 @@
2005
2059
  }
2006
2060
 
2007
2061
  .table tbody tr.table__row--interactive:hover {
2008
- background: var(--q1-color-bg-subtle);
2062
+ --table-cell-bg: var(--q1-table-row-bg-hover, var(--q1-color-bg-subtle));
2063
+ }
2064
+
2065
+ .table tbody tr.table__row--interactive:hover:has(.table__checkbox-control input:checked) {
2066
+ --table-cell-bg: var(--q1-table-row-bg-selected-hover, var(--q1-color-bg-selected));
2009
2067
  }
2010
2068
  }
2011
2069
 
2070
+ /* 按压在悬停值上再加深:两个输入都不透明,混出来的仍不透明。选中行另起一支,否则选中规则的
2071
+ 特异度更高,按压没有反馈。 */
2012
2072
  .table tbody tr.table__row--interactive:active {
2013
- background: color-mix(in srgb, var(--q1-color-bg-subtle), var(--q1-color-text-primary) 8%);
2073
+ --table-cell-bg: color-mix(in srgb, var(--q1-table-row-bg-hover, var(--q1-color-bg-subtle)), var(--q1-color-text-primary) 8%);
2074
+ }
2075
+
2076
+ .table tbody tr.table__row--interactive:active:has(.table__checkbox-control input:checked) {
2077
+ --table-cell-bg: color-mix(
2078
+ in srgb,
2079
+ var(--q1-table-row-bg-selected-hover, var(--q1-color-bg-selected)),
2080
+ var(--q1-color-text-primary) 8%
2081
+ );
2014
2082
  }
2015
2083
 
2016
2084
  .table th[aria-sort='ascending'] .table__sort,
@@ -121,6 +121,10 @@
121
121
  --q1-color-bg-overlay: var(--q1-color-background-100);
122
122
  --q1-color-bg-hover: color-mix(in srgb, var(--q1-color-text-primary) 4%, transparent);
123
123
  --q1-color-bg-selected: var(--q1-color-primary-100);
124
+ --q1-table-row-bg: var(--q1-color-bg-canvas);
125
+ --q1-table-row-bg-hover: #f6f6f6;
126
+ --q1-table-row-bg-selected: var(--q1-color-bg-selected);
127
+ --q1-table-row-bg-selected-hover: #edebfa;
124
128
  --q1-color-bg-inverse: var(--q1-color-gray-1000);
125
129
  --q1-color-text-on-inverse: var(--q1-color-background-100);
126
130
  --q1-color-bg-media: #0a0a0a;
@@ -389,6 +393,10 @@
389
393
  --q1-color-bg-overlay: var(--q1-color-gray-300);
390
394
  --q1-color-bg-hover: color-mix(in srgb, var(--q1-color-text-primary) 6%, transparent);
391
395
  --q1-color-bg-selected: #1f1e38;
396
+ --q1-table-row-bg: var(--q1-color-bg-canvas);
397
+ --q1-table-row-bg-hover: #1f1f1f;
398
+ --q1-table-row-bg-selected: var(--q1-color-bg-selected);
399
+ --q1-table-row-bg-selected-hover: #25243d;
392
400
  --q1-color-bg-inverse: var(--q1-color-gray-1000);
393
401
  --q1-color-text-on-inverse: #0a0a0a;
394
402
  --q1-color-bg-media: #0a0a0a;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q1travel/design-system",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "React components, design tokens, and interface contracts for q1travel products.",
5
5
  "keywords": [
6
6
  "react",