@pieai/swimmer-ui-kit 1.1.0 → 1.2.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,36 @@
3
3
  All notable changes to `@pieai/swimmer-ui-kit`.
4
4
  Format: [Keep a Changelog](https://keepachangelog.com); versioning: semver.
5
5
 
6
+ ## 1.2.0 — 2026-07-18
7
+
8
+ Purely additive: an official "overlay glass" HUD surface tone plus a compact
9
+ density, for products that float kit chrome over a live scene (TuringPact 3D
10
+ tavern, SupaLuv cinematic stage). No exported component, prop, class, or token
11
+ was removed or renamed.
12
+
13
+ ### Added
14
+
15
+ - Overlay glass scope: `data-game-ui-tone="glass"` (alias class
16
+ `.game-ui-overlay-scope`) re-scopes semantic surface/text/elevation tokens on
17
+ a subtree to dark translucent glass — fill `rgba(12,14,20,0.72)`, 1px light
18
+ border, no clay box-shadow, warm accent hover/primary, WCAG-visible warm
19
+ focus ring (`--game-ui-overlay-glass-focus-ring`). Nests inside light or
20
+ `night` page themes.
21
+ - Compact density: `data-game-ui-density="compact"` (orthogonal to tone) —
22
+ 34px control floor, tighter panel/chip padding for HUD clusters.
23
+ - Primitive tokens `--game-ui-overlay-glass-*` in `theme.css`; TS mirrors
24
+ `CLAY_OVERLAY_GLASS_TOKENS` and `GAME_UI_OVERLAY` attr/class constants.
25
+ - Clay `GameAssetIcon` gets a soft dark drop-shadow inside glass scope so
26
+ sculpted icons read on translucent dark chips.
27
+ - Stories/preview compare: same HUD cluster in default clay vs overlay glass
28
+ over a busy scene background, light and night contexts.
29
+
30
+ ### Migration notes
31
+
32
+ - Consumers opt in per subtree; nothing changes without the attribute.
33
+ - SupaLuv can delete its `.vn-stage .game-ui-button` `!important` overrides
34
+ (stage.css ~217-360) after wrapping its HUD in the glass scope.
35
+
6
36
  ## 1.1.0 — 2026-07-13
7
37
 
8
38
  A design-system quality pass: fixes real bugs in the existing surface
@@ -6,10 +6,11 @@
6
6
  // "token-only" bar the design-system-guide asks for.
7
7
  //
8
8
  // Raw colors are expected (and fine) inside token-defining blocks —
9
- // :root { ... } or an attribute-selector theme block like
10
- // [data-game-ui-theme='night'] / [data-theme='dark'] — since that is
11
- // exactly how the design-system-guide tells consumers to re-theme. Only
12
- // raw colors inside *other* selectors (component rules) are flagged.
9
+ // :root { ... } or an attribute-selector theme/tone block like
10
+ // [data-game-ui-theme='night'] / [data-game-ui-tone='glass'] /
11
+ // [data-theme='dark'] — since that is how the design-system-guide tells
12
+ // consumers to re-theme or re-scope surface tones. Only raw colors inside
13
+ // *other* selectors (component rules) are flagged.
13
14
  //
14
15
  // Usage: swimmer-ui-check [dir] [--ext=css,tsx]
15
16
  // dir directory to scan, default "src"
@@ -18,8 +19,15 @@ import { readFileSync, readdirSync, statSync } from 'node:fs';
18
19
  import { extname, join, relative } from 'node:path';
19
20
 
20
21
  const RAW_COLOR = /#[0-9a-fA-F]{3,8}\b|\brgba?\(|\bhsla?\(|\boklch\(/g;
21
- const TOKEN_BLOCK_SELECTOR = /:root\b|\[data-[\w-]*theme[\w-]*\s*=/i;
22
- const IGNORE_DIRS = new Set(['node_modules', 'dist', '.git', 'storybook-static', 'site-dist', 'build']);
22
+ const TOKEN_BLOCK_SELECTOR = /:root\b|\[data-[\w-]*(?:theme|tone)[\w-]*\s*=/i;
23
+ const IGNORE_DIRS = new Set([
24
+ 'node_modules',
25
+ 'dist',
26
+ '.git',
27
+ 'storybook-static',
28
+ 'site-dist',
29
+ 'build',
30
+ ]);
23
31
 
24
32
  function walk(dir, exts, out) {
25
33
  for (const entry of readdirSync(dir)) {
@@ -90,7 +98,9 @@ const args = process.argv.slice(2);
90
98
  const target = args.find((a) => !a.startsWith('--')) ?? 'src';
91
99
  const extArg = args.find((a) => a.startsWith('--ext='));
92
100
  const exts = new Set(
93
- (extArg ? extArg.slice('--ext='.length).split(',') : ['css']).map((e) => (e.startsWith('.') ? e : `.${e}`)),
101
+ (extArg ? extArg.slice('--ext='.length).split(',') : ['css']).map((e) =>
102
+ e.startsWith('.') ? e : `.${e}`,
103
+ ),
94
104
  );
95
105
 
96
106
  const files = [];
@@ -105,7 +115,9 @@ let violationCount = 0;
105
115
  for (const file of files) {
106
116
  const text = readFileSync(file, 'utf8');
107
117
  for (const violation of findViolations(text)) {
108
- console.log(`${relative(process.cwd(), file)}:${violation.line}: raw color literal "${violation.text}" — use var(--game-ui-*) instead`);
118
+ console.log(
119
+ `${relative(process.cwd(), file)}:${violation.line}: raw color literal "${violation.text}" — use var(--game-ui-*) instead`,
120
+ );
109
121
  violationCount += 1;
110
122
  }
111
123
  }
@@ -113,9 +125,12 @@ for (const file of files) {
113
125
  if (violationCount > 0) {
114
126
  console.error(
115
127
  `\nswimmer-ui-check: ${violationCount} raw color literal(s) in ${files.length} file(s) under "${target}". ` +
116
- 'Raw colors are expected inside :root / [data-*theme*=...] token blocks (that is how you re-theme the kit) ' +
117
- 'but not inside component rules — see the design-system-guide "主题化配方" section.',
128
+ 'Raw colors are expected inside :root / [data-*theme*=...] / [data-*tone*=...] token blocks ' +
129
+ '(that is how you re-theme or re-scope the kit) but not inside component rules — see the ' +
130
+ 'design-system-guide "主题化配方" section.',
118
131
  );
119
132
  process.exit(1);
120
133
  }
121
- console.log(`swimmer-ui-check: 0 raw color literals in component rules across ${files.length} file(s) under "${target}". Clean.`);
134
+ console.log(
135
+ `swimmer-ui-check: 0 raw color literals in component rules across ${files.length} file(s) under "${target}". Clean.`,
136
+ );
package/dist/index.d.ts CHANGED
@@ -72,6 +72,9 @@ export declare const CLAY_COLOR_TOKENS: {
72
72
  readonly shadow: "rgba(76, 52, 28, 0.24)";
73
73
  readonly glass: "rgba(255, 248, 236, 0.82)";
74
74
  readonly nightGlass: "rgba(31, 24, 18, 0.76)";
75
+ /** Official HUD-on-scene glass fill (matches SupaLuv stage chrome). */
76
+ readonly overlayGlass: "rgba(12, 14, 20, 0.72)";
77
+ readonly overlayGlassText: "#fff6ee";
75
78
  };
76
79
 
77
80
  export declare const CLAY_ELEVATION_TOKENS: {
@@ -268,6 +271,26 @@ export declare const CLAY_MOTION_TOKENS: {
268
271
  readonly reducedMotion: "var(--game-ui-reduced-motion-policy)";
269
272
  };
270
273
 
274
+ /**
275
+ * Semantic CSS vars for the official overlay-glass HUD tone
276
+ * (`data-game-ui-tone="glass"` / `.game-ui-overlay-scope`).
277
+ */
278
+ declare const CLAY_OVERLAY_GLASS_TOKENS: {
279
+ readonly bg: "var(--game-ui-overlay-glass-bg)";
280
+ readonly bgHover: "var(--game-ui-overlay-glass-bg-hover)";
281
+ readonly bgStrong: "var(--game-ui-overlay-glass-bg-strong)";
282
+ readonly bgPanel: "var(--game-ui-overlay-glass-bg-panel)";
283
+ readonly border: "var(--game-ui-overlay-glass-border)";
284
+ readonly borderHover: "var(--game-ui-overlay-glass-border-hover)";
285
+ readonly text: "var(--game-ui-overlay-glass-text)";
286
+ readonly textMuted: "var(--game-ui-overlay-glass-text-muted)";
287
+ readonly blur: "var(--game-ui-overlay-glass-blur)";
288
+ readonly focusRing: "var(--game-ui-overlay-glass-focus-ring)";
289
+ readonly primaryFill: "var(--game-ui-overlay-glass-primary-fill)";
290
+ };
291
+ export { CLAY_OVERLAY_GLASS_TOKENS }
292
+ export { CLAY_OVERLAY_GLASS_TOKENS as GAME_UI_OVERLAY_GLASS_TOKENS }
293
+
271
294
  export declare const CLAY_RADIUS_TOKENS: {
272
295
  readonly bead: "var(--game-ui-radius-bead)";
273
296
  readonly control: "var(--game-ui-radius-control)";
@@ -363,6 +386,9 @@ export declare const CLAY_UI_TOKENS: {
363
386
  readonly shadow: "rgba(76, 52, 28, 0.24)";
364
387
  readonly glass: "rgba(255, 248, 236, 0.82)";
365
388
  readonly nightGlass: "rgba(31, 24, 18, 0.76)";
389
+ /** Official HUD-on-scene glass fill (matches SupaLuv stage chrome). */
390
+ readonly overlayGlass: "rgba(12, 14, 20, 0.72)";
391
+ readonly overlayGlassText: "#fff6ee";
366
392
  };
367
393
  readonly semantic: {
368
394
  readonly background: "var(--game-ui-bg)";
@@ -470,6 +496,19 @@ export declare const CLAY_UI_TOKENS: {
470
496
  readonly buildRailCardSize: "var(--game-ui-build-rail-card-size)";
471
497
  readonly brushNumberWidth: "var(--game-ui-brush-number-width)";
472
498
  };
499
+ readonly overlayGlass: {
500
+ readonly bg: "var(--game-ui-overlay-glass-bg)";
501
+ readonly bgHover: "var(--game-ui-overlay-glass-bg-hover)";
502
+ readonly bgStrong: "var(--game-ui-overlay-glass-bg-strong)";
503
+ readonly bgPanel: "var(--game-ui-overlay-glass-bg-panel)";
504
+ readonly border: "var(--game-ui-overlay-glass-border)";
505
+ readonly borderHover: "var(--game-ui-overlay-glass-border-hover)";
506
+ readonly text: "var(--game-ui-overlay-glass-text)";
507
+ readonly textMuted: "var(--game-ui-overlay-glass-text-muted)";
508
+ readonly blur: "var(--game-ui-overlay-glass-blur)";
509
+ readonly focusRing: "var(--game-ui-overlay-glass-focus-ring)";
510
+ readonly primaryFill: "var(--game-ui-overlay-glass-primary-fill)";
511
+ };
473
512
  };
474
513
 
475
514
  export declare type ClayAssetGroup = keyof typeof CLAY_ASSETS;
@@ -507,7 +546,7 @@ export declare type ClayIconStyle = 'game' | 'line';
507
546
 
508
547
  export declare type ClayTokenCategory = keyof typeof CLAY_UI_TOKENS;
509
548
 
510
- export declare function FirstSessionHud({ authenticated, batteryCount, className, dailyStreak, iconSlots, labels, onHistory, onSettings, onWardrobe, playerName }: FirstSessionHudProps): ReactNode;
549
+ export declare function FirstSessionHud({ authenticated, batteryCount, className, dailyStreak, iconSlots, labels, onHistory, onSettings, onWardrobe, playerName, }: FirstSessionHudProps): ReactNode;
511
550
 
512
551
  export declare interface FirstSessionHudIconSlots {
513
552
  history?: ReactNode;
@@ -556,7 +595,7 @@ export declare interface FirstSessionHudProps {
556
595
  playerName: string;
557
596
  }
558
597
 
559
- export declare function FirstSessionOnboarding({ labels, onDismiss, open }: FirstSessionOnboardingProps): ReactNode;
598
+ export declare function FirstSessionOnboarding({ labels, onDismiss, open, }: FirstSessionOnboardingProps): ReactNode;
560
599
 
561
600
  export declare interface FirstSessionOnboardingLabels {
562
601
  badge: string;
@@ -578,6 +617,15 @@ export declare interface FirstSessionOnboardingStep {
578
617
  title: string;
579
618
  }
580
619
 
620
+ /** Opt-in attribute values for the official overlay-glass HUD scope. */
621
+ export declare const GAME_UI_OVERLAY: {
622
+ readonly toneAttr: "data-game-ui-tone";
623
+ readonly toneGlass: "glass";
624
+ readonly densityAttr: "data-game-ui-density";
625
+ readonly densityCompact: "compact";
626
+ readonly scopeClass: "game-ui-overlay-scope";
627
+ };
628
+
581
629
  export declare const GAME_UI_PREVIEW_MESSAGES: readonly GameUiHistoryEntry[];
582
630
 
583
631
  export declare const GAME_UI_TARGETS: {
@@ -681,7 +729,7 @@ export declare const GAME_UI_TOKENS: {
681
729
  readonly disabled: "var(--game-ui-disabled)";
682
730
  };
683
731
 
684
- export declare function GameActionGrid({ actions, className, density, iconLabelMode, label, style }: GameActionGridProps): ReactNode;
732
+ export declare function GameActionGrid({ actions, className, density, iconLabelMode, label, style, }: GameActionGridProps): ReactNode;
685
733
 
686
734
  export declare interface GameActionGridProps {
687
735
  actions: readonly GameUiAction[];
@@ -736,7 +784,7 @@ export declare interface GameAssetGroup {
736
784
  source?: GameAssetSource;
737
785
  }
738
786
 
739
- export declare function GameAssetIcon({ className, icon, label, size, style, useSourceAsset }: GameAssetIconProps): ReactNode;
787
+ export declare function GameAssetIcon({ className, icon, label, size, style, useSourceAsset, }: GameAssetIconProps): ReactNode;
740
788
 
741
789
  export declare interface GameAssetIconProps {
742
790
  className?: string;
@@ -773,7 +821,7 @@ export declare type GameAssetSource = 'starter' | 'generated' | 'imported';
773
821
 
774
822
  export declare type GameAssetStatus = 'ready' | 'generating' | 'missing' | 'placed' | 'selected' | 'error';
775
823
 
776
- export declare function GameAvatar({ className, name, size, src, status }: GameAvatarProps): ReactNode;
824
+ export declare function GameAvatar({ className, name, size, src, status, }: GameAvatarProps): ReactNode;
777
825
 
778
826
  export declare interface GameAvatarProps {
779
827
  /** Display name — used as image alt text and for the initials fallback. */
@@ -1155,7 +1203,7 @@ export declare interface GameDialogProps {
1155
1203
  title: string;
1156
1204
  }
1157
1205
 
1158
- export declare function GameEmptyState({ action, className, description, icon, title }: GameEmptyStateProps): ReactNode;
1206
+ export declare function GameEmptyState({ action, className, description, icon, title, }: GameEmptyStateProps): ReactNode;
1159
1207
 
1160
1208
  export declare interface GameEmptyStateProps {
1161
1209
  /** Optional clay icon shown above the title. */
@@ -1176,7 +1224,7 @@ export declare interface GameFactItem {
1176
1224
  value: ReactNode;
1177
1225
  }
1178
1226
 
1179
- export declare function GameFactList({ className, density, facts, label, variant }: GameFactListProps): ReactNode;
1227
+ export declare function GameFactList({ className, density, facts, label, variant, }: GameFactListProps): ReactNode;
1180
1228
 
1181
1229
  export declare interface GameFactListProps {
1182
1230
  className?: string;
@@ -1186,7 +1234,7 @@ export declare interface GameFactListProps {
1186
1234
  variant?: 'facts' | 'stats';
1187
1235
  }
1188
1236
 
1189
- export declare function GameField({ children, className, error, hint, label, required }: GameFieldProps): ReactNode;
1237
+ export declare function GameField({ children, className, error, hint, label, required, }: GameFieldProps): ReactNode;
1190
1238
 
1191
1239
  export declare interface GameFieldProps {
1192
1240
  /** The input/textarea this field labels. Rendered inside the <label>. */
@@ -1286,7 +1334,7 @@ export declare interface GameInteractionSoundOptions {
1286
1334
  sfxVolume?: number;
1287
1335
  }
1288
1336
 
1289
- export declare function GameLanguageMenu({ className, currentLabel, label, options, value, defaultValue, onSelect }: GameLanguageMenuProps): ReactNode;
1337
+ export declare function GameLanguageMenu({ className, currentLabel, label, options, value, defaultValue, onSelect, }: GameLanguageMenuProps): ReactNode;
1290
1338
 
1291
1339
  export declare interface GameLanguageMenuProps {
1292
1340
  className?: string;
@@ -1377,7 +1425,7 @@ export declare const GameObjectToolbar: typeof GamePlacementToolbar;
1377
1425
 
1378
1426
  export declare type GameObjectToolbarProps = GamePlacementToolbarProps;
1379
1427
 
1380
- export declare function GameOrientationGate({ body, cta, badgeLabel, manualHint, preview, title }: GameOrientationGateProps): ReactNode;
1428
+ export declare function GameOrientationGate({ body, cta, badgeLabel, manualHint, preview, title, }: GameOrientationGateProps): ReactNode;
1381
1429
 
1382
1430
  export declare interface GameOrientationGateProps {
1383
1431
  body: string;
@@ -1417,7 +1465,7 @@ export declare interface GamePlacementToolbarProps {
1417
1465
  title: string;
1418
1466
  }
1419
1467
 
1420
- export declare function GameProgress({ className, label, max, showValue, tone, value }: GameProgressProps): ReactNode;
1468
+ export declare function GameProgress({ className, label, max, showValue, tone, value, }: GameProgressProps): ReactNode;
1421
1469
 
1422
1470
  export declare interface GameProgressProps {
1423
1471
  /** Current value, between 0 and `max`. */
@@ -1480,7 +1528,7 @@ export declare const GameSceneHudLayout: typeof GameShell;
1480
1528
 
1481
1529
  export declare type GameSceneHudLayoutProps = GameShellProps;
1482
1530
 
1483
- export declare function GameSegmentedControl({ activeId, label, onSelect, options }: GameSegmentedControlProps): ReactNode;
1531
+ export declare function GameSegmentedControl({ activeId, label, onSelect, options, }: GameSegmentedControlProps): ReactNode;
1484
1532
 
1485
1533
  export declare interface GameSegmentedControlProps {
1486
1534
  activeId: string;