Skip to content

Commit

Permalink
fix(ui): add light theme portal container for storybook + use with Se…
Browse files Browse the repository at this point in the history
…lect
  • Loading branch information
przemyslaw-wlodek committed May 3, 2024
1 parent 820bfe5 commit 5a79d30
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 35 deletions.
2 changes: 1 addition & 1 deletion packages/ui/src/design-system/decorators/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { page } from './page.decorator';
export * as Variants from './variants-table';
export { Section } from './page-section.component';
export { useDarkThemePortalContainer } from './page.hooks';
export { usePortalContainer } from './page.hooks';
export { UIStateTable } from './ui-state-table.component';
export { ColorSchemaTable } from './color-schema-table.component';
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@ interface Props {
export const PageProvider = ({
children,
}: Readonly<Props>): React.ReactElement => {
const [state, setState] = useState<HTMLElement>();
const [state, setState] = useState<{
lightThemePortalContainer?: HTMLElement;
darkThemePortalContainer?: HTMLElement;
}>({});

return (
<PageContext.Provider
value={{
portalContainer: state,
setPortalContainer: setState,
...state,
setPortalContainers: ({ lightTheme, darkTheme }): void => {
setState({
lightThemePortalContainer: lightTheme,
darkThemePortalContainer: darkTheme,
});
},
}}
>
{children}
Expand Down
17 changes: 11 additions & 6 deletions packages/ui/src/design-system/decorators/page.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,18 @@ export const Page = ({
title,
subtitle,
}: Readonly<PageProps>): JSX.Element => {
const container = useRef<HTMLDivElement>(null);
const { setPortalContainer } = usePageContext();
const lightThemeContainer = useRef<HTMLDivElement>(null);
const darkThemeContainer = useRef<HTMLDivElement>(null);
const { setPortalContainers } = usePageContext();

useEffect(() => {
if (container.current) {
setPortalContainer(container.current);
if (lightThemeContainer.current && darkThemeContainer.current) {
setPortalContainers({
lightTheme: lightThemeContainer.current,
darkTheme: darkThemeContainer.current,
});
}
}, [container.current]);
}, [lightThemeContainer.current, darkThemeContainer.current]);

return (
<ThemeProvider colorScheme={ThemeColorScheme.Light}>
Expand All @@ -52,8 +56,9 @@ export const Page = ({
{children}
</Grid>
</div>
<div id="light-theme-portal-container" ref={lightThemeContainer} />
<LocalThemeProvider colorScheme={ThemeColorScheme.Dark}>
<div id="dark-theme-portal-container" ref={container} />
<div id="dark-theme-portal-container" ref={darkThemeContainer} />
</LocalThemeProvider>
</ThemeProvider>
);
Expand Down
18 changes: 10 additions & 8 deletions packages/ui/src/design-system/decorators/page.context.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { createContext, useContext } from 'react';

interface PageContextValue {
portalContainer?: HTMLElement;
setPortalContainer: (container: Readonly<HTMLElement>) => void;
darkThemePortalContainer?: HTMLElement;
lightThemePortalContainer?: HTMLElement;
setPortalContainers: ({
lightTheme,
darkTheme,
}: Readonly<{ lightTheme: HTMLElement; darkTheme: HTMLElement }>) => void;
}

export const PageContext = createContext<PageContextValue>({
portalContainer: undefined,
setPortalContainer: () => false,
darkThemePortalContainer: undefined,
lightThemePortalContainer: undefined,
setPortalContainers: () => void 0,
});

export const usePageContext = (): PageContextValue => {
const context = useContext(PageContext);
return context;
};
export const usePageContext = (): PageContextValue => useContext(PageContext);
16 changes: 14 additions & 2 deletions packages/ui/src/design-system/decorators/page.hooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import { usePageContext } from './page.context';

export const useDarkThemePortalContainer = (): HTMLElement | undefined =>
usePageContext().portalContainer;
interface UsePortalContainerReturnType {
darkThemePortalContainer?: HTMLElement;
lightThemePortalContainer?: HTMLElement;
}

/**
* **Important**: This is for Storybook use only. In real app everything will be placed in context of a single
* ThemeProvider. It should be used with all components that create portals to fix LocalThemeProvider with dark theme
* and Interaction tests (without this approach your component may not be accessible using `canvas.getByTestId()`).
*/
export const usePortalContainer = (): UsePortalContainerReturnType => ({
darkThemePortalContainer: usePageContext().darkThemePortalContainer,
lightThemePortalContainer: usePageContext().lightThemePortalContainer,
});
27 changes: 12 additions & 15 deletions packages/ui/src/design-system/select/select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ import type { Meta } from '@storybook/react';
import capitalize from 'lodash/capitalize';

import { LocalThemeProvider, ThemeColorScheme } from '../../design-tokens';
import {
page,
Section,
useDarkThemePortalContainer,
Variants,
} from '../decorators';
import { page, Section, usePortalContainer, Variants } from '../decorators';
import { Divider } from '../divider';
import { Cell, Grid } from '../grid';

Expand Down Expand Up @@ -80,7 +75,8 @@ const SelectAlignment = (): JSX.Element => (
);

const SelectVariants = (): JSX.Element => {
const darkThemePortalContainer = useDarkThemePortalContainer();
const { darkThemePortalContainer, lightThemePortalContainer } =
usePortalContainer();
const renderedOptions = options.map(option => (
<Select.Item
key={option.value}
Expand Down Expand Up @@ -112,7 +108,7 @@ const SelectVariants = (): JSX.Element => {
portalContainer={
colorScheme === ThemeColorScheme.Dark
? darkThemePortalContainer
: undefined
: lightThemePortalContainer
}
>
{renderedOptions}
Expand All @@ -139,7 +135,7 @@ const SelectVariants = (): JSX.Element => {
portalContainer={
colorScheme === ThemeColorScheme.Dark
? darkThemePortalContainer
: undefined
: lightThemePortalContainer
}
>
{renderedOptions}
Expand All @@ -155,7 +151,8 @@ const SelectVariants = (): JSX.Element => {
};

const SelectRootVariants = (): JSX.Element => {
const darkThemePortalContainer = useDarkThemePortalContainer();
const { darkThemePortalContainer, lightThemePortalContainer } =
usePortalContainer();
const renderedOptions = options.map(option => (
<Select.Item
key={option.value}
Expand Down Expand Up @@ -193,7 +190,7 @@ const SelectRootVariants = (): JSX.Element => {
portalContainer={
colorScheme === ThemeColorScheme.Dark
? darkThemePortalContainer
: undefined
: lightThemePortalContainer
}
>
{renderedOptions}
Expand All @@ -210,7 +207,7 @@ const SelectRootVariants = (): JSX.Element => {
portalContainer={
colorScheme === ThemeColorScheme.Dark
? darkThemePortalContainer
: undefined
: lightThemePortalContainer
}
>
{renderedOptions}
Expand All @@ -226,7 +223,7 @@ const SelectRootVariants = (): JSX.Element => {
portalContainer={
colorScheme === ThemeColorScheme.Dark
? darkThemePortalContainer
: undefined
: lightThemePortalContainer
}
>
{renderedOptions}
Expand All @@ -243,7 +240,7 @@ const SelectRootVariants = (): JSX.Element => {
portalContainer={
colorScheme === ThemeColorScheme.Dark
? darkThemePortalContainer
: undefined
: lightThemePortalContainer
}
>
{renderedOptions}
Expand All @@ -260,7 +257,7 @@ const SelectRootVariants = (): JSX.Element => {
portalContainer={
colorScheme === ThemeColorScheme.Dark
? darkThemePortalContainer
: undefined
: lightThemePortalContainer
}
>
{renderedOptions}
Expand Down

0 comments on commit 5a79d30

Please sign in to comment.