@linhey/rhine-design 0.6.0 → 0.8.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +19 -8
  3. package/components/Actions.tsx +18 -1
  4. package/components/AppShell.tsx +46 -17
  5. package/components/Media.tsx +7 -7
  6. package/components/NeutronStarBackdrop.tsx +43 -0
  7. package/components/OrbitBackdrop.tsx +4 -2
  8. package/components/Overlays.tsx +37 -8
  9. package/components/README.md +27 -3
  10. package/components/StatusTimeline.tsx +72 -6
  11. package/components/StatusTimelineList.tsx +38 -0
  12. package/components/ThemePicker.tsx +49 -0
  13. package/components/assets/orbit-bird.svg +578 -0
  14. package/components/assets/orbit-crystal.svg +11 -0
  15. package/components/assets/orbit-donut.svg +16 -0
  16. package/components/assets/theme-previews/arknights.png +0 -0
  17. package/components/assets/theme-previews/manifest.json +24 -0
  18. package/components/assets/theme-previews/neo-brutalism.png +0 -0
  19. package/components/assets/theme-previews/rhine.png +0 -0
  20. package/components/common.css +3 -3
  21. package/components/components.tsx +3 -3
  22. package/components/dialog-settings.css +9 -0
  23. package/components/extensions.css +8 -32
  24. package/components/index.ts +11 -5
  25. package/components/media-parity.css +55 -2
  26. package/components/neutron.css +53 -0
  27. package/components/neutronRenderer.ts +327 -0
  28. package/components/orbit.css +79 -1
  29. package/components/orbitBirdFlight.ts +34 -0
  30. package/components/orbitBirdGeometry.ts +158 -0
  31. package/components/orbitDonut.ts +134 -0
  32. package/components/orbitDonutThree.ts +208 -0
  33. package/components/orbitObjectMaterials.ts +76 -0
  34. package/components/orbitObjects.ts +71 -0
  35. package/components/orbitObjectsThree.ts +215 -0
  36. package/components/orbitProjection.ts +21 -0
  37. package/components/orbitRenderer.ts +163 -46
  38. package/components/styles.css +3 -1
  39. package/components/theme-neo-brutalism.css +3 -2
  40. package/components/theme-picker.css +17 -0
  41. package/components/theme.tsx +2 -8
  42. package/components/themeMetadata.ts +7 -0
  43. package/components/timeline.css +17 -6
  44. package/components/useFloatingScale.ts +96 -0
  45. package/docs/APPLICATION_COMPONENTS.md +52 -3
  46. package/docs/COMPACT_ACCOUNT_PATTERNS.md +70 -0
  47. package/docs/DATE_RANGE_FILTER.md +60 -0
  48. package/docs/DESIGN_SYSTEM.md +7 -0
  49. package/docs/FLOATING_OVERLAYS.md +15 -0
  50. package/docs/INTERACTION_PATTERNS.md +5 -1
  51. package/docs/NEUTRON_STAR_BACKDROP.md +122 -0
  52. package/docs/ORBIT_BACKDROP.md +38 -46
  53. package/docs/SETTINGS_DIALOG.md +21 -0
  54. package/docs/THEME_PICKER.md +26 -0
  55. package/docs/THEMING.md +2 -0
  56. package/docs/assets/compact-account-neo.png +0 -0
  57. package/docs/assets/neutron-star-original.png +0 -0
  58. package/docs/assets/neutron-star-theme.png +0 -0
  59. package/docs/assets/orbit-bird.png +0 -0
  60. package/docs/assets/orbit-crystal.png +0 -0
  61. package/docs/assets/orbit-strawberry.png +0 -0
  62. package/package.json +8 -3
  63. package/preview/CompactAccountGallery.tsx +178 -0
  64. package/preview/DateRangeFilterGallery.tsx +109 -0
  65. package/preview/ExtensionsGallery.tsx +27 -18
  66. package/preview/GalleryShell.tsx +3 -3
  67. package/preview/MonitoringGallery.tsx +2 -0
  68. package/preview/NeutronStarGallery.tsx +56 -0
  69. package/preview/OrbitGallery.tsx +35 -32
  70. package/preview/OverlayBoundsGallery.tsx +49 -0
  71. package/preview/SettingsDialogGallery.tsx +33 -0
  72. package/preview/ThemePickerGallery.tsx +24 -0
  73. package/preview/ThemeSample.tsx +14 -0
  74. package/preview/TimelineListGallery.tsx +36 -0
  75. package/preview/extensions.css +9 -0
  76. package/preview/main.tsx +16 -3
  77. package/preview/preview.css +8 -0
  78. package/preview/theme-sample.html +1 -0
  79. package/scripts/check-overlay-bounds.js +76 -0
  80. package/scripts/check-settings-theme.js +88 -0
  81. package/skills/rhine-design/SKILL.md +3 -2
  82. package/skills/rhine-design/references/API_MAP.md +13 -2
  83. package/skills/rhine-design/references/TASK_MAP.md +8 -2
  84. package/skills/rhine-design/references/integration.md +1 -1
  85. package/tests/AppShellControls.test.tsx +82 -0
  86. package/tests/ButtonLink.test.tsx +94 -0
  87. package/tests/CompactAccountGallery.test.tsx +116 -0
  88. package/tests/DateRangeFilterGallery.test.tsx +85 -0
  89. package/tests/NeutronStarBackdrop.test.tsx +288 -0
  90. package/tests/NeutronStarGallery.test.tsx +62 -0
  91. package/tests/NeutronStarImport.test.tsx +15 -0
  92. package/tests/OrbitBackdrop.test.tsx +246 -9
  93. package/tests/OrbitDonutThree.test.tsx +91 -0
  94. package/tests/OrbitObjectsThree.test.tsx +164 -0
  95. package/tests/SettingsDialog.test.tsx +66 -0
  96. package/tests/StatusTimelineList.test.tsx +63 -0
  97. package/tests/ThemePicker.test.tsx +30 -0
  98. package/tests/TimelineLegend.test.tsx +60 -0
