Skip to content

Commit

Permalink
[Emotion] Convert euiFocusRing() mixin (elastic#5855)
Browse files Browse the repository at this point in the history
* Commented out some unused (yet) properties and updated the Focus docs section
* Make `focus` global token required
* Updated ThemeExamples code snippets to scroll horizontally

* [EuiSplitPanel] Fix border-radius of nested split panels
# Conflicts:
#	src/global_styling/mixins/index.ts
  • Loading branch information
cchaos committed May 3, 2022
1 parent 099f6bc commit d47f414
Show file tree
Hide file tree
Showing 18 changed files with 493 additions and 234 deletions.
47 changes: 2 additions & 45 deletions src-docs/src/views/accessibility/accessibility_example.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import { css } from '@emotion/react';

import { GuideSectionTypes } from '../../components';

Expand All @@ -11,16 +10,13 @@ import {
EuiScreenReaderLive,
EuiScreenReaderOnly,
EuiSpacer,
euiScreenReaderOnlyStyles,
EuiText,
} from '../../../../src';

import { ThemeExample } from '../theme/_components/_theme_example';

import ScreenReaderLive from './screen_reader_live';
import ScreenReaderOnly from './screen_reader';
import ScreenReaderFocus from './screen_reader_focus';
import SkipLink from './skip_link';
import StylesHelpers from './styles_helpers';

const screenReaderLiveSource = require('!!raw-loader!./screen_reader_live');
const screenReaderOnlySource = require('!!raw-loader!./screen_reader');
Expand Down Expand Up @@ -193,46 +189,7 @@ export const AccessibilityExample = {
{
title: 'Styles helpers',
wrapText: false,
text: (
<>
<ThemeExample
title={<code>.euiScreenReaderOnly</code>}
description={
<p>
This utility class allows you to apply the screen reader only
CSS styles directly to your component.
</p>
}
example={
<EuiText size="s">
<p>The next paragraph is hidden except for screen readers.</p>
<p className="euiScreenReaderOnly">
I am hidden except for screen readers
</p>
</EuiText>
}
snippet={'<p className="euiScreenReaderOnly" />'}
/>
<ThemeExample
title={<code>euiScreenReaderOnlyStyles()</code>}
description={
<p>
This function allows you to apply the screen reader only CSS
styles directly to your component.
</p>
}
example={
<EuiText size="s">
<p>The next paragraph is hidden except for screen readers.</p>
<p css={css(euiScreenReaderOnlyStyles())}>
I am hidden except for screen readers
</p>
</EuiText>
}
snippet={'<p css={css(euiScreenReaderOnlyStyles())} />'}
/>
</>
),
text: <StylesHelpers />,
},
],
};
97 changes: 97 additions & 0 deletions src-docs/src/views/accessibility/styles_helpers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { css } from '@emotion/react';
import React from 'react';

import {
EuiCode,
euiScreenReaderOnlyStyles,
EuiText,
useEuiFocusRing,
} from '../../../../src';
import { useEuiTheme } from '../../../../src/services';
import { ThemeExample } from '../theme/_components/_theme_example';

