@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.48 → 2.0.0-next.50
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/.storybook/ComponentPreview.tsx +26 -0
- package/.storybook/PreviewTemplate.tsx +99 -0
- package/.storybook/action-handler.ts +81 -0
- package/.storybook/channels.ts +44 -0
- package/.storybook/main.ts +313 -0
- package/.storybook/manager.ts +71 -0
- package/.storybook/openbridgeTheme.ts +197 -0
- package/.storybook/preview-head.html +15 -0
- package/.storybook/preview.tsx +129 -0
- package/.storybook/vitest.setup.ts +23 -0
- package/bundle/openbridge-webcomponents.bundle.js +196 -38
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +16 -1
- package/dist/automation/automation-tank/automation-tank.css.js +166 -28
- package/dist/automation/automation-tank/automation-tank.css.js.map +1 -1
- package/dist/automation/automation-tank/automation-tank.d.ts +32 -0
- package/dist/automation/automation-tank/automation-tank.d.ts.map +1 -1
- package/dist/automation/automation-tank/automation-tank.js +28 -0
- package/dist/automation/automation-tank/automation-tank.js.map +1 -1
- package/dist/components/icon-button/icon-button.d.ts +4 -0
- package/dist/components/icon-button/icon-button.d.ts.map +1 -1
- package/dist/components/icon-button/icon-button.js.map +1 -1
- package/dist/components/message-menu-item/message-menu-item.css.js +2 -10
- package/dist/components/message-menu-item/message-menu-item.css.js.map +1 -1
- package/eslint.config.mjs +589 -0
- package/fix-imports.mjs +185 -0
- package/fix-js-extensions.mjs +44 -0
- package/lit-localize.json +15 -0
- package/new-component.ts +148 -0
- package/package.json +55 -3
- package/postcss.config.mjs +195 -0
- package/script/check-css-mixins.ts +191 -0
- package/script/check-css-variables.ts +280 -0
- package/script/convert-icons.ts +202 -0
- package/script/convert-vessel-svg-to-ts.ts +110 -0
- package/script/docgen/README.md +95 -0
- package/script/docgen/docs-gen.ts +225 -0
- package/script/docgen/prompt-system.txt +187 -0
- package/script/download-alert-icons.ts +193 -0
- package/script/download-icons.ts +314 -0
- package/script/figmavariables.json +139 -0
- package/script/generate-bundle-entry.ts +77 -0
- package/script/prepare-full-bundle.ts +105 -0
- package/script/sort-custom-element-manifest.ts +67 -0
- package/src/automation/automation-tank/automation-tank.css +119 -21
- package/src/automation/automation-tank/automation-tank.stories.ts +38 -0
- package/src/automation/automation-tank/automation-tank.ts +64 -0
- package/src/components/icon-button/icon-button.ts +4 -0
- package/src/components/message-menu-item/message-menu-item.css +2 -5
- package/vite.config.ts +107 -0
- package/vitest.browser.config.ts +14 -0
- package/vitest.config.ts +51 -0
- package/xliff/es-419.xlf +111 -0
- package/xliff/fi-FI.xlf +139 -0
- package/dist/NotoSans.ttf +0 -0
- package/dist/oicl.svg +0 -4
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useOf, DocsContext, Story } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import React, { useContext } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A block that displays the story name or title from the of prop
|
|
6
|
+
* - if a story reference is passed, it renders the story name
|
|
7
|
+
* - if a meta reference is passed, it renders the stories' title
|
|
8
|
+
* - if nothing is passed, it defaults to the primary story
|
|
9
|
+
*/
|
|
10
|
+
export const ComponentPreview = (props: { of?: string }) => {
|
|
11
|
+
const { of } = props;
|
|
12
|
+
if ('of' in props && of === undefined) {
|
|
13
|
+
throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { csfFile } = useOf(of || 'meta', ['meta']);
|
|
17
|
+
const context = useContext(DocsContext);
|
|
18
|
+
|
|
19
|
+
const primaryStory = context.componentStoriesFromCSFFile(csfFile)[0];
|
|
20
|
+
|
|
21
|
+
return primaryStory ? (
|
|
22
|
+
<div style={{ padding: '24px', backgroundColor: 'var(--container-section-color)', width: '100%', borderRadius: '2px'}}>
|
|
23
|
+
<Story of={primaryStory.moduleExport} />
|
|
24
|
+
</div>
|
|
25
|
+
) : null;
|
|
26
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React, { useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { Meta, Title, Primary, Controls, Stories, Description, Subtitle } from '@storybook/addon-docs/blocks';
|
|
3
|
+
import { ComponentPreview } from './ComponentPreview.js';
|
|
4
|
+
|
|
5
|
+
const STICKY_MAX_HEIGHT_VH = 80;
|
|
6
|
+
const getStickyMaxHeight = () => (window.innerHeight * STICKY_MAX_HEIGHT_VH) / 100;
|
|
7
|
+
|
|
8
|
+
function useStickyOnSmall(getMaxHeight: () => number, enabled: boolean) {
|
|
9
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
10
|
+
const [isSticky, setIsSticky] = useState(true);
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!ref.current || !enabled) return;
|
|
14
|
+
|
|
15
|
+
const checkSticky = () => {
|
|
16
|
+
if (!ref.current) return;
|
|
17
|
+
const height = ref.current.getBoundingClientRect().height;
|
|
18
|
+
setIsSticky(height <= getMaxHeight());
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const observer = new ResizeObserver(() => {
|
|
22
|
+
requestAnimationFrame(checkSticky);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
observer.observe(ref.current);
|
|
26
|
+
|
|
27
|
+
window.addEventListener('resize', checkSticky);
|
|
28
|
+
|
|
29
|
+
return () => {
|
|
30
|
+
observer.disconnect();
|
|
31
|
+
window.removeEventListener('resize', checkSticky);
|
|
32
|
+
};
|
|
33
|
+
}, [getMaxHeight, enabled]);
|
|
34
|
+
|
|
35
|
+
return { ref, isSticky };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const PreviewTemplate: React.FC = () => {
|
|
39
|
+
const [isCollapsed, setIsCollapsed] = useState(false);
|
|
40
|
+
const { ref: previewRef, isSticky } = useStickyOnSmall(getStickyMaxHeight, !isCollapsed);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<>
|
|
44
|
+
<Meta />
|
|
45
|
+
<Title />
|
|
46
|
+
<ComponentPreview of="meta" />
|
|
47
|
+
<Subtitle />
|
|
48
|
+
<Description />
|
|
49
|
+
<div>
|
|
50
|
+
<div
|
|
51
|
+
ref={previewRef}
|
|
52
|
+
style={{
|
|
53
|
+
position: isSticky ? 'sticky' : 'relative',
|
|
54
|
+
top: isSticky ? 0 : undefined,
|
|
55
|
+
zIndex: 10,
|
|
56
|
+
backgroundColor: 'var(--container-section-color)',
|
|
57
|
+
borderRadius: '2px',
|
|
58
|
+
overflow: 'hidden',
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
{/* Toolbar */}
|
|
62
|
+
<div style={{
|
|
63
|
+
display: 'flex',
|
|
64
|
+
justifyContent: 'space-between',
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
padding: '8px 12px',
|
|
67
|
+
borderBottom: isCollapsed ? 'none' : '1px solid rgba(128, 128, 128, 0.2)',
|
|
68
|
+
backgroundColor: 'rgba(0, 0, 0, 0.05)',
|
|
69
|
+
}}>
|
|
70
|
+
<span style={{ fontSize: '12px', fontWeight: 500, opacity: 0.7 }}>Preview</span>
|
|
71
|
+
<button
|
|
72
|
+
onClick={() => setIsCollapsed(!isCollapsed)}
|
|
73
|
+
style={{
|
|
74
|
+
padding: '4px 8px',
|
|
75
|
+
fontSize: '11px',
|
|
76
|
+
border: '1px solid rgba(128, 128, 128, 0.3)',
|
|
77
|
+
borderRadius: '4px',
|
|
78
|
+
background: 'transparent',
|
|
79
|
+
cursor: 'pointer',
|
|
80
|
+
}}
|
|
81
|
+
>
|
|
82
|
+
{isCollapsed ? 'Expand' : 'Collapse'}
|
|
83
|
+
</button>
|
|
84
|
+
</div>
|
|
85
|
+
{/* Preview content */}
|
|
86
|
+
{!isCollapsed && (
|
|
87
|
+
<div style={{ padding: '24px' }}>
|
|
88
|
+
<Primary />
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
</div>
|
|
92
|
+
<Controls />
|
|
93
|
+
</div>
|
|
94
|
+
<Stories />
|
|
95
|
+
</>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default PreviewTemplate;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type {PartialStoryFn, Renderer} from 'storybook/internal/types';
|
|
2
|
+
|
|
3
|
+
import {makeDecorator, useEffect} from 'storybook/preview-api';
|
|
4
|
+
import {getCustomElements} from '@storybook/web-components';
|
|
5
|
+
|
|
6
|
+
import {action} from 'storybook/actions';
|
|
7
|
+
|
|
8
|
+
const actionsFn = (e: Event) => {
|
|
9
|
+
const eventName = e.type;
|
|
10
|
+
let detail: unknown = undefined;
|
|
11
|
+
if (e instanceof CustomEvent) {
|
|
12
|
+
if (e.detail !== undefined) {
|
|
13
|
+
const serialized = JSON.stringify(e.detail);
|
|
14
|
+
detail = serialized !== undefined ? JSON.parse(serialized) : undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
action(eventName)({
|
|
18
|
+
detail,
|
|
19
|
+
type: e.type,
|
|
20
|
+
bubbles: e.bubbles,
|
|
21
|
+
composed: e.composed,
|
|
22
|
+
cancelable: e.cancelable,
|
|
23
|
+
target: e.target,
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const recursiveFindObcElement = (element: HTMLElement): HTMLElement | null => {
|
|
28
|
+
if (element.tagName.startsWith('OBC-')) {
|
|
29
|
+
return element;
|
|
30
|
+
}
|
|
31
|
+
if (element.children.length > 0) {
|
|
32
|
+
for (const child of element.children) {
|
|
33
|
+
const obcElement = recursiveFindObcElement(child as HTMLElement);
|
|
34
|
+
if (obcElement) {
|
|
35
|
+
return obcElement;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const applyEventHandlers = (...handles: string[]) => {
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
const root = document.getElementById('storybook-root');
|
|
45
|
+
const obcElement = root && recursiveFindObcElement(root);
|
|
46
|
+
if (obcElement) {
|
|
47
|
+
handles.forEach((eventName) => {
|
|
48
|
+
obcElement.addEventListener(eventName, actionsFn);
|
|
49
|
+
});
|
|
50
|
+
return () =>
|
|
51
|
+
handles.forEach((eventName) =>
|
|
52
|
+
obcElement.removeEventListener(eventName, actionsFn)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}, [handles]);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const withActions: <T extends Renderer>(
|
|
60
|
+
storyFn: PartialStoryFn<T>
|
|
61
|
+
) => T['storyResult'] = makeDecorator({
|
|
62
|
+
name: 'withActions',
|
|
63
|
+
parameterName: 'actions',
|
|
64
|
+
skipIfNoParametersOrOptions: false,
|
|
65
|
+
wrapper: (getStory, context) => {
|
|
66
|
+
const customElements = getCustomElements();
|
|
67
|
+
const module = customElements.modules.find(
|
|
68
|
+
(m: {declarations: {tagName: string}[]}) =>
|
|
69
|
+
m.declarations.find((e) => e.tagName === context.component)
|
|
70
|
+
);
|
|
71
|
+
const component = module?.declarations.find(
|
|
72
|
+
(e: {tagName: string}) => e.tagName === context.component
|
|
73
|
+
);
|
|
74
|
+
const events = component?.events?.map((e: {name: string}) => e.name);
|
|
75
|
+
if (events) {
|
|
76
|
+
applyEventHandlers(...events);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return getStory(context);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// These constants are the single source of truth for the Storybook channel
|
|
2
|
+
// links shown in the sidebar brand area and on the Introduction page.
|
|
3
|
+
//
|
|
4
|
+
// Background: the library has two long-lived release branches:
|
|
5
|
+
// - `stable` → published quarterly to the Stable Storybook
|
|
6
|
+
// - `develop` → published on every merge to the Develop Storybook
|
|
7
|
+
//
|
|
8
|
+
// The Develop URL below is a placeholder until the second Firebase Hosting
|
|
9
|
+
// site is provisioned and a branch-based deploy workflow is in place.
|
|
10
|
+
|
|
11
|
+
export const STORYBOOK_STABLE_URL = 'https://openbridge-storybook.web.app';
|
|
12
|
+
export const STORYBOOK_DEVELOP_URL =
|
|
13
|
+
'https://openbridge-next-storybook.web.app';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Detects the current Storybook branch/channel.
|
|
17
|
+
* Priorities:
|
|
18
|
+
* 1. VITE_STORYBOOK_BRANCH env var (set during CI build)
|
|
19
|
+
* 2. Hostname detection (for deployed instances)
|
|
20
|
+
* 3. Default to 'develop' (for local dev)
|
|
21
|
+
*/
|
|
22
|
+
export const getBranch = (): 'stable' | 'develop' => {
|
|
23
|
+
// Use process.env and window globals instead of import.meta to avoid IIFE warnings in Storybook Manager.
|
|
24
|
+
// These are injected/defined in main.ts.
|
|
25
|
+
const envBranch =
|
|
26
|
+
(typeof process !== 'undefined' && process.env?.VITE_STORYBOOK_BRANCH) ||
|
|
27
|
+
(typeof window !== 'undefined' && (window as any).VITE_STORYBOOK_BRANCH);
|
|
28
|
+
|
|
29
|
+
if (envBranch === 'stable' || envBranch === 'develop') {
|
|
30
|
+
return envBranch as 'stable' | 'develop';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (typeof window !== 'undefined' && window.location.hostname) {
|
|
34
|
+
const host = window.location.hostname;
|
|
35
|
+
if (host.includes('-next')) return 'develop';
|
|
36
|
+
if (host.includes('openbridge-storybook.web.app')) return 'stable';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return 'develop';
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const STORYBOOK_BRANCH = getBranch();
|
|
43
|
+
export const isStable = STORYBOOK_BRANCH === 'stable';
|
|
44
|
+
export const isDevelop = STORYBOOK_BRANCH === 'develop';
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
// This file has been automatically migrated to valid ESM format by Storybook.
|
|
2
|
+
import {createRequire} from 'node:module';
|
|
3
|
+
import {dirname, join} from 'path';
|
|
4
|
+
import type {StorybookConfig} from '@storybook/web-components-vite';
|
|
5
|
+
import FullReload from 'vite-plugin-full-reload';
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
|
|
9
|
+
const config: StorybookConfig = {
|
|
10
|
+
stories: [
|
|
11
|
+
'../src/**/*.mdx',
|
|
12
|
+
'../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
|
|
13
|
+
'../docs/**/*.mdx',
|
|
14
|
+
'../docs/**/*.stories.@(js|jsx|mjs|ts|tsx)',
|
|
15
|
+
],
|
|
16
|
+
|
|
17
|
+
addons: [
|
|
18
|
+
getAbsolutePath('@storybook/addon-links'),
|
|
19
|
+
getAbsolutePath('@storybook/addon-themes'),
|
|
20
|
+
getAbsolutePath('storybook-addon-tag-badges'),
|
|
21
|
+
getAbsolutePath('@storybook/addon-docs'),
|
|
22
|
+
getAbsolutePath('@storybook/addon-vitest'),
|
|
23
|
+
// getAbsolutePath('storybook-addon-vis'),
|
|
24
|
+
],
|
|
25
|
+
|
|
26
|
+
framework: {
|
|
27
|
+
name: getAbsolutePath('@storybook/web-components-vite'),
|
|
28
|
+
options: {},
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
staticDirs: [{from: '../public', to: '/assets'}],
|
|
32
|
+
|
|
33
|
+
async viteFinal(viteConfig) {
|
|
34
|
+
// full reload whenever a TypeScript, CSS (or HTML) file in /src changes
|
|
35
|
+
viteConfig.plugins ??= [];
|
|
36
|
+
viteConfig.plugins.push(FullReload(['src/**/*.{ts,css,html}']));
|
|
37
|
+
|
|
38
|
+
// Ensure process.env.VITE_STORYBOOK_BRANCH is replaced in the preview
|
|
39
|
+
viteConfig.define = {
|
|
40
|
+
...viteConfig.define,
|
|
41
|
+
'process.env.VITE_STORYBOOK_BRANCH': JSON.stringify(
|
|
42
|
+
process.env.VITE_STORYBOOK_BRANCH || ''
|
|
43
|
+
),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return viteConfig;
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
previewHead: (head, options) => `
|
|
50
|
+
<dialog> ${options.configType}</dialog>
|
|
51
|
+
${head}
|
|
52
|
+
<style>
|
|
53
|
+
@font-face {
|
|
54
|
+
font-family: Noto Sans;
|
|
55
|
+
src: url(./assets/NotoSans.ttf);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@font-face {
|
|
59
|
+
font-family: 'noto-sans';
|
|
60
|
+
src: url(./assets/NotoSans.ttf);
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
63
|
+
`,
|
|
64
|
+
|
|
65
|
+
managerHead: (head) => `
|
|
66
|
+
${head}
|
|
67
|
+
<script>
|
|
68
|
+
window.VITE_STORYBOOK_BRANCH = "${process.env.VITE_STORYBOOK_BRANCH || ''}";
|
|
69
|
+
</script>
|
|
70
|
+
<style>
|
|
71
|
+
/* OpenBridge Storybook UI Fixes */
|
|
72
|
+
|
|
73
|
+
/* ========== DARK THEME ========== */
|
|
74
|
+
@media (prefers-color-scheme: dark) {
|
|
75
|
+
/* Search results - non-matched letters */
|
|
76
|
+
#storybook-explorer-searchfield ~ div li,
|
|
77
|
+
#storybook-explorer-searchfield ~ div li span,
|
|
78
|
+
#storybook-explorer-searchfield ~ div li div,
|
|
79
|
+
[id*="search"] ~ * li,
|
|
80
|
+
[role="listbox"] li,
|
|
81
|
+
[role="listbox"] li span,
|
|
82
|
+
[role="option"],
|
|
83
|
+
[role="option"] span {
|
|
84
|
+
color: rgb(140, 140, 140) !important;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Matched/searched letters */
|
|
88
|
+
#storybook-explorer-searchfield ~ div mark,
|
|
89
|
+
[id*="search"] ~ * mark,
|
|
90
|
+
[role="listbox"] mark,
|
|
91
|
+
[role="option"] mark,
|
|
92
|
+
mark {
|
|
93
|
+
background: transparent !important;
|
|
94
|
+
color: rgb(233, 233, 233) !important;
|
|
95
|
+
font-weight: 600 !important;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Search result path text */
|
|
99
|
+
[role="option"] > div:last-child,
|
|
100
|
+
[role="listbox"] li > div:last-child {
|
|
101
|
+
color: rgb(140, 140, 140) !important;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Search result icons */
|
|
105
|
+
[role="listbox"] svg,
|
|
106
|
+
[role="option"] svg {
|
|
107
|
+
color: rgb(180, 180, 180) !important;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Search results background */
|
|
111
|
+
[role="listbox"],
|
|
112
|
+
[role="listbox"] li,
|
|
113
|
+
[role="option"] {
|
|
114
|
+
background: rgb(24, 24, 24) !important;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Sidebar item text */
|
|
118
|
+
button[data-nodetype] > span,
|
|
119
|
+
[data-nodetype="component"] span,
|
|
120
|
+
[data-nodetype="story"] span {
|
|
121
|
+
color: rgb(220, 220, 220) !important;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Selected/active sidebar item text */
|
|
125
|
+
[data-selected="true"] span {
|
|
126
|
+
color: rgb(255, 255, 255) !important;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* Search input placeholder */
|
|
130
|
+
input::placeholder {
|
|
131
|
+
color: rgb(140, 140, 140) !important;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Sidebar icons */
|
|
135
|
+
#storybook-explorer-tree .sidebar-item svg {
|
|
136
|
+
color: rgb(180, 180, 180) !important;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* Selected sidebar item background */
|
|
140
|
+
[data-selected="true"] {
|
|
141
|
+
background: rgb(60, 60, 60) !important;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* Remove box-shadow on selected items */
|
|
145
|
+
[data-selected="true"] *,
|
|
146
|
+
[data-selected="true"] [class*="css-"] {
|
|
147
|
+
box-shadow: none !important;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* ========== LIGHT THEME ========== */
|
|
152
|
+
@media (prefers-color-scheme: light) {
|
|
153
|
+
/* Search results - non-matched letters */
|
|
154
|
+
#storybook-explorer-searchfield ~ div li,
|
|
155
|
+
#storybook-explorer-searchfield ~ div li span,
|
|
156
|
+
#storybook-explorer-searchfield ~ div li div,
|
|
157
|
+
[id*="search"] ~ * li,
|
|
158
|
+
[role="listbox"] li,
|
|
159
|
+
[role="listbox"] li span,
|
|
160
|
+
[role="option"],
|
|
161
|
+
[role="option"] span {
|
|
162
|
+
color: rgb(112, 112, 112) !important;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Matched/searched letters */
|
|
166
|
+
#storybook-explorer-searchfield ~ div mark,
|
|
167
|
+
[id*="search"] ~ * mark,
|
|
168
|
+
[role="listbox"] mark,
|
|
169
|
+
[role="option"] mark,
|
|
170
|
+
mark {
|
|
171
|
+
background: transparent !important;
|
|
172
|
+
color: rgb(31, 31, 31) !important;
|
|
173
|
+
font-weight: 600 !important;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* Search result path text */
|
|
177
|
+
[role="option"] > div:last-child,
|
|
178
|
+
[role="listbox"] li > div:last-child {
|
|
179
|
+
color: rgb(112, 112, 112) !important;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Search result icons */
|
|
183
|
+
[role="listbox"] svg,
|
|
184
|
+
[role="option"] svg {
|
|
185
|
+
color: rgb(83, 83, 83) !important;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* Search results background */
|
|
189
|
+
[role="listbox"],
|
|
190
|
+
[role="listbox"] li,
|
|
191
|
+
[role="option"] {
|
|
192
|
+
background: rgb(247, 247, 247) !important;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* Sidebar item text */
|
|
196
|
+
button[data-nodetype] > span,
|
|
197
|
+
[data-nodetype="component"] span,
|
|
198
|
+
[data-nodetype="story"] span {
|
|
199
|
+
color: rgb(31, 31, 31) !important;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
/* Search input placeholder */
|
|
204
|
+
input::placeholder {
|
|
205
|
+
color: rgb(112, 112, 112) !important;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* Sidebar icons */
|
|
209
|
+
#storybook-explorer-tree .sidebar-item svg {
|
|
210
|
+
color: rgb(83, 83, 83) !important;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* Non-selected sidebar item HOVER state - gray background */
|
|
214
|
+
[data-nodetype]:not([data-selected="true"]):hover,
|
|
215
|
+
[data-nodetype="story"]:not([data-selected="true"]):hover,
|
|
216
|
+
[data-nodetype="component"]:not([data-selected="true"]):hover,
|
|
217
|
+
[data-nodetype="docs"]:not([data-selected="true"]):hover,
|
|
218
|
+
.css-wzf5rv:hover,
|
|
219
|
+
.css-wzf5rv:focus {
|
|
220
|
+
--tree-node-background-hover: rgb(224, 224, 224) !important;
|
|
221
|
+
background: rgb(224, 224, 224) !important;
|
|
222
|
+
box-shadow: none !important;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* Selected sidebar item background - light blue */
|
|
226
|
+
[data-selected="true"],
|
|
227
|
+
button[data-selected="true"],
|
|
228
|
+
a[data-selected="true"],
|
|
229
|
+
[data-nodetype][data-selected="true"],
|
|
230
|
+
[data-nodetype="story"][data-selected="true"],
|
|
231
|
+
[data-nodetype="component"][data-selected="true"],
|
|
232
|
+
[data-nodetype="docs"][data-selected="true"] {
|
|
233
|
+
background: #DBECFF !important;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Selected sidebar item text - dark for contrast on light blue */
|
|
237
|
+
[data-selected="true"] span,
|
|
238
|
+
[data-selected="true"] > span,
|
|
239
|
+
[data-selected="true"] div,
|
|
240
|
+
[data-selected="true"] [class*="css-"],
|
|
241
|
+
button[data-selected="true"] span,
|
|
242
|
+
a[data-selected="true"] span,
|
|
243
|
+
[data-nodetype][data-selected="true"] span,
|
|
244
|
+
[data-nodetype="story"][data-selected="true"] span,
|
|
245
|
+
[data-nodetype="component"][data-selected="true"] span,
|
|
246
|
+
[data-nodetype="docs"][data-selected="true"] span {
|
|
247
|
+
color: rgb(31, 31, 31) !important;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* Remove box-shadow on selected items */
|
|
251
|
+
[data-selected="true"] *,
|
|
252
|
+
[data-selected="true"] [class*="css-"] {
|
|
253
|
+
box-shadow: none !important;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/* Selected sidebar item HOVER state - slightly darker light blue */
|
|
257
|
+
[data-selected="true"]:hover,
|
|
258
|
+
button[data-selected="true"]:hover,
|
|
259
|
+
a[data-selected="true"]:hover,
|
|
260
|
+
[data-nodetype][data-selected="true"]:hover,
|
|
261
|
+
[data-nodetype="story"][data-selected="true"]:hover,
|
|
262
|
+
[data-nodetype="component"][data-selected="true"]:hover,
|
|
263
|
+
[data-nodetype="docs"][data-selected="true"]:hover {
|
|
264
|
+
background: #C8E0FF !important;
|
|
265
|
+
box-shadow: none !important;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* Remove box-shadow on selected item hover */
|
|
269
|
+
[data-selected="true"]:hover * {
|
|
270
|
+
box-shadow: none !important;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Selected sidebar item text on hover - keep dark */
|
|
274
|
+
[data-selected="true"]:hover span,
|
|
275
|
+
[data-selected="true"]:hover div,
|
|
276
|
+
[data-selected="true"]:hover [class*="css-"],
|
|
277
|
+
button[data-selected="true"]:hover span,
|
|
278
|
+
a[data-selected="true"]:hover span,
|
|
279
|
+
[data-nodetype][data-selected="true"]:hover span {
|
|
280
|
+
color: rgb(31, 31, 31) !important;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/* Fix context menu button (three dots) blue background */
|
|
284
|
+
[data-selected="true"] button,
|
|
285
|
+
[data-selected="true"]:hover button,
|
|
286
|
+
[data-selected="true"] [aria-label],
|
|
287
|
+
[data-selected="true"]:hover [aria-label],
|
|
288
|
+
button[aria-label*="menu" i],
|
|
289
|
+
button[aria-label*="actions" i],
|
|
290
|
+
.sidebar-item button,
|
|
291
|
+
[data-nodetype] button {
|
|
292
|
+
background: transparent !important;
|
|
293
|
+
background-color: transparent !important;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Fix boolean toggle buttons - use white background with dark text */
|
|
297
|
+
[class*="css-"] input:checked ~ span:last-of-type,
|
|
298
|
+
[class*="css-"] input:not(:checked) ~ span:first-of-type {
|
|
299
|
+
background: rgb(255, 255, 255) !important;
|
|
300
|
+
color: rgb(31, 31, 31) !important;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
</style>
|
|
305
|
+
`,
|
|
306
|
+
|
|
307
|
+
docs: {},
|
|
308
|
+
};
|
|
309
|
+
export default config;
|
|
310
|
+
|
|
311
|
+
function getAbsolutePath(value: string): string {
|
|
312
|
+
return dirname(require.resolve(join(value, 'package.json')));
|
|
313
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {addons} from 'storybook/manager-api';
|
|
2
|
+
import {openbridgeDark, openbridgeLight} from './openbridgeTheme.js';
|
|
3
|
+
|
|
4
|
+
// Detect system color scheme preference
|
|
5
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
6
|
+
|
|
7
|
+
addons.setConfig({
|
|
8
|
+
// Use OpenBridge themed variants for both light and dark mode
|
|
9
|
+
theme: prefersDark ? openbridgeDark : openbridgeLight,
|
|
10
|
+
|
|
11
|
+
// Put controls panel on the right side
|
|
12
|
+
panelPosition: 'right',
|
|
13
|
+
selectedPanel: 'addon-controls',
|
|
14
|
+
initialActive: 'canvas',
|
|
15
|
+
|
|
16
|
+
// Sidebar configuration
|
|
17
|
+
sidebar: {
|
|
18
|
+
showRoots: true,
|
|
19
|
+
collapsedRoots: ['other'],
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Tag badges for version indicators
|
|
23
|
+
tagBadges: [
|
|
24
|
+
{
|
|
25
|
+
tags: '5.0',
|
|
26
|
+
badge: {
|
|
27
|
+
text: '5.0',
|
|
28
|
+
style: {
|
|
29
|
+
backgroundColor: 'rgb(255, 219, 55)',
|
|
30
|
+
color: '#000',
|
|
31
|
+
},
|
|
32
|
+
tooltip: 'OpenBridge 5.0',
|
|
33
|
+
},
|
|
34
|
+
display: {
|
|
35
|
+
sidebar: ['component'],
|
|
36
|
+
toolbar: true,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
tags: 'alpha',
|
|
41
|
+
badge: {
|
|
42
|
+
text: '6.0 Alpha',
|
|
43
|
+
style: {
|
|
44
|
+
backgroundColor: 'rgb(255, 219, 55)',
|
|
45
|
+
color: '#000',
|
|
46
|
+
},
|
|
47
|
+
tooltip: 'Alpha components are still under design and may change.',
|
|
48
|
+
},
|
|
49
|
+
display: {
|
|
50
|
+
sidebar: ['component'],
|
|
51
|
+
toolbar: true,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
tags: 'wip',
|
|
56
|
+
badge: {
|
|
57
|
+
text: 'WIP',
|
|
58
|
+
style: {
|
|
59
|
+
backgroundColor: 'rgb(255, 219, 55)',
|
|
60
|
+
color: '#000',
|
|
61
|
+
},
|
|
62
|
+
tooltip:
|
|
63
|
+
'Work in progress components are still under development and may change.',
|
|
64
|
+
},
|
|
65
|
+
display: {
|
|
66
|
+
sidebar: ['component'],
|
|
67
|
+
toolbar: true,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
});
|