Skip to content
Merged
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
38 changes: 24 additions & 14 deletions src-docs/src/views/emotion/canopy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
mergeDeep,
useEuiTheme,
withEuiTheme,
WithEuiThemeProps,
EuiThemeProvider,
computed,
euiThemeDefault,
Expand All @@ -34,13 +35,13 @@ import {
} from '../../../../src/services';

const View = () => {
const [theme, colorMode] = useEuiTheme();
const { euiTheme, colorMode } = useEuiTheme();
return (
<div css={{ display: 'flex' }}>
<div>
{colorMode}
<pre>
<code>{JSON.stringify(theme, null, 2)}</code>
<code>{JSON.stringify(euiTheme, null, 2)}</code>
</pre>
</div>
<div>
Expand All @@ -49,23 +50,23 @@ const View = () => {
aria-hidden="true"
type="stopFilled"
size="xxl"
css={{ color: theme.colors.euiColorPrimary }}
css={{ color: euiTheme.colors.euiColorPrimary }}
/>
</h3>
<h3>
<EuiIcon
aria-hidden="true"
type="stopFilled"
size="xxl"
css={{ color: theme.colors.euiColorSecondary }}
css={{ color: euiTheme.colors.euiColorSecondary }}
/>
</h3>
<h3>
<EuiIcon
aria-hidden="true"
type="stopFilled"
size="xxl"
css={{ color: theme.colors.euiTextColor }}
css={{ color: euiTheme.colors.euiTextColor }}
/>
</h3>
</div>
Expand Down Expand Up @@ -116,22 +117,28 @@ const View2 = () => {
);
};

interface BlockProps extends WithEuiThemeProps {
size?: 'xxl' | 'xl';
}
// eslint-disable-next-line react/prefer-stateless-function
class Block extends React.Component<any> {
class Block extends React.Component<BlockProps> {
render() {
const { theme, ...props } = this.props;
// TODO: TS autocomplete not working
const {
theme: { euiTheme },
size = 'xxl',
...props
} = this.props;
const blockStyle = css`
color: ${theme.theme.colors.euiColorPrimary};
border-radius: ${theme.theme.borders.euiBorderRadiusSmall};
border: ${theme.theme.borders.euiBorderEditable};
color: ${euiTheme.colors.euiColorPrimary};
border-radius: ${euiTheme.borders.euiBorderRadiusSmall};
border: ${euiTheme.borders.euiBorderEditable};
`;
return (
<div {...props}>
<EuiIcon
aria-hidden="true"
type="stopFilled"
size="xxl"
size={size}
css={blockStyle}
/>
</div>
Expand Down Expand Up @@ -217,7 +224,10 @@ export default () => {

const Extend = () => {
// Generic type (ExtensionsComputed) necessary if accessing extensions/custom properties
const [{ colors, custom }, colorMode] = useEuiTheme<ExtensionsComputed>();
const {
euiTheme: { colors, custom },
colorMode,
} = useEuiTheme<ExtensionsComputed>();
return (
<div css={{ display: 'flex' }}>
<div>
Expand Down Expand Up @@ -286,7 +296,7 @@ export default () => {
<em>Inverse colorMode</em>
<View3 />
<em>withEuiTheme</em>
<BlockWithTheme />
<BlockWithTheme size="xxl" />
</EuiThemeProvider>
</EuiThemeProvider>
<EuiSpacer />
Expand Down
10 changes: 5 additions & 5 deletions src-docs/src/views/theme/computed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ import { EuiText } from '../../../../src/components/text';
import { EuiThemeProvider, useEuiTheme } from '../../../../src/services';

const Box: FunctionComponent<{ children: ReactNode }> = ({ children }) => {
const [theme] = useEuiTheme();
const { euiTheme } = useEuiTheme();

return (
<EuiText
css={{
background: theme.colors.euiFocusBackgroundColor,
padding: theme.sizes.euiSizeXL,
color: theme.colors.euiColorPrimaryText,
background: euiTheme.colors.euiFocusBackgroundColor,
padding: euiTheme.sizes.euiSizeXL,
color: euiTheme.colors.euiColorPrimaryText,
}}>
<p>
<EuiIcon type="stopFilled" color={theme.colors.euiColorPrimary} />{' '}
<EuiIcon type="stopFilled" color={euiTheme.colors.euiColorPrimary} />{' '}
{children}
</p>
</EuiText>
Expand Down
8 changes: 4 additions & 4 deletions src-docs/src/views/theme/consuming.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ import { EuiIcon } from '../../../../src/components/icon';
import { useEuiTheme } from '../../../../src/services';

export default () => {
const [theme] = useEuiTheme();
const { euiTheme } = useEuiTheme();
return (
<div>
<p>
<EuiIcon
type="stopFilled"
size="xxl"
css={{ color: theme.colors.euiColorPrimary }}
css={{ color: euiTheme.colors.euiColorPrimary }}
/>{' '}
This primary color will adjust based on the light or dark theme value
</p>
<EuiSpacer />
<div
css={{
background: theme.colors.euiColorLightShade,
padding: theme.sizes.euiSizeXL,
background: euiTheme.colors.euiColorLightShade,
padding: euiTheme.sizes.euiSizeXL,
}}>
<p>
The padding of this box is passed as a raw unit translated to pixels
Expand Down
10 changes: 5 additions & 5 deletions src-docs/src/views/theme/consuming_hoc.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React from 'react';
import { css } from '@emotion/react';
import { withEuiTheme } from '../../../../src/services';
import { withEuiTheme, WithEuiThemeProps } from '../../../../src/services';
import { EuiIcon } from '../../../../src/components/icon';

// eslint-disable-next-line react/prefer-stateless-function
class Block extends React.Component<any> {
class Block extends React.Component<WithEuiThemeProps> {
render() {
const { theme } = this.props;

const divStyle = css`
background: ${theme.theme.colors.euiColorLightShade};
background: ${theme.euiTheme.colors.euiColorLightShade};
// This way of providing sizing values doesn't output correctly
padding: ${theme.theme.sizes.euiSizeXL};
border-radius: ${theme.theme.borders.euiBorderRadius};
padding: ${theme.euiTheme.sizes.euiSizeXL};
border-radius: ${theme.euiTheme.borders.euiBorderRadius};
`;

return (
Expand Down
24 changes: 13 additions & 11 deletions src-docs/src/views/theme/create_computed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ import {
useEuiTheme,
} from '../../../../src/services';

interface ThemeExtensions {
colors: {
customColorPrimary: string;
customColorPrimaryHighlight: string;
customColorPrimaryText: string;
};
}

const Box: FunctionComponent<{ children: ReactNode }> = ({ children }) => {
const [theme] = useEuiTheme();
const { euiTheme } = useEuiTheme<ThemeExtensions>();

return (
<EuiText
css={{
// @ts-ignore Needs to be fixed in types
background: theme.colors.customColorPrimaryHighlight,
padding: theme.sizes.euiSizeXL,
// @ts-ignore Needs to be fixed in types
color: theme.colors.customColorPrimaryText,
background: euiTheme.colors.customColorPrimaryHighlight,
padding: euiTheme.sizes.euiSizeXL,
color: euiTheme.colors.customColorPrimaryText,
}}>
<p>
<EuiIcon
type="stopFilled"
// @ts-ignore Needs to be fixed in types
color={theme.colors.customColorPrimary}
/>{' '}
<EuiIcon type="stopFilled" color={euiTheme.colors.customColorPrimary} />{' '}
{children}
</p>
</EuiText>
Expand Down
8 changes: 4 additions & 4 deletions src-docs/src/views/theme/inverse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { EuiSpacer } from '../../../../src/components/spacer';
import { EuiThemeProvider, useEuiTheme } from '../../../../src/services';

const Box: FunctionComponent<{ children: ReactNode }> = ({ children }) => {
const [theme] = useEuiTheme();
const { euiTheme } = useEuiTheme();

return (
<div
css={{
background: theme.colors.euiColorLightShade,
padding: theme.sizes.euiSizeXL,
color: theme.colors.euiTextColor,
background: euiTheme.colors.euiColorLightShade,
padding: euiTheme.sizes.euiSizeXL,
color: euiTheme.colors.euiTextColor,
}}>
<p>{children}</p>
</div>
Expand Down
6 changes: 3 additions & 3 deletions src-docs/src/views/theme/override_simple.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { EuiCode } from '../../../../src/components/code';
import { EuiThemeProvider, useEuiTheme } from '../../../../src/services';

const Box: FunctionComponent<{ children: ReactNode }> = ({ children }) => {
const [theme] = useEuiTheme();
const { euiTheme } = useEuiTheme();

return (
<div
css={{
background: theme.colors.euiColorLightShade,
padding: theme.sizes.euiSizeXL,
background: euiTheme.colors.euiColorLightShade,
padding: euiTheme.sizes.euiSizeXL,
}}>
<p>{children}</p>
</div>
Expand Down
31 changes: 26 additions & 5 deletions src-docs/src/views/theme/theme_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,31 @@ export const ThemeExample = {
<>
<p>
Using the react hook <strong>useEuiTheme()</strong> makes it very
easy to consume the EUI static variables like colors and sizing. It
will also automatically update based on the currently used theme.
easy to consume the EUI static and computed variables like colors
and sizing. It simply passes back an object of the current theme
which includes
</p>
<ul>
<li>
<EuiCode language="ts">euiTheme: EuiThemeComputed</EuiCode> All
the calculated keys including any modifications
</li>
<li>
<EuiCode language="ts">colorMode: EuiThemeColorMode</EuiCode>{' '}
Simply {"'light'"} or {"'dark'"}
</li>
<li>
<EuiCode language="ts">
modifications: EuiThemeModifications
</EuiCode>{' '}
Only the modification keys
</li>
</ul>
<p>
You&apos;ll want to pass these theme variables via the{' '}
<EuiCode>css</EuiCode> property to take advantage of Emotion&apos;s
compilation.
When consuming the theme&apos;s keys like{' '}
<EuiCode>euiTheme.colors.primary</EuiCode>, you&apos;ll want to pass
them via the <EuiCode>css</EuiCode> property to take advantage of
Emotion&apos;s compilation.
</p>
</>
),
Expand Down Expand Up @@ -217,6 +235,9 @@ export const ThemeExample = {
specific theme variables. Instead, you should append custom keys to
the theme.
</p>
<p>
<em>TODO: Indicate type support for custom keys.</em>
</p>
</>
),
demo: <CreateComputed />,
Expand Down
1 change: 1 addition & 0 deletions src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export {
EuiColorModeContext,
useEuiTheme,
withEuiTheme,
WithEuiThemeProps,
EuiThemeProvider,
buildTheme,
computed,
Expand Down
4 changes: 2 additions & 2 deletions src/services/theme/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ All three props are optional. The default values for EUI will be used in the eve
A custom React hook that returns the computed theme. This hook is little more than a wrapper around the `useContext` hook, accessing three of the top-level providers: computed theme, color mode, and modifications.

```js
const [theme, colorMode, modifications] = useEuiTheme();
const {euiTheme, colorMode, modifications} = useEuiTheme();
```

The `theme` variable has TypeScript support, which will result in IDE autocomplete availability.
The `euiTheme` variable has TypeScript support, which will result in IDE autocomplete availability.

### WithEuiTheme
A higher-order-component that wraps `useEuiTheme` for React class components.
Expand Down
48 changes: 25 additions & 23 deletions src/services/theme/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,43 +30,45 @@ import {
EuiThemeComputed,
} from './types';

export const useEuiTheme = <T extends {}>(): [
EuiThemeComputed<T>,
EuiThemeColorMode,
EuiThemeModifications<T>
] => {
export const useEuiTheme = <T extends {} = {}>(): {
euiTheme: EuiThemeComputed<T>;
colorMode: EuiThemeColorMode;
modifications: EuiThemeModifications<T>;
} => {
const theme = useContext(EuiThemeContext);
const modifications = useContext(EuiModificationsContext);
const colorMode = useContext(EuiColorModeContext);
const modifications = useContext(EuiModificationsContext);

return [
theme as EuiThemeComputed<T>,
return {
euiTheme: theme as EuiThemeComputed<T>,
colorMode,
modifications as EuiThemeModifications<T>,
];
modifications: modifications as EuiThemeModifications<T>,
};
};

export const withEuiTheme = <T extends {}, U extends {}>(
Component: React.ComponentType<
T & {
theme: {
theme: EuiThemeComputed<U>;
colorMode: EuiThemeColorMode;
};
}
>
export interface WithEuiThemeProps<P = {}> {
theme: {
euiTheme: EuiThemeComputed<P>;
colorMode: EuiThemeColorMode;
};
}
export const withEuiTheme = <T extends {} = {}, U extends {} = {}>(
Component: React.ComponentType<T & WithEuiThemeProps<U>>
) => {
const componentName = Component.displayName || Component.name || 'Component';
const Render = (props: T, ref: React.Ref<T>) => {
const [theme, colorMode] = useEuiTheme<U>();
const Render = (
props: Omit<T, keyof WithEuiThemeProps<U>>,
ref: React.Ref<Omit<T, keyof WithEuiThemeProps<U>>>
) => {
const { euiTheme, colorMode } = useEuiTheme<U>();
return (
<Component
theme={{
theme,
euiTheme,
colorMode,
}}
ref={ref}
{...props}
{...(props as T)}
/>
);
};
Expand Down
Loading