Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: eigen huisstijl hack #202

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
9 changes: 9 additions & 0 deletions packages/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
},
"devDependencies": {
"@gemeente-denhaag/design-tokens-components": "0.2.3-alpha.408",
"@gemeente-denhaag/action": "0.1.1-alpha.80",
"@gemeente-denhaag/card": "0.2.3-alpha.414",
"@gemeente-denhaag/sidenav": "0.1.0-alpha.228",
"@nl-design-system-unstable/voorbeeld-design-tokens": "2.0.0",
"@storybook/addon-a11y": "8.2.9",
Expand All @@ -29,12 +31,19 @@
"@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",
"@types/react": "18.3.5",
"@types/react-dom": "18.3.0",
"@utrecht/component-library-react": "7.2.0",
"@utrecht/design-tokens": "2.1.1",
"@utrecht/button-react": "2.0.0",
"@utrecht/icon": "1.1.0",
"@vng.nl/assets": "workspace:*",
"@vng.nl/design-tokens": "workspace:*",
Expand Down
33 changes: 33 additions & 0 deletions packages/storybook/src/components/ExpandableSection/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.todo-expandable-section {
border: 1px solid #ccc;
inline-size: 100%;
margin-block-end: 24px;
}

.todo-expandable-section__header {
align-items: start;
background-color: #f9f9fa;
column-gap: 8px;
cursor: pointer;
display: flex;
justify-content: flex-start;
padding-block: 12px;
padding-inline: 16px;
}

.todo-expandable-section__title {
font-size: inherit;
margin-block: 0;
}

.todo-expandable-section__button {
background: transparent;
border: none;
cursor: pointer;
}

.todo-expandable-section__content {
background-color: #fff;
padding-block: 24px;
padding-inline: 16px;
}
34 changes: 34 additions & 0 deletions packages/storybook/src/components/ExpandableSection/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { IconChevronDown, IconChevronUp } from '@tabler/icons-react';
import React, { ReactNode, useState } from 'react';
import './index.css';

export interface ExpandableSectionProps {
title: ReactNode;
description?: ReactNode;
children?: ReactNode;
}

export const ExpandableSection: React.FC<ExpandableSectionProps> = ({ title, description, children }) => {
const [isExpanded, setIsExpanded] = useState<boolean>(false);

const togglePanel = () => {
setIsExpanded(!isExpanded);
};

return (
<div className={`todo-expandable-section ${isExpanded ? 'todo-expandable-section--expanded' : ''}`}>
<div className="todo-expandable-section__header" onClick={togglePanel}>
<button className="todo-expandable-section__button">
{isExpanded ? <IconChevronUp /> : <IconChevronDown />}
</button>
<div>
<h2 className="todo-expandable-section__title">{title}</h2>
{description && <div className="todo-expandable-section__description">{description}</div>}
</div>
</div>
{isExpanded && <div className="todo-expandable-section__content">{children}</div>}
</div>
);
};

export default ExpandableSection;
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,25 @@ import {
PageHeader,
} from '@utrecht/component-library-react/dist/css-module';
import { HTMLAttributes, PropsWithChildren, ReactElement } from 'react';
import { Logo, PageHeaderLogo } from './Logo';

interface LayoutProps extends PropsWithChildren<HTMLAttributes<HTMLDivElement>> {
logo?: ReactElement;
footerLogo?: ReactElement;
}

export const Layout = ({ logo, children, className, ...props }: LayoutProps) => {
export const Layout = ({ logo, children, className, footerLogo, ...props }: LayoutProps) => {
return (
<div className={`utrecht-document ${className}`} {...props}>
<PageHeader className="voorbeeld-page-header">
<div className="todo-page-header__content">{logo || <PageHeaderLogo />}</div>
<div className="todo-page-header__content">{logo}</div>
</PageHeader>
<PageContent className="todo-page-content">
<main className={'utrecht-page-content__main'}>{children}</main>
</PageContent>
<PageFooter>
<div className="todo-page-footer__content">
<div className="todo-footer-content-group">
<div className="todo-footer-content-block">{logo || <Logo />}</div>
{footerLogo && <div className="todo-footer-content-block">{footerLogo}</div>}
<div className="todo-footer-content-block">
<Heading2>Contact</Heading2>
<address className="todo-address utrecht-paragraph">
Expand Down

Large diffs are not rendered by default.

109 changes: 109 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,115 @@
--todo-page-header-padding-inline-end: var(--voorbeeld-space-inline-mouse);
}

.denhaag-theme {
--utrecht-space-around: 1;
--utrecht-article-max-inline-size: 670px;
--todo-page-header-content-max-inline-size: calc(var(--utrecht-article-max-inline-size) * 1.5);
--todo-page-header-padding-inline-start: var(--voorbeeld-space-inline-mouse);
--todo-page-header-padding-inline-end: var(--voorbeeld-space-inline-mouse);
--utrecht-paragraph-margin-block-end: var(--voorbeeld-space-block-rabbit);
--utrecht-heading-1-margin-block-start: 0;
--utrecht-heading-1-margin-block-end: var(--voorbeeld-space-block-rabbit);
--utrecht-heading-2-margin-block-end: var(--voorbeeld-space-block-rabbit);
--utrecht-heading-3-margin-block-start: var(--voorbeeld-space-block-rabbit);
--utrecht-button-group-margin-block-start: var(--voorbeeld-space-block-rabbit);
--utrecht-page-footer-padding-block-end: var(--voorbeeld-space-block-dog);
--utrecht-page-footer-padding-block-start: var(--voorbeeld-space-block-dog);
--utrecht-page-footer-padding-inline-end: var(--voorbeeld-space-inline-dog);
--utrecht-page-footer-padding-inline-start: var(--voorbeeld-space-inline-dog);
--utrecht-page-header-padding-block-start: var(--voorbeeld-space-block-mouse);
--utrecht-page-header-padding-block-end: var(--voorbeeld-space-block-mouse);
--utrecht-page-padding-inline-start: var(--voorbeeld-space-inline-pig);
--utrecht-page-padding-inline-end: var(--voorbeeld-space-inline-pig);
--utrecht-page-content-padding-block-start: var(--voorbeeld-space-block-beetle);
--utrecht-page-content-padding-block-end: var(--voorbeeld-space-block-dog);
--utrecht-page-content-padding-inline-start: 0;
--utrecht-page-content-padding-inline-end: 0;

/* TEMP VOORBEELD SCALE */
--voorbeeld-space-relation-onbemind: var(--voorbeeld-space-row-horse);
--voorbeeld-space-relation-onbekenden: var(--voorbeeld-space-row-pig);
--voorbeeld-space-relation-bekenden: var(--voorbeeld-space-row-cat);
--voorbeeld-space-relation-vrienden: var(--voorbeeld-space-row-rat);
--voorbeeld-space-relation-besties: var(--voorbeeld-space-row-snail);
--voorbeeld-space-relation-kind: 0px;
--voorbeeld-space-row-giraffe: 160px;
--voorbeeld-space-row-elephant: 96px;
--voorbeeld-space-row-horse: 64px;
--voorbeeld-space-row-tiger: 48px;
--voorbeeld-space-row-pig: 32px;
--voorbeeld-space-row-dog: 28px;
--voorbeeld-space-row-cat: 24px;
--voorbeeld-space-row-rabbit: 20px;
--voorbeeld-space-row-rat: 16px;
--voorbeeld-space-row-mouse: 12px;
--voorbeeld-space-row-snail: 8px;
--voorbeeld-space-row-beetle: 4px;
--voorbeeld-space-row-ant: 2px;
--voorbeeld-space-row-flea: 1px;
--voorbeeld-space-column-giraffe: 160px;
--voorbeeld-space-column-elephant: 96px;
--voorbeeld-space-column-horse: 64px;
--voorbeeld-space-column-tiger: 48px;
--voorbeeld-space-column-pig: 32px;
--voorbeeld-space-column-dog: 28px;
--voorbeeld-space-column-cat: 24px;
--voorbeeld-space-column-rabbit: 20px;
--voorbeeld-space-column-rat: 16px;
--voorbeeld-space-column-mouse: 12px;
--voorbeeld-space-column-snail: 8px;
--voorbeeld-space-column-beetle: 4px;
--voorbeeld-space-column-ant: 2px;
--voorbeeld-space-column-flea: 1px;
--voorbeeld-space-text-dog: 24px;
--voorbeeld-space-text-cat: 16px;
--voorbeeld-space-text-rabbit: 14px;
--voorbeeld-space-text-rat: 12px;
--voorbeeld-space-text-mouse: 8px;
--voorbeeld-space-text-snail: 6px;
--voorbeeld-space-text-beetle: 4px;
--voorbeeld-space-text-ant: 2px;
--voorbeeld-space-text-flea: 1px;
--voorbeeld-space-block-pig: 64px;
--voorbeeld-space-block-dog: 48px;
--voorbeeld-space-block-cat: 32px;
--voorbeeld-space-block-rabbit: 24px;
--voorbeeld-space-block-rat: 20px;
--voorbeeld-space-block-mouse: 16px;
--voorbeeld-space-block-snail: 12px;
--voorbeeld-space-block-beetle: 8px;
--voorbeeld-space-block-ant: 4px;
--voorbeeld-space-block-flea: 2px;
--voorbeeld-space-inline-pig: 48px;
--voorbeeld-space-inline-dog: 32px;
--voorbeeld-space-inline-cat: 28px;
--voorbeeld-space-inline-rabbit: 24px;
--voorbeeld-space-inline-rat: 20px;
--voorbeeld-space-inline-mouse: 16px;
--voorbeeld-space-inline-snail: 12px;
--voorbeeld-space-inline-beetle: 8px;
--voorbeeld-space-inline-ant: 4px;
--voorbeeld-space-inline-flea: 2px;
}

.utrecht-theme {
--utrecht-space-around: 1.5;
--todo-page-header-content-max-inline-size: calc(var(--utrecht-article-max-inline-size) * 1.5);
--todo-page-header-padding-inline-start: var(--voorbeeld-space-inline-mouse);
--todo-page-header-padding-inline-end: var(--voorbeeld-space-inline-mouse);
--voorbeeld-space-inline-mouse: 16px;
}

.denhaag-header__logo {
block-size: 64px;
inline-size: 180px;

}

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

.voorbeeld-back-link {
align-items: center;
column-gap: 8px;
Expand Down
Loading
Loading