[9.0] [Storybook] Use native theme switcher (#215443) (#215630)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[Storybook] Use native theme switcher
(#215443)](https://github.com/elastic/kibana/pull/215443)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Sergi
Romeu","email":"sergi.romeu@elastic.co"},"sourceCommit":{"committedDate":"2025-03-24T08:54:15Z","message":"[Storybook]
Use native theme switcher (#215443)\n\n## Summary\n\nCloses
#213294\n\nThis PR replaces the custom theme switcher in favor of the
native\ntoolbar customization SB has integrated.\n\nAlso removed
`@storybook/icons` which was only used in the theme\nswitcher
component.\n\n## How to test\n1. Run `yarn storybook <plugin>`\n2. You
should be able to change between themes on the
toolbar.","sha":"965a69d9fbf47b5a7054c0ed8eeb60687e6707bc","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Feature:Storybook","backport:prev-minor","ci:build-storybooks","Team:obs-ux-infra_services","v9.1.0"],"title":"[Storybook]
Use native theme
switcher","number":215443,"url":"https://github.com/elastic/kibana/pull/215443","mergeCommit":{"message":"[Storybook]
Use native theme switcher (#215443)\n\n## Summary\n\nCloses
#213294\n\nThis PR replaces the custom theme switcher in favor of the
native\ntoolbar customization SB has integrated.\n\nAlso removed
`@storybook/icons` which was only used in the theme\nswitcher
component.\n\n## How to test\n1. Run `yarn storybook <plugin>`\n2. You
should be able to change between themes on the
toolbar.","sha":"965a69d9fbf47b5a7054c0ed8eeb60687e6707bc"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/215443","number":215443,"mergeCommit":{"message":"[Storybook]
Use native theme switcher (#215443)\n\n## Summary\n\nCloses
#213294\n\nThis PR replaces the custom theme switcher in favor of the
native\ntoolbar customization SB has integrated.\n\nAlso removed
`@storybook/icons` which was only used in the theme\nswitcher
component.\n\n## How to test\n1. Run `yarn storybook <plugin>`\n2. You
should be able to change between themes on the
toolbar.","sha":"965a69d9fbf47b5a7054c0ed8eeb60687e6707bc"}}]}]
BACKPORT-->

Co-authored-by: Sergi Romeu <sergi.romeu@elastic.co>
This commit is contained in:
Kibana Machine 2025-03-24 12:42:32 +01:00 committed by GitHub
parent d8d718b6fd
commit 3de7305e4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 42 additions and 127 deletions

View file

@ -1553,7 +1553,6 @@
"@storybook/components": "^8.6.3",
"@storybook/core-events": "^8.6.3",
"@storybook/core-server": "^8.6.3",
"@storybook/icons": "^1.3.2",
"@storybook/manager-api": "^8.6.3",
"@storybook/preview-api": "^8.6.3",
"@storybook/react": "^8.6.3",

View file

@ -10,13 +10,53 @@
import type { Preview } from '@storybook/react';
import * as jest from 'jest-mock';
import { decorators } from './decorators';
import {
AMSTERDAM_DARK,
AMSTERDAM_LIGHT,
BOREALIS_DARK,
BOREALIS_LIGHT,
DEFAULT_THEME,
THEME_TITLES,
} from './themes';
// @ts-expect-error
window.jest = jest;
const preview: Preview = {
decorators,
initialGlobals: { euiTheme: 'v8.light' },
initialGlobals: { euiTheme: DEFAULT_THEME },
globalTypes: {
euiTheme: {
description: 'Change the EUI theme',
toolbar: {
title: 'Theme',
icon: 'paintbrush',
dynamicTitle: true,
items: [
{
value: BOREALIS_LIGHT,
icon: 'hearthollow',
title: THEME_TITLES[BOREALIS_LIGHT],
},
{
value: BOREALIS_DARK,
icon: 'heart',
title: THEME_TITLES[BOREALIS_DARK],
},
{
value: AMSTERDAM_LIGHT,
icon: 'hearthollow',
title: THEME_TITLES[AMSTERDAM_LIGHT],
},
{
value: AMSTERDAM_DARK,
icon: 'heart',
title: THEME_TITLES[AMSTERDAM_DARK],
},
],
},
},
},
};
// eslint-disable-next-line import/no-default-export

View file

@ -9,7 +9,6 @@
import { addons } from '@storybook/manager-api';
import { create } from '@storybook/theming';
import { registerThemeSwitcherAddon } from './register_theme_switcher_addon';
// This configures the "Manager", or main outer view of Storybook. It is an
// addon that's loaded by the `managerEntries` part of the preset in ../preset.js.
@ -25,5 +24,3 @@ addons.setConfig({
panelPosition: 'bottom',
showToolbar: true,
});
registerThemeSwitcherAddon();

View file

@ -1,39 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { addons, types } from '@storybook/manager-api';
import { ThemeSwitcher } from './theme_switcher';
export const THEME_SWITCHER_ADDON_ID = 'kibana/eui-theme-switcher';
export function registerThemeSwitcherAddon() {
addons.register(THEME_SWITCHER_ADDON_ID, (api) => {
const channel = api.getChannel();
channel?.on('globalsUpdated', ({ globals }) => {
const previewFrame = document.getElementById(
'storybook-preview-iframe'
) as HTMLIFrameElement | null;
const stylesheet = previewFrame?.contentDocument?.getElementById(
'eui-theme-css'
) as HTMLLinkElement | null;
if (stylesheet && globals.euiTheme) {
stylesheet.href = `kbn-ui-shared-deps-npm.${globals.euiTheme}.css`;
}
});
addons.add(THEME_SWITCHER_ADDON_ID, {
title: 'EUI Theme Switcher',
type: types.TOOL,
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
render: ThemeSwitcher,
});
});
}

View file

@ -1,82 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { useCallback, useEffect } from 'react';
import { IconButton, TooltipLinkList, WithTooltip } from '@storybook/components';
import { useGlobals } from '@storybook/manager-api';
import { HeartIcon, HeartHollowIcon } from '@storybook/icons';
import { DEFAULT_THEME, THEMES, THEME_TITLES } from './themes';
type PropsOf<T extends React.FC<any>> = T extends React.FC<infer P> ? P : never;
type ArrayItem<T extends any[]> = T extends Array<infer I> ? I : never;
type Link = ArrayItem<PropsOf<typeof TooltipLinkList>['links']>;
export function ThemeSwitcher() {
const [{ euiTheme: selectedTheme }, updateGlobals] = useGlobals();
const selectTheme = useCallback(
(themeId: string) => {
updateGlobals({ euiTheme: themeId });
},
[updateGlobals]
);
useEffect(() => {
if (!selectedTheme) {
selectTheme(DEFAULT_THEME);
}
}, [selectTheme, selectedTheme]);
return (
<WithTooltip
placement="top"
trigger="click"
tooltip={({ onHide }) => (
<ThemeSwitcherTooltip
onHide={onHide}
onChangeSelectedTheme={selectTheme}
selectedTheme={selectedTheme}
/>
)}
>
<IconButton key="eui-theme" title="Change the EUI theme">
{selectedTheme?.includes('dark') ? <HeartIcon /> : <HeartHollowIcon />}
</IconButton>
</WithTooltip>
);
}
const ThemeSwitcherTooltip = React.memo(
({
onHide,
onChangeSelectedTheme,
selectedTheme,
}: {
onHide: () => void;
onChangeSelectedTheme: (themeId: string) => void;
selectedTheme: string;
}) => {
const links = THEMES.map(
(theme): Link => ({
id: theme,
title: THEME_TITLES[theme],
onClick: (_event, item) => {
if (item.id != null && item.id !== selectedTheme) {
onChangeSelectedTheme(item.id);
}
onHide();
},
active: selectedTheme === theme,
})
);
return <TooltipLinkList links={links.flat()} />;
}
);

View file

@ -10154,7 +10154,7 @@
resolved "https://registry.yarnpkg.com/@storybook/global/-/global-5.0.0.tgz#b793d34b94f572c1d7d9e0f44fac4e0dbc9572ed"
integrity sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==
"@storybook/icons@^1.2.12", "@storybook/icons@^1.3.2":
"@storybook/icons@^1.2.12":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@storybook/icons/-/icons-1.3.2.tgz#e9b92c35ca789ff79f9d0b3848829dd6490ca628"
integrity sha512-t3xcbCKkPvqyef8urBM0j/nP6sKtnlRkVgC+8JTbTAZQjaTmOjes3byEgzs89p4B/K6cJsg9wLW2k3SknLtYJw==