Skip to content

Commit

Permalink
wip: eigen huisstijl hack
Browse files Browse the repository at this point in the history
  • Loading branch information
bddjong committed Oct 19, 2024
1 parent e89ac10 commit 228339f
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 1 deletion.
137 changes: 137 additions & 0 deletions packages/storybook/addons/user-theme/manager.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { addons, types } from '@storybook/manager-api';
import { useStorybookState } from '@storybook/manager-api';
import React, { useRef, useState } from 'react';

addons.register('my/panel', () => {
addons.add('my-panel-addon/panel', {
title: 'Jouw huisstijl',
type: types.TAB, //another option is using a panel but its much less visible to non power users
route: () => `/design-tokens`,
match: ({ viewMode }) => viewMode === 'design-tokens',
render: () => <DesignTokenUploaderTab />,
});
});

const DesignTokenUploaderTab = () => {
const [themeName, setThemeName] = useState<string>(null);
const { storyId } = useStorybookState();
const iframeRef = useRef<HTMLIFrameElement>(null);
const iframeUrl = `/iframe.html?id=${storyId}&viewMode=story`;
const themeElementRef = useRef<HTMLElement | null>(null);

const handleFileUpload = (file: File) => {
const reader = new FileReader();

reader.onload = (e) => {
const fileContent = e.target?.result as string;

if (fileContent) {
console.log('File content successfully read:', fileContent);

const themeMatch = fileContent.match(/(\.[\w-]+)/);
if (themeMatch) {
const themeSelector = themeMatch[1];
setThemeName(formatSelectorAsThemeName(themeSelector));

console.log(`Extracted theme selector: ${themeSelector}`);

if (iframeRef.current) {
const iframeDoc = iframeRef.current.contentDocument || iframeRef.current.contentWindow?.document;
if (iframeDoc) {
applyCustomTheme(iframeDoc, themeSelector, fileContent);
}
}
} else {
console.error('Failed to extract a valid theme selector from the file.');
}
} else {
console.error('No file content was read.');
}
};

reader.readAsText(file);
};

const handleFileDrop = (e: React.DragEvent) => {
e.preventDefault();
const file = e.dataTransfer.files[0];
if (file) {
handleFileUpload(file);
}
};

const applyCustomTheme = (iframeDoc: Document, customTheme: string, fileContent: string) => {
const themeElement = iframeDoc.querySelector("[class$='-theme']");

if (themeElement) {
console.log('Found theme element:', themeElement);

themeElementRef.current = themeElement as HTMLElement;

const oldThemeClass = Array.from(themeElement.classList).find((c) => c.endsWith('-theme'));
if (oldThemeClass) {
themeElement.classList.remove(oldThemeClass);
}

themeElement.classList.add(customTheme.replace('.', ''));

const styleElement = document.createElement('style');
styleElement.innerHTML = fileContent;
themeElement.appendChild(styleElement);

console.log(`Applied new theme: ${customTheme} and dumped all CSS.`);
}
};

return (
<div style={{ height: '100vh', width: '100%', display: 'flex', flexDirection: 'column' }}>
<div
style={{ padding: '20px', background: '#444', borderBottom: '1px solid #ccc', marginBlockStart: '8px' }}
onDrop={handleFileDrop}
onDragOver={(e) => e.preventDefault()}
>
<h2>
Upload eigen huisstijl: <span>Actief: {themeName || 'Geen eigen thema'}</span>
</h2>
<p>
Je kan je eigen huisstijl uploaden door middel van een theme.css bestand. Lees hier voor een stappenplan: rip
geen docs
</p>
<input
type="file"
accept=".css"
onChange={(e) => {
if (e.target.files?.[0]) {
handleFileUpload(e.target.files[0]);
}
}}
/>
</div>

<div style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center', background: 'white' }}>
<iframe
id="storybook-canvas"
title="Storybook Canvas"
src={iframeUrl}
style={{
width: '100%',
height: '100%',
border: 'none',
margin: '0',
padding: '0',
background: 'white',
}}
ref={iframeRef}
/>
</div>
</div>
);
};

const formatSelectorAsThemeName = (selector: string) => {
return selector
.replace('.', '')
.split('-')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
};
1 change: 1 addition & 0 deletions packages/storybook/config/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const config: StorybookConfig = {
'@storybook/addon-docs',
'@storybook/addon-viewport',
'@whitespace/storybook-addon-html',
'../addons/user-theme',
],
framework: {
name: '@storybook/react-vite',
Expand Down
5 changes: 5 additions & 0 deletions packages/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
"@storybook/addon-interactions": "8.2.9",
"@storybook/addon-links": "8.2.9",
"@storybook/addon-viewport": "8.2.9",
"@storybook/components": "8.2.9",
"@storybook/manager-api": "8.2.9",
"@storybook/blocks": "8.2.9",
"@storybook/core-client": "8.2.9",
"@storybook/preview-api": "8.2.9",
"@storybook/react": "8.2.9",
"@storybook/react-vite": "8.2.9",
"@tabler/icons-react": "3.14.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/storybook/src/templates/form-wmebv/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
--todo-page-header-padding-inline-end: var(--voorbeeld-space-inline-mouse);
}

.utrecht-document {
--utrecht-space-around: 1;
}

.voorbeeld-back-link {
align-items: center;
column-gap: 8px;
Expand Down
2 changes: 1 addition & 1 deletion packages/storybook/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
"skipLibCheck": true
},
"extends": "../../tsconfig.json",
"include": ["config/**/*.ts", "config/**/*.tsx", "src/**/*.ts", "src/**/*.tsx"],
"include": ["config/**/*.ts", "config/**/*.tsx", "src/**/*.ts", "src/**/*.tsx", "addons/**/*.ts", "addons/**/*.tsx"],
"exclude": ["**/node_modules/*"]
}
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 228339f

Please sign in to comment.