@@ -0,0 +1,16 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 320" fill="none">
2
+ <ellipse cx="210" cy="282" rx="133" ry="16" fill="#E5C8B9"/>
3
+ <g transform="rotate(-60 200 153)">
4
+ <g stroke="#202323" stroke-width="4" stroke-linejoin="round">
5
+ <path fill="#DF9451" fill-rule="evenodd" d="M350 153c0 69-67 112-150 112S50 222 50 153 117 41 200 41s150 43 150 112Zm-98 0c0-20-23-34-52-34s-52 14-52 34 23 34 52 34 52-14 52-34Z"/>
6
+ <path fill="#F58EB3" fill-rule="evenodd" d="M349 137c6 28-11 58-28 67-9 16-18 4-29 17-13 18-22 1-39 11-14 11-24 1-39 8-15 9-29-7-44-1-17 4-25-12-40-10-18 3-22-19-36-17-14-1-20-21-31-24-15-15-21-32-13-55C60 73 123 37 200 37s137 36 149 100Zm-98 5c0-11-12-18-21-19-8-14-19-3-31-9-12-4-21 9-32 7-9 0-19 14-18 24-7 24 22 40 51 40 33 0 59-18 51-43Z"/>
7
+ </g>
8
+ <g stroke-linecap="round" stroke-width="6">
9
+ <path stroke="#FFF8E8" d="m91 120 10-8m57-34 7-9m69 1 13 3m65 45 9 7m-53 77 10-9m-116 18 9 5m-51-37 7 11"/>
10
+ <path stroke="#36735C" d="m119 103 11 3m61-34 2-10m83 31 8-5m37 72-12-2m-69 64-10-5m-103-24-8-3"/>
11
+ <path stroke="#FFD44B" d="m77 151 7 9m69-59 8 7m52-12 10 2m65 31 3 10m-20 50-9-2m-75 27 3 11"/>
12
+ <path stroke="#E54C77" d="m115 141 5 9m66-53 10 1m60-16 10 6m54 47-6 10m-72 52-8 2m-78-8-8-9"/>
13
+ </g>
14
+ <path d="M90 105c15-21 35-33 53-40m129 128c14-4 24-11 33-18" stroke="#FFE0EB" stroke-width="5" stroke-linecap="round"/>
15
+ </g>
16
+ </svg>
@@ -0,0 +1,24 @@
1
+ {
2
+ "revision": 1,
3
+ "sourceBaseline": "95578008442d06bdda681f2722f46b0d3cb01794",
4
+ "width": 960,
5
+ "height": 600,
6
+ "sourceSHA256": {
7
+ "preview/ThemeSample.tsx": "1922382b1bd075726838323d4cd0b64ad1e0c90118c24fee50b49d77dfb78fcd",
8
+ "components/theme.tsx": "68b739a38e6dc2faf01fa3a17af95ce47411cb592857df981d8c3d10ec05824c",
9
+ "components/tokens.css": "d6ae0c876d40e17ba80fd4eed5a5e1ff0a58a8fba7d0b3210906f5738ef57d44",
10
+ "components/theme-arknights.css": "114f2d877e41a1dd0fe7ccc801166bbf2a67031cb110f05ccdcf779e67f9f5d7",
11
+ "components/theme-neo-brutalism.css": "0205d7f3bf4167724f2be0ae8dbabbdc5f0adb81dd0f2386c3be02c73cb7ee32",
12
+ "components/components.tsx": "4926d35115b4b11f7277789d9df9917c5c355cdabd3287fc9c4c55e996611a66",
13
+ "components/common.css": "246f2e07d84b2d0cd81e94b615850bb4b112aae97c34a9548b190447f84d4c16",
14
+ "components/Navigation.tsx": "4d77b0a51897c0758529285b7a6672920685ce39c8ee0372b2d282eac1d769c7",
15
+ "components/Layout.tsx": "d802937b725d7c1783242ecb21d51dcf0aa0497f6e48502ebbc1d98fd63aa8f1",
16
+ "components/Typography.tsx": "b82a590ec61b9f901c75ebfb5421931240dbb34e710c2eaf2bfa678e4f15f454",
17
+ "components/themeMetadata.ts": "c795fa74ed742ab9746db058919aac4de2978bbde3dfe7352075e1b9d2628b73"
18
+ },
19
+ "images": {
20
+ "arknights.png": "6787af3f88612fcd6f3550114056d6281ce51a2a3b03c9e38eb5235ab14fdb46",
21
+ "neo-brutalism.png": "02faec22e585718e7121411cc71dc0efea86376089c94c1ba7195548bdb73255",
22
+ "rhine.png": "2bbb22a1c6da3afd5f0af079d3977ca4399d1502bba1d908fadb78cd89918049"
23
+ }
24
+ }
@@ -49,7 +49,7 @@
49
49
  .rhine-combobox__list [role=option][aria-disabled=true],.rhine-combobox__empty { color:var(--rhine-muted); cursor:default; }
