@dfosco/storyboard 0.8.1 → 0.9.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/dist/storyboard-ui.css +1 -1
- package/dist/storyboard-ui.js +6420 -6336
- package/dist/storyboard-ui.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/dist/tiny-canvas.css +1 -1
- package/package.json +1 -1
- package/scaffold/src/library/_app.jsx +2 -14
- package/scaffold/src/library/_app.module.css +2 -8
- package/scaffold/src/library/mount.jsx +0 -1
- package/src/canvas/style.css +16 -16
- package/src/core/artifact/operations.js +35 -2
- package/src/core/artifact/schemas/canvas.schema.json +7 -1
- package/src/core/canvas/hot-pool.js +11 -22
- package/src/core/canvas/selectedWidgets.js +1 -1
- package/src/core/canvas/server.js +52 -31
- package/src/core/canvas/server.test.js +107 -0
- package/src/core/cli/artifact.js +2 -0
- package/src/core/cli/create.js +35 -5
- package/src/core/cli/schemas.js +6 -1
- package/src/core/comments/ui/comment-layout.css +14 -14
- package/src/core/index.js +18 -0
- package/src/core/inspector/highlighter.js +1 -1
- package/src/core/inspector/mouseMode.js +2 -2
- package/src/core/lib/components/ui/dialog/dialog.module.css +8 -8
- package/src/core/modes/modes.css +4 -4
- package/src/core/mountStoryboardCore.js +53 -9
- package/src/core/mountStoryboardCore.test.js +25 -1
- package/src/core/rename-watcher/config.json +1 -1
- package/src/core/rename-watcher/watcher.js +1 -1
- package/src/core/stores/canvasInteractionStore.js +120 -0
- package/src/core/stores/canvasInteractionStore.test.js +126 -0
- package/src/core/stores/configSchema.js +23 -6
- package/src/core/stores/configSchema.test.js +3 -0
- package/src/core/stores/customerModeConfig.js +24 -3
- package/src/core/stores/customerModeConfig.test.js +46 -0
- package/src/core/stores/presentationStore.js +118 -0
- package/src/core/stores/presentationStore.test.js +114 -0
- package/src/core/stores/uiConfig.js +10 -2
- package/src/core/styles/tailwind.css +138 -90
- package/src/core/styles/workspace-chrome.css +4 -21
- package/src/core/ui/AutosyncMenuButton.css +7 -7
- package/src/core/ui/BranchSelect.module.css +5 -5
- package/src/core/ui/ChromeSlot.jsx +92 -0
- package/src/core/ui/ChromeSlot.test.jsx +140 -0
- package/src/core/ui/CoreUIBar.css +5 -5
- package/src/core/ui/CoreUIBar.jsx +161 -136
- package/src/core/ui/InspectorPanel.css +5 -5
- package/src/core/ui/InspectorPanel.jsx +9 -9
- package/src/core/ui/PwaInstallBanner.css +5 -5
- package/src/core/ui/PwaInstallBanner.jsx +5 -5
- package/src/core/ui/core-ui-colors.css +28 -66
- package/src/core/ui/sidepanel.css +12 -12
- package/src/core/workshop/features/createCanvas/CreateCanvasForm.jsx +102 -13
- package/src/internals/ArtifactForm/ArtifactForm.module.css +7 -7
- package/src/internals/AuthModal/AuthModal.module.css +34 -34
- package/src/internals/BaseUiForm/BaseUiForm.module.css +85 -85
- package/src/internals/BranchBar/BranchBar.module.css +4 -4
- package/src/internals/BranchesDropdown/BranchesDropdown.module.css +9 -9
- package/src/internals/CommandPalette/CommandPalette.jsx +16 -10
- package/src/internals/CommandPalette/WidgetArtifactDialog.css +16 -16
- package/src/internals/CommandPalette/command-palette.css +14 -14
- package/src/internals/CreatePage/CreatePage.module.css +1 -1
- package/src/internals/FlowError.module.css +5 -5
- package/src/internals/PrototypeErrorBoundary.module.css +15 -15
- package/src/internals/SimpleWorkspace/SimpleWorkspace.jsx +5 -4
- package/src/internals/SimpleWorkspace/SimpleWorkspace.module.css +38 -38
- package/src/internals/Viewfinder.jsx +33 -16
- package/src/internals/Viewfinder.module.css +189 -189
- package/src/internals/canvas/CanvasControls.module.css +11 -11
- package/src/internals/canvas/CanvasPage.bridge.test.jsx +11 -37
- package/src/internals/canvas/CanvasPage.jsx +91 -93
- package/src/internals/canvas/CanvasPage.module.css +20 -19
- package/src/internals/canvas/CanvasToolbar.module.css +11 -11
- package/src/internals/canvas/ConnectorLayer.jsx +39 -2
- package/src/internals/canvas/ConnectorLayer.module.css +10 -10
- package/src/internals/canvas/PageSelector.module.css +28 -28
- package/src/internals/canvas/canvasTheme.js +22 -111
- package/src/internals/canvas/isolation/prototypeRoutes.jsx +12 -3
- package/src/internals/canvas/isolation/storyRoutes.jsx +1 -1
- package/src/internals/canvas/widgets/CodePenEmbed.jsx +16 -36
- package/src/internals/canvas/widgets/CodePenEmbed.module.css +12 -12
- package/src/internals/canvas/widgets/CropOverlay.module.css +23 -23
- package/src/internals/canvas/widgets/ExpandedPane.module.css +8 -8
- package/src/internals/canvas/widgets/FigmaEmbed.jsx +15 -36
- package/src/internals/canvas/widgets/FigmaEmbed.module.css +15 -15
- package/src/internals/canvas/widgets/FrozenTerminalOverlay.module.css +5 -5
- package/src/internals/canvas/widgets/ImageWidget.module.css +3 -3
- package/src/internals/canvas/widgets/LinkPreview.module.css +77 -78
- package/src/internals/canvas/widgets/MarkdownBlock.module.css +31 -31
- package/src/internals/canvas/widgets/PromptWidget.jsx +2 -16
- package/src/internals/canvas/widgets/PromptWidget.module.css +33 -33
- package/src/internals/canvas/widgets/PrototypeEmbed.jsx +23 -7
- package/src/internals/canvas/widgets/PrototypeEmbed.module.css +58 -56
- package/src/internals/canvas/widgets/PrototypeEmbed.test.jsx +4 -4
- package/src/internals/canvas/widgets/ResizeHandle.module.css +4 -4
- package/src/internals/canvas/widgets/StorySetWidget.jsx +45 -21
- package/src/internals/canvas/widgets/StoryWidget.jsx +53 -21
- package/src/internals/canvas/widgets/StoryWidget.module.css +22 -20
- package/src/internals/canvas/widgets/TerminalReadWidget.module.css +4 -4
- package/src/internals/canvas/widgets/TerminalWidget.jsx +56 -45
- package/src/internals/canvas/widgets/TerminalWidget.module.css +10 -10
- package/src/internals/canvas/widgets/TilesWidget.module.css +17 -17
- package/src/internals/canvas/widgets/WidgetChrome.module.css +61 -61
- package/src/internals/canvas/widgets/WidgetWrapper.module.css +2 -2
- package/src/internals/canvas/widgets/embedOverlay.module.css +14 -4
- package/src/internals/canvas/widgets/embedTheme.js +10 -102
- package/src/internals/canvas/widgets/widgetConfig.js +5 -5
- package/src/internals/story/ComponentSetPage.module.css +14 -14
- package/src/internals/story/StoryPage.module.css +2 -2
- package/src/internals/vite/data-plugin.js +5 -2
- package/src/internals/canvas/WebGLContextPool.jsx +0 -291
- package/src/internals/canvas/WebGLContextPool.test.jsx +0 -165
- package/src/internals/canvas/widgets/ComponentSetWidget.module.css +0 -89
- package/src/internals/canvas/widgets/StorySetWidget.module.css +0 -89
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation Store — consumer-supplied overrides for storyboard chrome elements.
|
|
3
|
+
*
|
|
4
|
+
* A chrome element is any rendered piece of storyboard UI that is wrapped in
|
|
5
|
+
* `<ChromeSlot id="...">` (toolbar buttons, canvas title, page selector, etc.).
|
|
6
|
+
*
|
|
7
|
+
* Consumers seed this registry through `mountStoryboardCore({ presentation })`
|
|
8
|
+
* and the store applies per-element overrides at render time:
|
|
9
|
+
*
|
|
10
|
+
* {
|
|
11
|
+
* "tool:command-palette": {
|
|
12
|
+
* style: { transform: 'translateY(20px)', opacity: 0 },
|
|
13
|
+
* className: 'landing-floating-button',
|
|
14
|
+
* props: { onPointerEnter: handleHover },
|
|
15
|
+
* decorator: (Element, ctx) => <ScrollAnimator>{Element}</ScrollAnimator>,
|
|
16
|
+
* },
|
|
17
|
+
* "canvas:title": { hidden: true },
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* This is an **advanced, undocumented** extension surface — intended for
|
|
21
|
+
* landing-page / hero canvas use cases where the consumer needs heavy
|
|
22
|
+
* customization of storyboard chrome. Not part of the public API.
|
|
23
|
+
*
|
|
24
|
+
* Framework-agnostic (zero npm dependencies).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {object} PresentationOverride
|
|
29
|
+
* @property {React.CSSProperties} [style] - Spread onto the chrome element root style
|
|
30
|
+
* @property {string} [className] - Appended to the chrome element root className
|
|
31
|
+
* @property {object} [props] - Spread as additional props on the chrome element
|
|
32
|
+
* @property {Function} [decorator] - (Element, ctx) => ReactNode wrapper
|
|
33
|
+
* @property {boolean} [hidden] - If true, render null (shorthand for full hide)
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** @type {Map<string, PresentationOverride>} */
|
|
37
|
+
let _overrides = new Map()
|
|
38
|
+
|
|
39
|
+
/** @type {Set<Function>} */
|
|
40
|
+
const _listeners = new Set()
|
|
41
|
+
|
|
42
|
+
let _snapshotVersion = 0
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Seed the presentation registry from a consumer-supplied map.
|
|
46
|
+
* Replaces any previous overrides. Called once at app startup.
|
|
47
|
+
*
|
|
48
|
+
* @param {Record<string, PresentationOverride>} [map]
|
|
49
|
+
*/
|
|
50
|
+
export function initPresentation(map) {
|
|
51
|
+
_overrides = new Map()
|
|
52
|
+
if (map && typeof map === 'object') {
|
|
53
|
+
for (const [id, override] of Object.entries(map)) {
|
|
54
|
+
if (override && typeof override === 'object') {
|
|
55
|
+
_overrides.set(id, override)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
_notify()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Set or replace a single chrome element's presentation override.
|
|
64
|
+
* @param {string} id
|
|
65
|
+
* @param {PresentationOverride|null|undefined} override Pass null/undefined to clear.
|
|
66
|
+
*/
|
|
67
|
+
export function setPresentation(id, override) {
|
|
68
|
+
if (override == null) {
|
|
69
|
+
_overrides.delete(id)
|
|
70
|
+
} else if (typeof override === 'object') {
|
|
71
|
+
_overrides.set(id, override)
|
|
72
|
+
}
|
|
73
|
+
_notify()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get the presentation override for a chrome element ID, or null if none.
|
|
78
|
+
* @param {string} id
|
|
79
|
+
* @returns {PresentationOverride|null}
|
|
80
|
+
*/
|
|
81
|
+
export function getPresentation(id) {
|
|
82
|
+
return _overrides.get(id) || null
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Subscribe to presentation registry changes. Returns an unsubscribe fn.
|
|
87
|
+
* Compatible with `useSyncExternalStore` shape.
|
|
88
|
+
* @param {Function} callback
|
|
89
|
+
* @returns {Function}
|
|
90
|
+
*/
|
|
91
|
+
export function subscribeToPresentation(callback) {
|
|
92
|
+
_listeners.add(callback)
|
|
93
|
+
return () => _listeners.delete(callback)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Snapshot version for change detection. Compatible with `useSyncExternalStore`.
|
|
98
|
+
* @returns {string}
|
|
99
|
+
*/
|
|
100
|
+
export function getPresentationSnapshot() {
|
|
101
|
+
return String(_snapshotVersion)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function _notify() {
|
|
105
|
+
_snapshotVersion++
|
|
106
|
+
for (const cb of _listeners) {
|
|
107
|
+
try { cb() } catch (err) {
|
|
108
|
+
console.error('[storyboard] Error in presentation subscriber:', err)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Reset all state. Only for tests. */
|
|
114
|
+
export function _resetPresentation() {
|
|
115
|
+
_overrides = new Map()
|
|
116
|
+
_listeners.clear()
|
|
117
|
+
_snapshotVersion = 0
|
|
118
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
initPresentation,
|
|
5
|
+
setPresentation,
|
|
6
|
+
getPresentation,
|
|
7
|
+
subscribeToPresentation,
|
|
8
|
+
getPresentationSnapshot,
|
|
9
|
+
_resetPresentation,
|
|
10
|
+
} from './presentationStore.js'
|
|
11
|
+
|
|
12
|
+
describe('presentationStore', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
_resetPresentation()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('returns null when no override is registered', () => {
|
|
18
|
+
expect(getPresentation('tool:command-palette')).toBeNull()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('seeds overrides from initPresentation', () => {
|
|
22
|
+
initPresentation({
|
|
23
|
+
'tool:command-palette': { hidden: true },
|
|
24
|
+
'canvas:title': { className: 'landing-title' },
|
|
25
|
+
})
|
|
26
|
+
expect(getPresentation('tool:command-palette')).toEqual({ hidden: true })
|
|
27
|
+
expect(getPresentation('canvas:title')).toEqual({ className: 'landing-title' })
|
|
28
|
+
expect(getPresentation('nope:nothing')).toBeNull()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('ignores non-object values in initPresentation', () => {
|
|
32
|
+
initPresentation({
|
|
33
|
+
'tool:a': null,
|
|
34
|
+
'tool:b': 'invalid',
|
|
35
|
+
'tool:c': 42,
|
|
36
|
+
'tool:d': { hidden: true },
|
|
37
|
+
})
|
|
38
|
+
expect(getPresentation('tool:a')).toBeNull()
|
|
39
|
+
expect(getPresentation('tool:b')).toBeNull()
|
|
40
|
+
expect(getPresentation('tool:c')).toBeNull()
|
|
41
|
+
expect(getPresentation('tool:d')).toEqual({ hidden: true })
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('replaces previous overrides on subsequent initPresentation calls', () => {
|
|
45
|
+
initPresentation({ 'tool:a': { hidden: true } })
|
|
46
|
+
initPresentation({ 'tool:b': { hidden: true } })
|
|
47
|
+
expect(getPresentation('tool:a')).toBeNull()
|
|
48
|
+
expect(getPresentation('tool:b')).toEqual({ hidden: true })
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('initPresentation() with no arg clears all overrides', () => {
|
|
52
|
+
initPresentation({ 'tool:a': { hidden: true } })
|
|
53
|
+
initPresentation()
|
|
54
|
+
expect(getPresentation('tool:a')).toBeNull()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('setPresentation adds and updates individual overrides', () => {
|
|
58
|
+
setPresentation('tool:a', { className: 'foo' })
|
|
59
|
+
expect(getPresentation('tool:a')).toEqual({ className: 'foo' })
|
|
60
|
+
|
|
61
|
+
setPresentation('tool:a', { className: 'bar' })
|
|
62
|
+
expect(getPresentation('tool:a')).toEqual({ className: 'bar' })
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('setPresentation with null/undefined deletes the override', () => {
|
|
66
|
+
setPresentation('tool:a', { hidden: true })
|
|
67
|
+
setPresentation('tool:a', null)
|
|
68
|
+
expect(getPresentation('tool:a')).toBeNull()
|
|
69
|
+
|
|
70
|
+
setPresentation('tool:b', { hidden: true })
|
|
71
|
+
setPresentation('tool:b', undefined)
|
|
72
|
+
expect(getPresentation('tool:b')).toBeNull()
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('subscribers are notified on init, set, and clear', () => {
|
|
76
|
+
const cb = vi.fn()
|
|
77
|
+
const unsub = subscribeToPresentation(cb)
|
|
78
|
+
|
|
79
|
+
initPresentation({ 'tool:a': { hidden: true } })
|
|
80
|
+
setPresentation('tool:b', { className: 'x' })
|
|
81
|
+
setPresentation('tool:a', null)
|
|
82
|
+
|
|
83
|
+
expect(cb).toHaveBeenCalledTimes(3)
|
|
84
|
+
unsub()
|
|
85
|
+
|
|
86
|
+
setPresentation('tool:c', { hidden: true })
|
|
87
|
+
expect(cb).toHaveBeenCalledTimes(3) // not called after unsubscribe
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('snapshot version changes on every mutation', () => {
|
|
91
|
+
const v0 = getPresentationSnapshot()
|
|
92
|
+
setPresentation('tool:a', { hidden: true })
|
|
93
|
+
const v1 = getPresentationSnapshot()
|
|
94
|
+
expect(v1).not.toBe(v0)
|
|
95
|
+
|
|
96
|
+
setPresentation('tool:b', { hidden: true })
|
|
97
|
+
const v2 = getPresentationSnapshot()
|
|
98
|
+
expect(v2).not.toBe(v1)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('subscriber errors are isolated', () => {
|
|
102
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
103
|
+
const goodCb = vi.fn()
|
|
104
|
+
|
|
105
|
+
subscribeToPresentation(() => { throw new Error('boom') })
|
|
106
|
+
subscribeToPresentation(goodCb)
|
|
107
|
+
|
|
108
|
+
setPresentation('tool:a', { hidden: true })
|
|
109
|
+
|
|
110
|
+
expect(goodCb).toHaveBeenCalled()
|
|
111
|
+
expect(consoleSpy).toHaveBeenCalled()
|
|
112
|
+
consoleSpy.mockRestore()
|
|
113
|
+
})
|
|
114
|
+
})
|
|
@@ -2,14 +2,22 @@
|
|
|
2
2
|
* UI Config — project-level overrides for storyboard chrome visibility.
|
|
3
3
|
*
|
|
4
4
|
* Client repos use the "ui" key in storyboard.config.json to hide
|
|
5
|
-
* specific menus
|
|
5
|
+
* specific menus, toolbar items, or workspace nav entries.
|
|
6
6
|
*
|
|
7
7
|
* {
|
|
8
8
|
* "ui": {
|
|
9
|
-
* "hide": [
|
|
9
|
+
* "hide": [
|
|
10
|
+
* "docs", // CoreUIBar menu key
|
|
11
|
+
* "comments", // CoreUIBar menu key
|
|
12
|
+
* "workspace:components" // workspace sidebar nav id
|
|
13
|
+
* ]
|
|
10
14
|
* }
|
|
11
15
|
* }
|
|
12
16
|
*
|
|
17
|
+
* Convention: namespaced keys (`<surface>:<id>`) are recommended for new
|
|
18
|
+
* surfaces to avoid collisions. Existing CoreUIBar menus use bare keys
|
|
19
|
+
* for back-compat.
|
|
20
|
+
*
|
|
13
21
|
* Framework-agnostic (zero npm dependencies).
|
|
14
22
|
*/
|
|
15
23
|
|
|
@@ -23,103 +23,151 @@
|
|
|
23
23
|
font-display: swap;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/*
|
|
27
|
+
* Storyboard color token Single Source of Truth.
|
|
28
|
+
*
|
|
29
|
+
* All semantic color variables live here. Two naming families coexist:
|
|
30
|
+
*
|
|
31
|
+
* 1. shadcn-style (`--color-*`) — used by Tailwind utilities
|
|
32
|
+
* (`bg-background`, `text-foreground`) and shadcn primitives.
|
|
33
|
+
* 2. Storyboard chrome (`--color-background-*`, `--color-foreground-*`,
|
|
34
|
+
* `--color-border-*`, `--color-overlay-*`, `--shadow-*`)
|
|
35
|
+
* — used by every workspace / canvas / widget CSS module.
|
|
36
|
+
*
|
|
37
|
+
* Light values live on `:root` (via `@theme`). Dark overrides live on
|
|
38
|
+
* `[data-sb-theme^="dark"]` and every per-surface dark attribute
|
|
39
|
+
* (`data-sb-canvas-theme`, `data-sb-prototype-theme`, etc.). The same
|
|
40
|
+
* selector list drives the `dark:` Tailwind variant (`themes.generated.css`).
|
|
41
|
+
*
|
|
42
|
+
* Concrete hex values are GitHub Primer palette values, kept verbatim
|
|
43
|
+
* so the visual identity is unchanged after dropping `@primer/primitives`.
|
|
44
|
+
*/
|
|
26
45
|
@theme {
|
|
27
|
-
--color-background:
|
|
28
|
-
--color-
|
|
29
|
-
--color-
|
|
30
|
-
--color-
|
|
31
|
-
--color-
|
|
32
|
-
--color-
|
|
33
|
-
--color-
|
|
34
|
-
--color-
|
|
35
|
-
--color-
|
|
36
|
-
--color-
|
|
37
|
-
--color-muted:
|
|
38
|
-
--color-
|
|
39
|
-
--color-
|
|
40
|
-
--color-
|
|
41
|
-
--color-
|
|
42
|
-
--color-
|
|
43
|
-
--color-
|
|
44
|
-
--color-
|
|
45
|
-
--color-
|
|
46
|
-
--color-
|
|
47
|
-
|
|
46
|
+
--color-background: #ffffff;
|
|
47
|
+
--color-background-muted: #f6f8fa;
|
|
48
|
+
--color-background-inset: #f6f8fa;
|
|
49
|
+
--color-background-emphasis: #25292e;
|
|
50
|
+
--color-background-inverse: #25292e;
|
|
51
|
+
--color-background-neutral-muted: #818b981f;
|
|
52
|
+
--color-background-neutral-emphasis: #59636e;
|
|
53
|
+
--color-background-accent-muted: #ddf4ff;
|
|
54
|
+
--color-background-accent-emphasis: #0969da;
|
|
55
|
+
--color-background-accent-emphasis-hover: #0860c7;
|
|
56
|
+
--color-background-danger-muted: #ffebe9;
|
|
57
|
+
--color-background-danger-emphasis: #cf222e;
|
|
58
|
+
--color-background-success-muted: #dafbe1;
|
|
59
|
+
--color-background-success-emphasis: #1f883d;
|
|
60
|
+
--color-background-success-hover: #1a7f37;
|
|
61
|
+
--color-background-attention-muted: #fff8c5;
|
|
62
|
+
--color-background-done-muted: #fbefff;
|
|
63
|
+
--color-background-done-emphasis: #8250df;
|
|
64
|
+
--color-background-open-emphasis: #1f883d;
|
|
65
|
+
--color-background-closed-emphasis: #cf222e;
|
|
66
|
+
|
|
67
|
+
--color-foreground: #1f2328;
|
|
68
|
+
--color-foreground-muted: #59636e;
|
|
69
|
+
--color-foreground-accent: #0969da;
|
|
70
|
+
--color-foreground-danger: #d1242f;
|
|
71
|
+
--color-foreground-success: #1a7f37;
|
|
72
|
+
--color-foreground-attention: #9a6700;
|
|
73
|
+
--color-foreground-on-emphasis: #ffffff;
|
|
74
|
+
--color-foreground-on-inverse: #ffffff;
|
|
75
|
+
|
|
76
|
+
--color-border: #d1d9e0;
|
|
77
|
+
--color-border-muted: #d1d9e0b3;
|
|
78
|
+
--color-border-emphasis: #818b98;
|
|
79
|
+
--color-border-accent-emphasis: #0969da;
|
|
80
|
+
--color-border-accent-muted: #54aeff66;
|
|
81
|
+
--color-border-danger-emphasis: #cf222e;
|
|
82
|
+
--color-border-danger-muted: #ff818266;
|
|
83
|
+
--color-border-success-muted: #4ac26b66;
|
|
84
|
+
--color-border-attention-muted: #d4a72c66;
|
|
85
|
+
|
|
86
|
+
--color-overlay-backdrop: #c8d1da66;
|
|
87
|
+
|
|
88
|
+
--shadow-resting: 0px 1px 1px 0px #1f23280f, 0px 1px 3px 0px #1f23280f;
|
|
89
|
+
--shadow-floating: 0px 0px 0px 1px #d1d9e080, 0px 6px 12px -3px #25292e0a, 0px 6px 18px 0px #25292e1f;
|
|
90
|
+
|
|
91
|
+
/* shadcn primitives (Tailwind utility-friendly aliases) */
|
|
92
|
+
--color-card: var(--color-background);
|
|
93
|
+
--color-card-foreground: var(--color-foreground);
|
|
94
|
+
--color-popover: var(--color-background);
|
|
95
|
+
--color-popover-foreground: var(--color-foreground);
|
|
96
|
+
--color-primary: #1f2328;
|
|
97
|
+
--color-primary-foreground: #ffffff;
|
|
98
|
+
--color-secondary: var(--color-background-muted);
|
|
99
|
+
--color-secondary-foreground: var(--color-foreground);
|
|
100
|
+
--color-muted: var(--color-background-muted);
|
|
101
|
+
--color-muted-foreground: var(--color-foreground-muted);
|
|
102
|
+
--color-accent: var(--color-background-accent-muted);
|
|
103
|
+
--color-accent-foreground: var(--color-foreground-accent);
|
|
104
|
+
--color-destructive: var(--color-background-danger-emphasis);
|
|
105
|
+
--color-destructive-foreground: #ffffff;
|
|
106
|
+
--color-input: var(--color-border);
|
|
107
|
+
--color-ring: var(--color-background-accent-emphasis);
|
|
108
|
+
--color-success: var(--color-background-success-emphasis);
|
|
109
|
+
--color-success-foreground: #ffffff;
|
|
110
|
+
|
|
48
111
|
--radius: 0.5rem;
|
|
49
112
|
--font-sans: "Hubot Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
|
50
113
|
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
51
|
-
|
|
52
|
-
--sb--color-background: hsl(0 0% 100%);
|
|
53
|
-
--sb--color-foreground: hsl(222.2 84% 4.9%);
|
|
54
|
-
--sb--color-card: hsl(0 0% 100%);
|
|
55
|
-
--sb--color-card-foreground: hsl(222.2 84% 4.9%);
|
|
56
|
-
--sb--color-popover: hsl(0 0% 100%);
|
|
57
|
-
--sb--color-popover-foreground: hsl(222.2 84% 4.9%);
|
|
58
|
-
--sb--color-primary: hsl(222.2 47.4% 11.2%);
|
|
59
|
-
--sb--color-primary-foreground: hsl(210 40% 98%);
|
|
60
|
-
--sb--color-secondary: hsl(210 40% 96.1%);
|
|
61
|
-
--sb--color-secondary-foreground: hsl(222.2 47.4% 11.2%);
|
|
62
|
-
--sb--color-muted: hsl(210 40% 96.1%);
|
|
63
|
-
--sb--color-muted-foreground: hsl(215.4 16.3% 46.9%);
|
|
64
|
-
--sb--color-accent: hsl(210 40% 96.1%);
|
|
65
|
-
--sb--color-accent-foreground: hsl(222.2 47.4% 11.2%);
|
|
66
|
-
--sb--color-destructive: hsl(0 84.2% 60.2%);
|
|
67
|
-
--sb--color-destructive-foreground: hsl(210 40% 98%);
|
|
68
|
-
--sb--color-border: hsl(214.3 31.8% 91.4%);
|
|
69
|
-
--sb--color-input: hsl(214.3 31.8% 91.4%);
|
|
70
|
-
--sb--color-ring: hsl(222.2 84% 4.9%);
|
|
71
|
-
--sb--color-success: hsl(142 71% 36%);
|
|
72
|
-
--sb--color-success-foreground: hsl(0 0% 100%);
|
|
73
|
-
--sb--radius: var(--radius);
|
|
74
|
-
--sb--font-sans: var(--font-sans);
|
|
75
|
-
--sb--font-mono: var(--font-mono);
|
|
76
114
|
}
|
|
77
115
|
|
|
78
116
|
@layer base {
|
|
79
|
-
[data-sb-theme^="dark"]
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
--color-
|
|
86
|
-
--color-
|
|
87
|
-
--color-
|
|
88
|
-
--color-
|
|
89
|
-
--color-
|
|
90
|
-
--color-muted:
|
|
91
|
-
--color-
|
|
92
|
-
--color-accent:
|
|
93
|
-
--color-accent-
|
|
94
|
-
--color-
|
|
95
|
-
--color-
|
|
96
|
-
--color-
|
|
97
|
-
--color-
|
|
98
|
-
--color-
|
|
99
|
-
--color-success:
|
|
100
|
-
--color-
|
|
101
|
-
|
|
102
|
-
--
|
|
103
|
-
--
|
|
104
|
-
--
|
|
105
|
-
|
|
106
|
-
--
|
|
107
|
-
--
|
|
108
|
-
--
|
|
109
|
-
--
|
|
110
|
-
--
|
|
111
|
-
--
|
|
112
|
-
--
|
|
113
|
-
--
|
|
114
|
-
|
|
115
|
-
--
|
|
116
|
-
--
|
|
117
|
-
--
|
|
118
|
-
--
|
|
119
|
-
--
|
|
120
|
-
--
|
|
121
|
-
--
|
|
122
|
-
--
|
|
117
|
+
[data-sb-theme^="dark"],
|
|
118
|
+
[data-sb-canvas-theme^="dark"],
|
|
119
|
+
[data-sb-prototype-theme^="dark"],
|
|
120
|
+
[data-sb-toolbar-theme^="dark"],
|
|
121
|
+
[data-sb-codeboxes-theme^="dark"],
|
|
122
|
+
[data-sb-code-theme^="dark"] {
|
|
123
|
+
--color-background: #0d1117;
|
|
124
|
+
--color-background-muted: #151b23;
|
|
125
|
+
--color-background-inset: #010409;
|
|
126
|
+
--color-background-emphasis: #3d444d;
|
|
127
|
+
--color-background-inverse: #ffffff;
|
|
128
|
+
--color-background-neutral-muted: #656c7633;
|
|
129
|
+
--color-background-neutral-emphasis: #656c76;
|
|
130
|
+
--color-background-accent-muted: #388bfd1a;
|
|
131
|
+
--color-background-accent-emphasis: #1f6feb;
|
|
132
|
+
--color-background-accent-emphasis-hover: #388bfd;
|
|
133
|
+
--color-background-danger-muted: #f851491a;
|
|
134
|
+
--color-background-danger-emphasis: #da3633;
|
|
135
|
+
--color-background-success-muted: #2ea04326;
|
|
136
|
+
--color-background-success-emphasis: #238636;
|
|
137
|
+
--color-background-success-hover: #2ea043;
|
|
138
|
+
--color-background-attention-muted: #bb800926;
|
|
139
|
+
--color-background-done-muted: #ab7df81a;
|
|
140
|
+
--color-background-done-emphasis: #8957e5;
|
|
141
|
+
--color-background-open-emphasis: #238636;
|
|
142
|
+
--color-background-closed-emphasis: #da3633;
|
|
143
|
+
|
|
144
|
+
--color-foreground: #f0f6fc;
|
|
145
|
+
--color-foreground-muted: #9198a1;
|
|
146
|
+
--color-foreground-accent: #4493f8;
|
|
147
|
+
--color-foreground-danger: #f85149;
|
|
148
|
+
--color-foreground-success: #3fb950;
|
|
149
|
+
--color-foreground-attention: #d29922;
|
|
150
|
+
--color-foreground-on-emphasis: #ffffff;
|
|
151
|
+
--color-foreground-on-inverse: #010409;
|
|
152
|
+
|
|
153
|
+
--color-border: #3d444d;
|
|
154
|
+
--color-border-muted: #3d444db3;
|
|
155
|
+
--color-border-emphasis: #656c76;
|
|
156
|
+
--color-border-accent-emphasis: #1f6feb;
|
|
157
|
+
--color-border-accent-muted: #388bfd66;
|
|
158
|
+
--color-border-danger-emphasis: #da3633;
|
|
159
|
+
--color-border-danger-muted: #f8514966;
|
|
160
|
+
--color-border-success-muted: #2ea04366;
|
|
161
|
+
--color-border-attention-muted: #bb800966;
|
|
162
|
+
|
|
163
|
+
--color-overlay-backdrop: #21283066;
|
|
164
|
+
|
|
165
|
+
--shadow-resting: 0px 1px 1px 0px #01040999, 0px 1px 3px 0px #01040999;
|
|
166
|
+
--shadow-floating: 0px 0px 0px 1px #3d444d, 0px 6px 12px -3px #01040966, 0px 6px 18px 0px #01040966;
|
|
167
|
+
|
|
168
|
+
--color-primary: #f0f6fc;
|
|
169
|
+
--color-primary-foreground: #0d1117;
|
|
170
|
+
--color-ring: var(--color-background-accent-emphasis);
|
|
123
171
|
}
|
|
124
172
|
}
|
|
125
173
|
@custom-variant data-open {
|
|
@@ -6,25 +6,8 @@
|
|
|
6
6
|
* Prototypes and stories do NOT load this stylesheet — their CSS chain
|
|
7
7
|
* is owned by the consumer's `src/_prototype.jsx` / `src/_story.jsx`.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* All color/spacing/typography tokens previously sourced from
|
|
10
|
+
* `@primer/primitives` now live in `core/styles/tailwind.css` (the
|
|
11
|
+
* single source of truth). This file is intentionally empty but kept
|
|
12
|
+
* for backward compatibility with consumers that import it directly.
|
|
13
13
|
*/
|
|
14
|
-
@import '@primer/primitives/dist/css/base/size/size.css';
|
|
15
|
-
@import '@primer/primitives/dist/css/base/typography/typography.css';
|
|
16
|
-
@import '@primer/primitives/dist/css/base/motion/motion.css';
|
|
17
|
-
@import '@primer/primitives/dist/css/functional/size/border.css';
|
|
18
|
-
@import '@primer/primitives/dist/css/functional/size/breakpoints.css';
|
|
19
|
-
@import '@primer/primitives/dist/css/functional/size/size-coarse.css';
|
|
20
|
-
@import '@primer/primitives/dist/css/functional/size/size-fine.css';
|
|
21
|
-
@import '@primer/primitives/dist/css/functional/size/size.css';
|
|
22
|
-
@import '@primer/primitives/dist/css/functional/size/viewport.css';
|
|
23
|
-
@import '@primer/primitives/dist/css/functional/typography/typography.css';
|
|
24
|
-
|
|
25
|
-
@import '@primer/primitives/dist/css/functional/themes/light.css';
|
|
26
|
-
@import '@primer/primitives/dist/css/functional/themes/light-colorblind.css';
|
|
27
|
-
@import '@primer/primitives/dist/css/functional/themes/dark.css';
|
|
28
|
-
@import '@primer/primitives/dist/css/functional/themes/dark-colorblind.css';
|
|
29
|
-
@import '@primer/primitives/dist/css/functional/themes/dark-high-contrast.css';
|
|
30
|
-
@import '@primer/primitives/dist/css/functional/themes/dark-dimmed.css';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
.menuTitle {
|
|
2
2
|
font-size: 13px;
|
|
3
3
|
font-weight: 500;
|
|
4
|
-
color: var(--
|
|
4
|
+
color: var(--color-foreground, #e6edf3);
|
|
5
5
|
padding: 6px 6px 0;
|
|
6
6
|
margin: 0;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.description {
|
|
10
10
|
font-size: 12px;
|
|
11
|
-
color: var(--
|
|
11
|
+
color: var(--color-foreground-muted, #848d97);
|
|
12
12
|
padding: 0 6px 4px;
|
|
13
13
|
margin: 0;
|
|
14
14
|
line-height: 1.4;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
.branchLabel {
|
|
25
25
|
font-size: 13px;
|
|
26
26
|
font-weight: 500;
|
|
27
|
-
color: var(--
|
|
27
|
+
color: var(--color-foreground, #e6edf3);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
.statusRow {
|
|
@@ -33,19 +33,19 @@
|
|
|
33
33
|
|
|
34
34
|
.scopeHint {
|
|
35
35
|
font-size: 11px;
|
|
36
|
-
color: var(--
|
|
36
|
+
color: var(--color-foreground-muted, #848d97);
|
|
37
37
|
padding: 4px 0;
|
|
38
38
|
margin: 0;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
.statusError {
|
|
42
42
|
font-size: 11px;
|
|
43
|
-
color: var(--
|
|
43
|
+
color: var(--color-foreground-danger, #f85149);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
.statusOk {
|
|
47
47
|
font-size: 11px;
|
|
48
|
-
color: var(--
|
|
48
|
+
color: var(--color-foreground-muted, #848d97);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
.footer {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
align-items: center;
|
|
54
54
|
gap: 6px;
|
|
55
55
|
font-size: 12px;
|
|
56
|
-
color: var(--
|
|
56
|
+
color: var(--color-foreground-muted, #848d97);
|
|
57
57
|
padding: 2px 6px 0;
|
|
58
58
|
margin: 0;
|
|
59
59
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
.select {
|
|
2
2
|
width: 100%;
|
|
3
3
|
appearance: none;
|
|
4
|
-
background-color: var(--
|
|
5
|
-
color: var(--
|
|
6
|
-
border: 1px solid var(--
|
|
4
|
+
background-color: var(--color-background, #0d1117);
|
|
5
|
+
color: var(--color-foreground, #e6edf3);
|
|
6
|
+
border: 1px solid var(--color-border, #30363d);
|
|
7
7
|
border-radius: 8px;
|
|
8
8
|
padding: 8px 32px 8px 12px;
|
|
9
9
|
font-size: 13px;
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
.select:hover:not(:disabled) {
|
|
19
|
-
border-color: var(--
|
|
19
|
+
border-color: var(--color-foreground-muted, #848d97);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.select:focus-visible {
|
|
23
|
-
outline: 2px solid var(--
|
|
23
|
+
outline: 2px solid var(--color-border-accent-emphasis, #1f6feb);
|
|
24
24
|
outline-offset: -1px;
|
|
25
25
|
}
|
|
26
26
|
|