export default () => {
const { euiTheme } = useEuiTheme();

return (
<>
<ThemeExample
title={<code>.euiScreenReaderOnly</code>}
description={
<p>
This utility class allows you to apply the screen reader only CSS
styles directly to your component.
</p>
}
example={
<EuiText size="s">
<p>The next paragraph is hidden except for screen readers.</p>
<p className="euiScreenReaderOnly">
I am hidden except for screen readers
</p>
</EuiText>
}
snippet={'<p className="euiScreenReaderOnly" />'}
/>
<ThemeExample
title={<code>euiScreenReaderOnlyStyles()</code>}
description={
<p>
This function allows you to apply the screen reader only CSS styles
directly to your component.
</p>
}
example={
<EuiText size="s">
<p>The next paragraph is hidden except for screen readers.</p>
<p css={css(euiScreenReaderOnlyStyles())}>
I am hidden except for screen readers
</p>
</EuiText>
}
snippet={'<p css={css(euiScreenReaderOnlyStyles())} />'}
/>
<ThemeExample
title={<code>useEuiFocusRing(offset?, color?)</code>}
description={
<p>
By default, all interactable elements will inherit the{' '}
<EuiCode>outline</EuiCode> property from the reset file. However,
some instances require adjustment to the <EuiCode>offset</EuiCode>{' '}
and <EuiCode>color</EuiCode> of this outline. This helper function
allows that customization of the focus outline.
</p>
}
props={`offset: 'inset' | 'outset' | 'center' | CSSProperties['outlineOffset'];
color: CSSProperties['outlineColor'];`}
example={
<EuiText size="s">
<p>
<button>
I am an unstyled <EuiCode>button</EuiCode> with inherited
outline
</button>
</p>
<p>
<button
css={css`
&:focus {
${useEuiFocusRing('outset', euiTheme.colors.primary)}
}
`}
>
I am an unstyled <EuiCode>button</EuiCode> with an{' '}
<EuiCode>outset, primary</EuiCode> outline
</button>
</p>
</EuiText>
}
snippetLanguage="emotion"
snippet={`&:focus {
\${useEuiFocusRing('outset', euiTheme.colors.primary)}
}`}
/>
</>
);
};
23 changes: 19 additions & 4 deletions src-docs/src/views/theme/_components/_theme_example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type ThemeExample = {
examplePanel?: _EuiSplitPanelInnerProps;
snippet?: GuideSectionExample['tabContent'];
snippetLanguage?: EuiCodeBlockProps['language'];
props?: ReactNode;
provider?: {
property?: string;
type?: string;
Expand All @@ -39,6 +40,7 @@ export const ThemeExample: FunctionComponent<ThemeExample> = ({
examplePanel,
snippet,
snippetLanguage = 'jsx',
props,
}) => {
const { euiTheme } = useEuiTheme();
const finalSnippet =
Expand Down Expand Up @@ -71,25 +73,38 @@ export const ThemeExample: FunctionComponent<ThemeExample> = ({
<EuiText size="s" grow={false}>
{description}
</EuiText>
{props && (
<>
<EuiSpacer />
<EuiCodeBlock
transparentBackground
paddingSize="none"
language="ts"
>
{props}
</EuiCodeBlock>
</>
)}
</EuiSplitPanel.Inner>

{(example || snippet) && (
<EuiSplitPanel.Inner>
<EuiSplitPanel.Inner style={{ overflow: 'hidden' }}>
<EuiSplitPanel.Outer
direction="column"
hasBorder={true}
hasShadow={false}
style={{ overflow: 'hidden' }}
>
{example && (
<EuiSplitPanel.Inner {...examplePanel}>
{example}
</EuiSplitPanel.Inner>
)}
<EuiSplitPanel.Inner color="subdued">
<EuiSplitPanel.Inner paddingSize="none" color="subdued">
{finalSnippet && (
<EuiCodeBlock
whiteSpace="pre"
isCopyable={true}
paddingSize="none"
paddingSize="m"
transparentBackground={true}
language={
snippetLanguage === 'emotion' ? 'jsx' : snippetLanguage
Expand Down
106 changes: 42 additions & 64 deletions src-docs/src/views/theme/customizing/_focus.js
Original file line number Diff line number Diff line change
@@ -1,95 +1,73 @@
import React from 'react';
import { css } from '@emotion/react';

import {
useEuiTheme,
EuiTitle,
EuiSpacer,
EuiColorPickerSwatch,
EuiFlexItem,
EuiCodeBlock,
EuiText,
EuiPanel,
} from '../../../../../src';

import { ThemeSection } from '../_theme_section';
import { getPropsFromComponent } from '../../../services/props/get_props';
import { useDebouncedUpdate } from '../hooks';

import { ThemeValue } from './_values';

import { getPropsFromComponent, EuiThemeFocus } from '../_props';
import { EuiThemeFocus } from '../_props';

export default ({ onThemeUpdate }) => {
const { euiTheme } = useEuiTheme();
const focus = euiTheme.focus;
const focusProps = getPropsFromComponent(EuiThemeFocus);

const updateFocus = (property, value) => {
onThemeUpdate({
focus: {
[property]: value,
},
});
};
const [focusClone, updateFocus] = useDebouncedUpdate({
property: 'focus',
value: focus,
onUpdate: onThemeUpdate,
});

const style = css`
width: ${euiTheme.size.xl};
height: ${euiTheme.size.xl};
border-radius: ${euiTheme.border.radius.small};
`;
const focusProps = getPropsFromComponent(EuiThemeFocus);

return (
<div>
<EuiTitle>
<EuiText>
<h2>Focus</h2>
</EuiTitle>

<EuiSpacer />

<ThemeSection
code="_EuiThemeFocus"
description={
</EuiText>
<EuiSpacer size="xl" />
<EuiPanel color="subdued">
<EuiTitle size="xs">
<h3>
<code>_EuiThemeFocus</code>
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText size="s" grow={false}>
<p>
These are general properties that apply to the focus state of
interactable components. Some components have their own specific
implementation, but most use these variables.
</p>
}
themeValues={Object.keys(focus).map((prop) => {
const isColor = prop.toLowerCase().includes('color');
if (prop === 'outline') {
return (
<EuiFlexItem key={prop}>
<ThemeValue
property="focus"
type={focusProps[prop]}
name={prop}
buttonStyle={[style, focus[prop]]}
/>
<EuiSpacer size="xs" />
<EuiCodeBlock paddingSize="s" language="css">{`${JSON.stringify(
focus[prop]
).replace(/[{}"]/g, '')};`}</EuiCodeBlock>
</EuiFlexItem>
);
}
</EuiText>

<EuiSpacer />

{Object.keys(focusProps).map((prop) => {
return (
<EuiFlexItem key={prop}>
<ThemeValue
property="focus"
name={prop}
type={focusProps[prop]}
value={focus[prop]}
onUpdate={(value) => updateFocus(prop, value)}
example={
isColor ? (
<EuiColorPickerSwatch color={focus[prop]} />
) : undefined
}
colorProps={
isColor ? { showAlpha: true, format: 'rgba' } : undefined
}
/>
</EuiFlexItem>
<ThemeValue
key={prop}
property="focus"
type={focusProps[prop]}
name={prop}
value={focusClone[prop]}
onUpdate={(value) => updateFocus(prop, value)}
forceUpdateType="string"
example={null}
numberProps={{
style: { width: 140 },
}}
/>
);
})}
/>
</EuiPanel>
</div>
);
};
Loading

0 comments on commit d47f414

Please sign in to comment.