50
50
  .rhine-overlay-anchor { display:inline-block; vertical-align:middle; max-width:100%; }
51
51
  .rhine-overlay { position:fixed; inset:0; background:var(--rhine-backdrop-bg); z-index:40; }
52
- .rhine-dialog { position:fixed; z-index:41; top:50%; left:50%; transform:translate(-50%,-50%); width:min(480px,calc(100vw - 32px)); max-height:calc(100dvh - 32px); overflow:auto; padding:24px; border:1px solid var(--rhine-line); border-radius:4px; background:var(--rhine-overlay-bg); color:var(--rhine-overlay-text); box-shadow:0 16px 48px #242b2826; }
52
+ .rhine-dialog { position:fixed; z-index:41; top:50%; left:50%; transform:translate(-50%,-50%); width:min(480px,calc(100% - 32px)); max-height:calc(100% - 32px); overflow:auto; padding:24px; border:1px solid var(--rhine-line); border-radius:4px; background:var(--rhine-overlay-bg); color:var(--rhine-overlay-text); box-shadow:0 16px 48px #242b2826; }
53
53
  .rhine-dialog>p,.rhine-dialog__main>p { margin-top:12px; }.rhine-dialog>.rhine-notice { margin-top:16px; }
54
54
  .rhine-dialog__main { min-width:0; }
55
55
  .rhine-dialog--split { width:min(960px,calc(100vw - 32px)); display:grid; grid-template-columns:minmax(240px,0.8fr) minmax(0,1.2fr); gap:24px; }
@@ -64,12 +64,12 @@
64
64
  .rhine-dialog__head>:first-child { min-width:0; overflow-wrap:anywhere; }
65
65
  .rhine-dialog__body { margin-top:24px; }.rhine-dialog__actions { display:flex; justify-content:flex-end; flex-wrap:wrap; gap:12px; margin-top:24px; }
66
66
  .rhine-popover,.rhine-menu { z-index:50; background:var(--rhine-overlay-bg); color:var(--rhine-overlay-text); border:1px solid var(--rhine-control); border-radius:4px; box-shadow:0 8px 24px #242b2820; max-width:calc(100vw - 24px); overflow:auto; }
67
- .rhine-popover { width:300px; padding:16px; max-height:var(--radix-popover-content-available-height); }
67
+ .rhine-popover { overflow-wrap:anywhere; width:300px; padding:16px; max-height:var(--radix-popover-content-available-height); }
68
68
  .rhine-menu { min-width:180px; max-height:var(--radix-dropdown-menu-content-available-height); padding:4px; }
69
69
  .rhine-menu__item { min-height:44px; padding:10px 12px; cursor:pointer; outline:none; overflow-wrap:anywhere; }
70
70
  .rhine-menu__item[data-highlighted] { background:var(--rhine-selected); box-shadow:inset 0 0 0 2px var(--rhine-green); }
71
71
  .rhine-menu__item[data-disabled] { color:var(--rhine-muted); cursor:default; }.rhine-menu__item[data-danger=true] { color:var(--rhine-error); }
72
- .rhine-tooltip { z-index:60; background:var(--rhine-ink); color:var(--rhine-surface); padding:8px 12px; border-radius:3px; max-width:min(280px,calc(100vw - 24px)); font-size:12px; line-height:18px; overflow-wrap:anywhere; }
72
+ .rhine-tooltip { overflow:auto; z-index:60; background:var(--rhine-ink); color:var(--rhine-surface); padding:8px 12px; border-radius:3px; max-width:min(280px,calc(100vw - 24px)); font-size:12px; line-height:18px; overflow-wrap:anywhere; }
73
73
  .rhine-toast-region { position:relative; }.rhine-toast { display:flex; align-items:start; gap:12px; justify-content:space-between; padding:16px; background:var(--rhine-tone-bg); border-left:3px solid var(--rhine-tone); color:var(--rhine-ink); animation:rhine-enter var(--rhine-duration-panel) var(--rhine-ease-standard); }
74
74
  .rhine-toast p { margin:4px 0 0; overflow-wrap:anywhere; }.rhine-toast strong { overflow-wrap:anywhere; }.rhine-toast>div { min-width:0; }
75
75
  .rhine-dialog[data-state=open],.rhine-overlay[data-state=open] { animation:rhine-overlay-fade var(--rhine-duration-overlay) var(--rhine-ease-standard); }
@@ -22,11 +22,11 @@ export function Badge({ tone = 'neutral', children }: { tone?: Tone; children: R
22
22
  export function Surface({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
23
23
  return <div {...props} className={classes('rhine-surface', className)} />;
24
24
  }
25
- export function SelectionCard({ label, selected, onSelectedChange, disabled = false, children }: {
26
- label: string; selected: boolean; onSelectedChange: (value: boolean) => void; disabled?: boolean; children: ReactNode;
25
+ export function SelectionCard({ label, selected, onSelectedChange, disabled = false, showIndicator = true, children }: {
26
+ label: string; selected: boolean; onSelectedChange: (value: boolean) => void; disabled?: boolean; showIndicator?: boolean; children: ReactNode;
27
27
  }) {
28
28
  return <label className="rhine-selection" data-selected={selected} data-disabled={disabled}>
29
- <span className="rhine-selection__heading"><strong>{label}</strong><input type="checkbox" aria-label={label} checked={selected} disabled={disabled} onChange={event => onSelectedChange(event.target.checked)} /></span>
29
+ <span className="rhine-selection__heading"><strong>{label}</strong><input className={showIndicator ? undefined : 'rhine-sr-only'} type="checkbox" aria-label={label} checked={selected} disabled={disabled} onChange={event => onSelectedChange(event.target.checked)} /></span>
30
30
  <span className="rhine-selection__content">{children}</span>
31
31
  </label>;
32
32
  }
@@ -0,0 +1,9 @@
1
+ .rhine-dialog--settings { width:min(960px,calc(100% - 32px)); max-height:calc(100% - 32px); container-type:inline-size; }
2
+ .rhine-dialog__settings-grid { display:grid; grid-template-columns:minmax(0,1fr); gap:24px; }
3
+ .rhine-dialog__navigation { min-width:0; padding-bottom:16px; border-bottom:1px solid var(--rhine-line); }
4
+ .rhine-dialog__settings-content { min-width:0; overflow-wrap:anywhere; }
5
+ .rhine-dialog__settings-content :is(input,textarea,select) { max-width:100%; }
6
+ @container (min-width:560px) {
7
+ .rhine-dialog__settings-grid { grid-template-columns:minmax(160px,1fr) minmax(0,3fr); }
8
+ .rhine-dialog__navigation { padding:0 24px 0 0; border-bottom:0; border-right:1px solid var(--rhine-line); }
9
+ }
@@ -4,7 +4,15 @@
4
4
  .rhine-shell__nav, .rhine-shell__secondary { flex:0 0 224px; min-width:0; overflow:auto; padding:16px; background:var(--rhine-sidebar-bg); border-right:1px solid var(--rhine-line); overflow-wrap:anywhere; }
5
5
  .rhine-shell__secondary { flex-basis:256px; }
6
6
  .rhine-shell[data-layout=left-right] .rhine-shell__secondary { order:2; border-right:0; border-left:1px solid var(--rhine-line); }
7
+ .rhine-shell__main { flex:1; display:flex; flex-direction:column; min-width:0; min-height:0; }
8
+ .rhine-shell__content-header { flex:none; min-width:0; padding:12px 24px; border-bottom:1px solid var(--rhine-line); background:var(--rhine-surface); color:var(--rhine-ink); }
9
+ .rhine-shell__content-header h1 { flex:1; min-width:0; margin:0; font:var(--rhine-weight-heading) var(--rhine-text-heading)/var(--rhine-leading-heading) var(--rhine-font); overflow-wrap:anywhere; }
10
+ .rhine-shell__content-header .rhine-inline { min-height:44px; }
11
+ .rhine-shell__content-header .rhine-shell__navigation-actions { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-inline-start:auto; }
12
+ .rhine-theme[data-rhine-theme=neo-brutalism] .rhine-shell__content-header { border-bottom:2px solid var(--rhine-ink); }
13
+ .rhine-theme[data-rhine-theme=arknights] .rhine-shell__content-header { border-bottom-color:var(--rhine-green); }
7
14
  .rhine-shell__content { flex:1; min-width:0; min-height:0; overflow:auto; padding:24px; overflow-wrap:anywhere; }
15
+ @media(max-width:760px) { .rhine-shell__content-header { padding:8px 16px; } .rhine-shell__content { padding:16px; } }
8
16
  .rhine-date-range { margin:0; min-width:0; padding:16px; border:1px solid var(--rhine-line); background:var(--rhine-field-group-bg); }
9
17
  .rhine-date-range legend { padding:0 4px; font-weight:600; }
10
18
  .rhine-date-range__fields { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr)); gap:16px; margin-bottom:16px; }
@@ -36,35 +44,3 @@
36
44
  .rhine-table__depth { display:block; white-space:nowrap; color:var(--rhine-muted); font-size:12px; }
37
45
  .rhine-table .rhine-check label { min-height:44px; }
38
46
  .rhine-pagination .rhine-select { width:auto; }
39
- .rhine-media-card { min-width:0; border:1px solid var(--rhine-line); border-radius:var(--rhine-radius-card); background:var(--rhine-surface); }
40
- .rhine-media-card[data-selected=true] { border:2px solid var(--rhine-green); }
41
- .rhine-media-card__open { display:block; width:100%; min-width:0; padding:0; border:0; background:none; color:inherit; font:inherit; text-align:left; cursor:pointer; }
42
- .rhine-media-card__open:disabled { cursor:default; opacity:.6; }
43
- .rhine-media-card__preview { position:relative; display:flex; align-items:center; justify-content:center; width:100%; overflow:hidden; background:var(--rhine-media-canvas); color:var(--rhine-media-text); border-radius:var(--rhine-radius-card) var(--rhine-radius-card) 0 0; }
44
- .rhine-media-card__preview :is(img,video) { width:100%; height:100%; object-fit:contain; }
45
- .rhine-media-card__kind { position:absolute; top:8px; left:8px; padding:4px 8px; background:var(--rhine-media-overlay); color:var(--rhine-media-text); border:1px solid var(--rhine-media-border); font-size:12px; }
46
- .rhine-media-card__caption { display:grid; gap:4px; padding:16px; overflow-wrap:anywhere; }
47
- .rhine-media-card__caption>span { font-size:12px; color:var(--rhine-muted); }
48
- .rhine-media-card>.rhine-check { padding:0 16px 12px; overflow-wrap:anywhere; }
49
- .rhine-media-card>.rhine-check label { min-height:44px; }
50
- .rhine-media-viewer { position:fixed; inset:0; z-index:41; width:100%; height:100dvh; display:flex; flex-direction:column; background:var(--rhine-media-canvas); color:var(--rhine-media-text); color-scheme:dark; overflow:auto; }
51
- .rhine-media-viewer__header { flex:none; display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:16px; padding:16px; background:var(--rhine-media-overlay); border-bottom:1px solid var(--rhine-media-border); }
52
- .rhine-media-viewer__header>div { min-width:0; }
53
- .rhine-media-viewer__header h2 { font-size:18px; line-height:26px; overflow-wrap:anywhere; margin:0; }
54
- .rhine-media-viewer__header p { color:var(--rhine-media-muted); font-size:12px; margin:4px 0 0; }
55
- .rhine-media-viewer__actions { display:flex; flex-wrap:wrap; gap:8px; }
56
- .rhine-media-viewer :is(button,select,a) { min-height:44px; min-width:44px; max-width:100%; padding:8px 12px; border:1px solid var(--rhine-media-border); border-radius:4px; background:var(--rhine-media-overlay); color:var(--rhine-media-text); font:inherit; overflow-wrap:anywhere; }
57
- .rhine-media-viewer button { cursor:pointer; }
58
- .rhine-media-viewer button:disabled { color:var(--rhine-media-muted); opacity:.5; cursor:default; }
59
- .rhine-theme .rhine-media-viewer.rhine-media-viewer :is(button,input,select,textarea,summary,a,[tabindex]):focus-visible { outline:3px solid var(--rhine-media-focus); outline-offset:-3px; }
60
- .rhine-media-viewer__body { display:grid; grid-template-columns:var(--rhine-media-columns); flex:1; min-height:0; min-width:0; }
61
- .rhine-media-viewer__canvas { display:flex; align-items:center; justify-content:center; min-height:0; min-width:0; overflow:auto; padding:16px; }
62
- .rhine-media-viewer__canvas :is(img,video) { display:block; max-width:100%; max-height:100%; object-fit:contain; }
63
- .rhine-media-viewer__metadata { min-width:0; overflow:auto; padding:24px; border-left:1px solid var(--rhine-media-border); background:var(--rhine-media-overlay); overflow-wrap:anywhere; }
64
- @media(max-width:760px) {
65
- .rhine-media-viewer__body { display:flex; flex-direction:column; overflow:auto; }
66
- .rhine-media-viewer__canvas { flex:1 0 220px; }
67
- .rhine-media-viewer__canvas :is(img,video) { max-height:50dvh; }
68
- .rhine-media-viewer__metadata { flex:none; overflow:visible; border-left:0; border-top:1px solid var(--rhine-media-border); }
69
- .rhine-shell__content { padding:16px; }
70
- }
@@ -1,16 +1,20 @@
1
1
  import './styles.css';
2
+ export { NeutronStarBackdrop } from './NeutronStarBackdrop';
3
+ export type { NeutronStarBackdropProps } from './NeutronStarBackdrop';
2
4
  export { OrbitBackdrop } from './OrbitBackdrop';
3
5
  export type { OrbitBackdropProps } from './OrbitBackdrop';
4
6
  export { Background } from './Background';
5
7
  export type { BackgroundProps, BackgroundRole, BackgroundDecoration, BackgroundAppearance } from './Background';
6
- export { AppShell } from './AppShell';
7
- export type { AppShellProps, ShellPanel } from './AppShell';
8
+ export { AppShell, AppShellToggle } from './AppShell';
9
+ export type { AppShellProps, AppShellToggleProps, ShellPanel } from './AppShell';
8
10
  export { MediaCard, MediaViewer } from './Media';
9
11
  export type { MediaCardProps, MediaViewerProps } from './Media';
10
12
  export { DateField, DateRangePicker, NumberField, RemoteMultiSelect, TreeSelect } from './AdvancedForms';
11
13
  export type { DateFieldProps, DateRange, DateRangePickerProps, NumberFieldProps, RemoteMultiSelectProps, TreeNode, TreeSelectProps } from './AdvancedForms';
12
14
  export { StatusTimeline, TimelineLegend } from './StatusTimeline';
13
- export type { TimelineSegment, TimelineStatus, TimelineDetail, StatusTimelineProps } from './StatusTimeline';
15
+ export type { TimelineSegment, TimelineStatus, TimelineDetail, StatusTimelineProps, TimelineLegendItem, TimelineLegendProps } from './StatusTimeline';
16
+ export { StatusTimelineList } from './StatusTimelineList';
17
+ export type { StatusTimelineItem, StatusTimelineListProps } from './StatusTimelineList';
14
18
  export { TrendChart, StackedBar } from './Charts';
15
19
  export type { ChartPoint, ChartPart, TrendChartProps, StackedBarProps } from './Charts';
16
20
 
@@ -22,8 +26,8 @@ export { Select } from './Select';
22
26
  export type { SelectProps } from './Select';
23
27
  export { Toolbar } from './Toolbar';
24
28
  export type { ToolbarProps } from './Toolbar';
25
- export { Icon, IconButton, Link, CopyButton } from './Actions';
26
- export type { IconName } from './Actions';
29
+ export { Icon, IconButton, Link, ButtonLink, CopyButton } from './Actions';
30
+ export type { IconName, ButtonLinkProps } from './Actions';
27
31
  export { Divider, Stack, Inline, Grid } from './Layout';
28
32
  export type { Spacing } from './Layout';
29
33
  export { Metric, KeyValue, DataTable, Pagination } from './Data';
@@ -40,3 +44,5 @@ export type { FieldsetProps, FieldError, ErrorSummaryProps } from './FormWorkflo
40
44
 
41
45
  export { Button, Badge, Surface, SelectionCard, TextField, Tabs, SegmentedControl, Notice, Progress, Skeleton, Disclosure, EmptyState } from './components';
42
46
  export type { ButtonProps, Tone, Choice, TabItem } from './components';
47
+
48
+ export { ThemePicker, ThemePreview, type ThemePickerProps, type ThemePickerOption, type ThemePreviewProps } from './ThemePicker';
@@ -1,3 +1,56 @@
1
- .rhine-media-card__actions { display:flex; flex-wrap:wrap; gap:8px; padding:0 16px 12px; }
2
- .rhine-media-card__asset { position:absolute; inset:0; }
1
+ /* Media pixels stay neutral; the surrounding controls belong to the host theme. */
2
+ .rhine-media-card { --media-card-border:var(--rhine-line); --media-card-shadow:0 0 transparent; min-width:0; display:flex; flex-direction:column; border:1px solid var(--media-card-border); border-radius:var(--rhine-radius-card); background:var(--rhine-surface); color:var(--rhine-ink); box-shadow:var(--media-card-shadow); }
3
+ .rhine-media-card[data-selected=true] { --media-card-border:var(--rhine-green); box-shadow:0 0 0 2px var(--rhine-green),var(--media-card-shadow, 0 0 transparent); background:var(--rhine-selected); }
4
+ .rhine-media-card__open { display:flex; flex-direction:column; flex:1; width:100%; min-width:0; padding:0; border:0; border-radius:inherit; background:none; color:inherit; font:inherit; text-align:left; cursor:pointer; }
5
+ .rhine-media-card__open:hover:not(:disabled) .rhine-media-card__caption { background:var(--rhine-selected); }
6
+ .rhine-media-card__open:disabled { cursor:default; opacity:.6; }
7
+ .rhine-theme .rhine-media-card__open:focus-visible { outline:3px solid var(--rhine-green); outline-offset:-5px; }
8
+ .rhine-media-card__preview { position:relative; display:flex; align-items:center; justify-content:center; width:100%; overflow:hidden; background:var(--rhine-selected); color:var(--rhine-muted); border-radius:calc(var(--rhine-radius-card) - 2px) calc(var(--rhine-radius-card) - 2px) 0 0; border-bottom:1px solid var(--media-card-border); }
9
+ .rhine-media-card__asset { position:absolute; inset:0; background:var(--rhine-selected); }
3
10
  .rhine-media-card__asset:not([hidden]) { display:flex; align-items:center; justify-content:center; }
11
+ .rhine-media-card__asset :is(img,video) { display:block; width:100%; height:100%; object-fit:contain; }
12
+ .rhine-media-card__kind { position:absolute; top:12px; left:12px; padding:4px 8px; background:var(--rhine-surface); color:var(--rhine-ink); border:1px solid var(--rhine-control); border-radius:var(--rhine-radius-control); font:600 var(--rhine-text-caption)/var(--rhine-leading-caption) var(--rhine-mono); }
13
+ .rhine-media-card__caption { display:grid; gap:8px; width:100%; padding:16px; overflow-wrap:anywhere; }
14
+ .rhine-media-card__caption strong { font-size:var(--rhine-text-heading); line-height:var(--rhine-leading-heading); font-weight:var(--rhine-weight-heading); }
15
+ .rhine-media-card__caption>span { font-size:var(--rhine-text-caption); line-height:var(--rhine-leading-caption); color:var(--rhine-muted); }
16
+ .rhine-media-card__footer { display:flex; align-items:center; flex-wrap:wrap; gap:12px; border-top:1px solid var(--media-card-border); padding:8px 16px; }
17
+ .rhine-media-card__footer .rhine-check { min-width:0; overflow-wrap:anywhere; }
18
+ .rhine-media-card__footer .rhine-check label { min-height:44px; }
19
+ .rhine-media-card__actions { display:flex; flex-wrap:wrap; gap:8px; }
20
+ .rhine-media-card__status { display:grid; justify-items:center; gap:12px; padding:40px 16px; font-size:var(--rhine-text-body); }
21
+ .rhine-media-card__status-mark { display:grid; place-items:center; width:44px; height:44px; border:1px solid var(--rhine-control); border-radius:var(--rhine-radius-control); font:24px var(--rhine-mono); }
22
+ .rhine-media-card[data-state=error] .rhine-media-card__status { color:var(--rhine-error); }
23
+ .rhine-theme[data-rhine-theme=neo-brutalism] .rhine-media-card { --media-card-border:var(--rhine-ink); --media-card-shadow:var(--rhine-hard-shadow); border-width:2px; }
24
+ .rhine-theme[data-rhine-theme=neo-brutalism] .rhine-media-card[data-selected=true] { --media-card-shadow:5px 5px 0 var(--rhine-green); }
25
+ .rhine-theme[data-rhine-theme=neo-brutalism] .rhine-media-card__kind { border:2px solid var(--rhine-ink); box-shadow:2px 2px 0 var(--rhine-ink); }
26
+ .rhine-theme[data-rhine-theme=arknights] .rhine-media-card__kind { border-left:3px solid var(--rhine-green); letter-spacing:.06em; }
27
+ .rhine-theme[data-rhine-theme=arknights] .rhine-media-card__caption { border-inline-start:3px solid var(--rhine-control); }
28
+ .rhine-media-viewer { position:fixed; inset:0; z-index:41; width:100%; height:100%; display:flex; flex-direction:column; background:var(--rhine-surface); color:var(--rhine-ink); overflow:auto; }
29
+ .rhine-media-viewer__header { position:sticky; top:0; z-index:1; flex:none; display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:16px; padding:16px 24px; background:var(--rhine-surface); border-bottom:1px solid var(--rhine-control); }
30
+ .rhine-media-viewer__header>div { min-width:0; }
31
+ .rhine-media-viewer__header h2 { font-size:var(--rhine-text-section); line-height:var(--rhine-leading-section); overflow-wrap:anywhere; margin:0; }
32
+ .rhine-media-viewer__header p { color:var(--rhine-muted); font-size:var(--rhine-text-caption); margin:4px 0 0; }
33
+ .rhine-media-viewer__actions { display:flex; align-items:center; flex-wrap:wrap; gap:8px; }
34
+ .rhine-media-viewer__actions label { display:flex; flex-wrap:wrap; align-items:center; gap:8px; font-size:var(--rhine-text-caption); }
35
+ .rhine-media-viewer :is(button,select,a):not(.rhine-button) { min-height:44px; min-width:44px; max-width:100%; padding:8px 12px; border:1px solid var(--rhine-control); border-radius:var(--rhine-radius-control); background:var(--rhine-surface); color:var(--rhine-ink); font:inherit; overflow-wrap:anywhere; }
36
+ .rhine-media-viewer button { cursor:pointer; }
37
+ .rhine-media-viewer button:disabled { cursor:default; }
38
+ .rhine-media-viewer__body { display:grid; grid-template-columns:var(--rhine-media-columns); flex:1; min-height:0; min-width:0; }
39
+ .rhine-media-viewer__canvas { display:flex; align-items:center; justify-content:center; min-height:0; min-width:0; overflow:auto; padding:24px; background:var(--rhine-media-canvas); color:var(--rhine-media-text); color-scheme:dark; }
40
+ .rhine-media-viewer__canvas :is(img,video) { display:block; max-width:100%; max-height:100%; object-fit:contain; }
41
+ .rhine-theme .rhine-media-viewer__canvas :focus-visible { outline:3px solid var(--rhine-media-focus); outline-offset:-3px; }
42
+ .rhine-media-viewer__metadata { min-width:0; overflow:auto; padding:24px; border-left:1px solid var(--rhine-control); background:var(--rhine-surface); overflow-wrap:anywhere; }
43
+ .rhine-media-viewer__metadata h3 { margin:0 0 16px; }
44
+ .rhine-theme[data-rhine-theme=neo-brutalism] .rhine-media-viewer__header { border-bottom:2px solid var(--rhine-ink); }
45
+ .rhine-theme[data-rhine-theme=arknights] .rhine-media-viewer__header { border-bottom-color:var(--rhine-green); }
46
+ @media(max-width:760px) {
47
+ .rhine-media-viewer__header { padding:12px 16px; }
48
+ .rhine-media-viewer__body { display:flex; flex-direction:column; overflow:auto; }
49
+ .rhine-media-viewer__canvas { flex:1 0 220px; padding:16px; }
50
+ .rhine-media-viewer__canvas :is(img,video) { max-height:50dvh; }
51
+ .rhine-media-viewer__metadata { flex:none; overflow:visible; border-left:0; border-top:1px solid var(--rhine-control); }
52
+ }
53
+
54
+ .rhine-theme[data-rhine-theme=neo-brutalism] .rhine-media-viewer :is(button,select,a):not(.rhine-button) { border:2px solid var(--rhine-ink); box-shadow:2px 2px 0 var(--rhine-ink); }
55
+ .rhine-media-card__open { overflow:hidden; }
56
+ .rhine-media-card:has(.rhine-media-card__footer) .rhine-media-card__open { border-bottom-left-radius:0; border-bottom-right-radius:0; }
@@ -0,0 +1,53 @@
1
+ .rhine-neutron {
2
+ position:relative; isolation:isolate; display:flex; flex-direction:column;
3
+ min-width:0; overflow:hidden; background:var(--rhine-content-bg); color:var(--rhine-content-text);
4
+ }
5
+ .rhine-neutron-art {
6
+ position:absolute; inset:0; max-height:740px; overflow:hidden; pointer-events:none;
7
+ mask-image:linear-gradient(to bottom, transparent, #000 8%, #000 72%, transparent);
8
+ -webkit-mask-image:linear-gradient(to bottom, transparent, #000 8%, #000 72%, transparent);
9
+ background:radial-gradient(ellipse at 78% 15%, color-mix(in srgb, var(--rhine-green) 14%, transparent), transparent 60%);
10
+ }
11
+ @media (max-width:600px) { .rhine-neutron-art { max-height:620px; } }
12
+ .rhine-neutron[data-rhine-neutron-appearance="original"] { background:#070c18; }
13
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-art {
14
+ background:radial-gradient(ellipse at 78% 15%, #13223e, transparent 52%);
15
+ }
16
+ .rhine-neutron-canvas { position:absolute; inset:0; display:block; width:100%; height:100%; pointer-events:none; }
17
+ .rhine-neutron-fallback {
18
+ position:absolute; inset:0; display:block;
19
+ background:radial-gradient(ellipse at 64% 38%, var(--rhine-surface) 0 3%, color-mix(in srgb, var(--rhine-green) 55%, transparent) 4%, transparent 24%);
20
+ }
21
+ .rhine-neutron-fallback i, .rhine-neutron-fallback b {
22
+ position:absolute; inset:17% 15% 27% 35%; border:1px solid var(--rhine-green); border-radius:50%; transform:rotate(-28deg); opacity:.65;
23
+ }
24
+ .rhine-neutron-fallback b { transform:rotate(48deg); }
25
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-fallback {
26
+ background:radial-gradient(ellipse at 64% 38%, #f0fcff 0 3%, #88c9fc 4%, #86baff55 8%, transparent 24%);
27
+ }
28
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-fallback :is(i,b) { border-color:#8fc4ee; }
29
+ .rhine-neutron-art[data-rhine-neutron-rendered="true"] .rhine-neutron-fallback { display:none; }
30
+ .rhine-neutron-art:not([data-rhine-neutron-rendered="true"]) .rhine-neutron-canvas { visibility:hidden; }
31
+ .rhine-neutron-content {
32
+ position:relative; z-index:1; flex:1; min-width:0;
33
+ padding-bottom:calc(44px + var(--rhine-space-4) * 2);
34
+ }
35
+ /* Only the artwork is screened; text and controls never pass through a blur filter. */
36
+ .rhine-neutron-content:not(:empty)::before {
37
+ content:''; position:absolute; inset:0; z-index:-1; pointer-events:none;
38
+ background:linear-gradient(90deg, color-mix(in srgb, var(--rhine-content-bg) 92%, transparent), color-mix(in srgb, var(--rhine-content-bg) 54%, transparent));
39
+ }
40
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-content { color:#f2f7ff; }
41
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-content:not(:empty)::before {
42
+ background:linear-gradient(90deg, #070c18e6, #070c1870);
43
+ }
44
+ /* Painted controls and surfaces keep their host tokens, including hover and disabled states. */
45
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-content :is(.rhine-text--muted,.rhine-field__hint) { color:inherit; opacity:.8; }
46
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-content .rhine-logo:not(.rhine-logo--icon),
47
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-content .rhine-button--quiet:not(:disabled):not(:hover),
48
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-content .rhine-button--quiet[aria-disabled=true]:not(:disabled) { color:inherit; }
49
+ .rhine-neutron[data-rhine-neutron-appearance="original"] .rhine-neutron-content .rhine-button--quiet:focus-visible { outline:none; box-shadow:inset 0 0 0 2px currentColor; }
50
+ .rhine-neutron-controls { position:absolute; right:var(--rhine-space-4); bottom:var(--rhine-space-4); z-index:2; max-width:calc(100% - var(--rhine-space-4) * 2); }
51
+ .rhine-neutron-controls .rhine-button { max-width:100%; }
52
+ /* Keep the focus ring on the painted control, where its text color retains contrast. */
53
+ .rhine-theme .rhine-neutron .rhine-neutron-controls .rhine-button:focus-visible { outline:2px solid currentColor; outline-offset:-5px; }