diff --git a/code/addons/a11y/src/components/VisionSimulator.tsx b/code/addons/a11y/src/components/VisionSimulator.tsx index 2acc66b21c71..096230ee293d 100644 --- a/code/addons/a11y/src/components/VisionSimulator.tsx +++ b/code/addons/a11y/src/components/VisionSimulator.tsx @@ -1,14 +1,13 @@ import type { ReactNode } from 'react'; -import React, { useState } from 'react'; - +import React, { useState, useEffect } from 'react'; +import ReactDOMServer from 'react-dom/server'; import { IconButton, TooltipLinkList, WithTooltip } from 'storybook/internal/components'; import { Global, styled } from 'storybook/internal/theming'; - import { AccessibilityIcon } from '@storybook/icons'; - import { Filters } from './ColorFilters'; const iframeId = 'storybook-preview-iframe'; +const iframeContents = 'storybook-root'; interface Option { name: string; @@ -42,14 +41,6 @@ const getFilter = (filterName: string) => { return `url('#${filterName}')`; }; -const Hidden = styled.div(() => ({ - '&, & svg': { - position: 'absolute', - width: 0, - height: 0, - }, -})); - const ColorIcon = styled.span<{ filter: string }>( { background: 'linear-gradient(to right, #F44336, #FF9800, #FFEB3B, #8BC34A, #2196F3, #9C27B0)', @@ -121,19 +112,39 @@ const getColorList = (active: Filter, set: (i: Filter) => void): Link[] => [ }), ]; +const hiddenStyles = { + position: 'absolute', + width: '0', + height: '0', +}; + +const injectFilters = (iframeDocument: Document) => { + if (!iframeDocument.getElementById('color-filters')) { + const filtersContainer = iframeDocument.createElement('div'); + filtersContainer.id = 'color-filters'; + Object.assign(filtersContainer.style, hiddenStyles); + iframeDocument.body.appendChild(filtersContainer); + const filtersSvgString = ReactDOMServer.renderToStaticMarkup(); + filtersContainer.innerHTML = filtersSvgString; + } +}; + export const VisionSimulator = () => { const [filter, setFilter] = useState(null); + + useEffect(() => { + const iframe = document.getElementById(iframeId) as HTMLIFrameElement; + if (iframe && iframe.contentDocument) { + injectFilters(iframe.contentDocument); + const storyRoot = iframe.contentDocument.getElementById(iframeContents); + if (storyRoot) { + storyRoot.style.filter = filter ? getFilter(filter.name) : 'none'; + } + } + }, [filter]); + return ( <> - {filter && ( - - )} { @@ -150,9 +161,6 @@ export const VisionSimulator = () => { - - - ); };