;
+
+export function Default() {
+ return (
+
+
+ {icons.map((icon, i) => (
+
+
+
+ ))}
+
+
+ {icons.map((icon, i) => (
+
+
+
+ ))}
+
+
+ {emojis.map((emoji, i) => (
+
+ {emoji}
+
+ ))}
+
+
+ {emojis.map((emoji, i) => (
+
+ {emoji}
+
+ ))}
+
+
+ );
+}
+
+Default.story = {
+ name: 'default'
+};
diff --git a/src/IconWrapper/IconWrapper.tsx b/src/IconWrapper/IconWrapper.tsx
new file mode 100644
index 00000000..a4ddc8b4
--- /dev/null
+++ b/src/IconWrapper/IconWrapper.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import styled from 'styled-components';
+import { getDisabledFilterId } from '../common/ThemeProvider';
+import { CommonStyledProps } from '../types';
+
+type IconWrapperProps = {
+ disabled?: boolean;
+} & React.HTMLAttributes &
+ CommonStyledProps;
+
+const IconWrapper = styled.div`
+ ${({ theme, disabled }) => `
+ display: grid;
+ filter: ${
+ disabled ? `contrast(2) url(#${getDisabledFilterId(theme)})` : 'none'
+ };
+`}
+`;
+
+IconWrapper.displayName = 'IconWrapper';
+
+export { IconWrapper, IconWrapperProps };
diff --git a/src/common/React95Provider.tsx b/src/common/React95Provider.tsx
new file mode 100644
index 00000000..7b52a6a7
--- /dev/null
+++ b/src/common/React95Provider.tsx
@@ -0,0 +1,35 @@
+import React from 'react';
+
+type Props = {
+ children: React.ReactNode;
+};
+
+const UtilsElementContext = React.createContext(null);
+
+export function useUtilsElement() {
+ const utils = React.useContext(UtilsElementContext);
+
+ return utils;
+}
+
+export function React95Provider({ children }: Props) {
+ const [utils, setUtils] = React.useState(null);
+
+ React.useLayoutEffect(() => {
+ const filtersWrapper = document.createElement('react95-utils');
+ const div = document.createElement('div');
+ filtersWrapper.appendChild(div);
+ document.documentElement.appendChild(filtersWrapper);
+ setUtils(div);
+
+ return () => {
+ filtersWrapper.remove();
+ };
+ }, []);
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/common/ThemeProvider.tsx b/src/common/ThemeProvider.tsx
new file mode 100644
index 00000000..60d03dee
--- /dev/null
+++ b/src/common/ThemeProvider.tsx
@@ -0,0 +1,84 @@
+import React from 'react';
+import { ThemeProvider as SCThemeProvider } from 'styled-components';
+import { Theme } from '../types';
+import { useUtilsElement } from './React95Provider';
+
+type Props = React.ComponentProps & {
+ theme: Theme;
+};
+
+export function getDisabledFilterId(theme: Theme) {
+ return `disabled-filter--${theme.name}`;
+}
+export function ThemeProvider({ theme, ...otherProps }: Props) {
+ const utilsElement = useUtilsElement();
+
+ React.useLayoutEffect(() => {
+ if (utilsElement) {
+ const filterId = getDisabledFilterId(theme);
+ const filter = document.getElementById(filterId);
+ if (!filter) {
+ // const disabledFilter = `
+ //
+ //
+ //
+ //
+ //
+ //
+
+ // `;
+ const disabledFilter = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+ const svg = document.createElementNS(
+ 'http://www.w3.org/2000/svg',
+ 'svg'
+ );
+ svg.innerHTML = disabledFilter;
+ utilsElement.appendChild(svg);
+ }
+ }
+ }, [theme, utilsElement]);
+ return ;
+}
diff --git a/src/index.ts b/src/index.ts
index 4e6b18a0..3a4e947e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -15,6 +15,7 @@ export * from './Frame/Frame';
export * from './GroupBox/GroupBox';
export * from './Handle/Handle';
export * from './Hourglass/Hourglass';
+export * from './IconWrapper/IconWrapper';
export * from './MenuList/MenuList';
export * from './Monitor/Monitor';
export * from './NumberInput/NumberInput';
@@ -45,3 +46,8 @@ export * from './legacy/Panel';
export * from './legacy/Progress';
export * from './legacy/TextField';
export * from './legacy/Tree';
+
+/* other */
+
+export * from './common/ThemeProvider';
+export * from './common/React95Provider';