From f2dca3e406886dd9ae3cbad059df32e4429d309d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= Date: Sun, 3 May 2020 12:46:23 +0200 Subject: [PATCH 01/15] feat(utils): make style helpers work with css prop --- src/styles/style-helpers.spec.js | 36 ++++++++--------- src/styles/style-helpers.ts | 68 +++++++++++++++++++++----------- 2 files changed, 62 insertions(+), 42 deletions(-) diff --git a/src/styles/style-helpers.spec.js b/src/styles/style-helpers.spec.js index 9d31973dc4..7bdae60a31 100644 --- a/src/styles/style-helpers.spec.js +++ b/src/styles/style-helpers.spec.js @@ -34,10 +34,10 @@ describe('Style helpers', () => { const { styles } = StyleHelpers.shadowSingle({ theme: light }); expect(styles).toMatchInlineSnapshot(` " - box-shadow: 0 0 0 1px rgba(12,15,20,0.02), - 0 0 1px 0 rgba(12,15,20,0.06), - 0 2px 2px 0 rgba(12,15,20,0.06); - " + box-shadow: 0 0 0 1px rgba(12,15,20,0.02), + 0 0 1px 0 rgba(12,15,20,0.06), + 0 2px 2px 0 rgba(12,15,20,0.06); + " `); }); }); @@ -47,10 +47,10 @@ describe('Style helpers', () => { const { styles } = StyleHelpers.shadowDouble({ theme: light }); expect(styles).toMatchInlineSnapshot(` " - box-shadow: 0 0 0 1px rgba(12,15,20,0.02), - 0 2px 2px 0 rgba(12,15,20,0.06), - 0 4px 4px 0 rgba(12,15,20,0.06); - " + box-shadow: 0 0 0 1px rgba(12,15,20,0.02), + 0 2px 2px 0 rgba(12,15,20,0.06), + 0 4px 4px 0 rgba(12,15,20,0.06); + " `); }); }); @@ -60,10 +60,10 @@ describe('Style helpers', () => { const { styles } = StyleHelpers.shadowTriple({ theme: light }); expect(styles).toMatchInlineSnapshot(` " - box-shadow: 0 0 0 1px rgba(12,15,20,0.02), - 0 4px 4px 0 rgba(12,15,20,0.06), - 0 8px 8px 0 rgba(12,15,20,0.06); - " + box-shadow: 0 0 0 1px rgba(12,15,20,0.02), + 0 4px 4px 0 rgba(12,15,20,0.06), + 0 8px 8px 0 rgba(12,15,20,0.06); + " `); }); }); @@ -230,13 +230,13 @@ describe('Style helpers', () => { const { styles } = StyleHelpers.focusOutline({ theme: light }); expect(styles).toMatchInlineSnapshot(` " - outline: 0; - box-shadow: 0 0 0 4px #AFD0FE; + outline: 0; + box-shadow: 0 0 0 4px #AFD0FE; - &::-moz-focus-inner { - border: 0; - } - " + &::-moz-focus-inner { + border: 0; + } + " `); }); }); diff --git a/src/styles/style-helpers.ts b/src/styles/style-helpers.ts index 73f4c0d89e..42bca2d559 100644 --- a/src/styles/style-helpers.ts +++ b/src/styles/style-helpers.ts @@ -17,7 +17,14 @@ import { css, SerializedStyles } from '@emotion/core'; import { transparentize } from 'polished'; import { Theme } from '@sumup/design-tokens'; -import { StyleProps } from './styled'; +type ThemeArgs = Theme | { theme: Theme }; + +function isTheme(args: ThemeArgs): args is Theme { + return (args as { theme: Theme }).theme === undefined; +} + +export const getTheme = (args: ThemeArgs): Theme => + isTheme(args) ? args : args.theme; export const shadowBorder = ( color: string, @@ -26,29 +33,39 @@ export const shadowBorder = ( box-shadow: 0px 0px 0px ${borderSize} ${color}; `; -export const shadowSingle = ({ theme }: StyleProps): SerializedStyles => css` - box-shadow: 0 0 0 1px ${transparentize(0.98, theme.colors.shadow)}, - 0 0 1px 0 ${transparentize(0.94, theme.colors.shadow)}, - 0 2px 2px 0 ${transparentize(0.94, theme.colors.shadow)}; -`; +export const shadowSingle = (args: ThemeArgs): SerializedStyles => { + const theme = getTheme(args); + return css` + box-shadow: 0 0 0 1px ${transparentize(0.98, theme.colors.shadow)}, + 0 0 1px 0 ${transparentize(0.94, theme.colors.shadow)}, + 0 2px 2px 0 ${transparentize(0.94, theme.colors.shadow)}; + `; +}; -export const shadowDouble = ({ theme }: StyleProps): SerializedStyles => css` - box-shadow: 0 0 0 1px ${transparentize(0.98, theme.colors.shadow)}, - 0 2px 2px 0 ${transparentize(0.94, theme.colors.shadow)}, - 0 4px 4px 0 ${transparentize(0.94, theme.colors.shadow)}; -`; +export const shadowDouble = (args: ThemeArgs): SerializedStyles => { + const theme = getTheme(args); + return css` + box-shadow: 0 0 0 1px ${transparentize(0.98, theme.colors.shadow)}, + 0 2px 2px 0 ${transparentize(0.94, theme.colors.shadow)}, + 0 4px 4px 0 ${transparentize(0.94, theme.colors.shadow)}; + `; +}; -export const shadowTriple = ({ theme }: StyleProps): SerializedStyles => css` - box-shadow: 0 0 0 1px ${transparentize(0.98, theme.colors.shadow)}, - 0 4px 4px 0 ${transparentize(0.94, theme.colors.shadow)}, - 0 8px 8px 0 ${transparentize(0.94, theme.colors.shadow)}; -`; +export const shadowTriple = (args: ThemeArgs): SerializedStyles => { + const theme = getTheme(args); + return css` + box-shadow: 0 0 0 1px ${transparentize(0.98, theme.colors.shadow)}, + 0 4px 4px 0 ${transparentize(0.94, theme.colors.shadow)}, + 0 8px 8px 0 ${transparentize(0.94, theme.colors.shadow)}; + `; +}; function createTypeHelper( type: T, size: keyof Theme['typography'][T] ) { - return ({ theme }: StyleProps): SerializedStyles => { + return (args: ThemeArgs): SerializedStyles => { + const theme = getTheme(args); const { fontSize, lineHeight } = (theme.typography[type][ size ] as unknown) as { @@ -90,14 +107,17 @@ export const disableVisually = (): SerializedStyles => css` /** * Visually communicates to the user that an element is focused. */ -export const focusOutline = ({ theme }: StyleProps): SerializedStyles => css` - outline: 0; - box-shadow: 0 0 0 4px ${theme.colors.p300}; +export const focusOutline = (args: ThemeArgs): SerializedStyles => { + const theme = getTheme(args); + return css` + outline: 0; + box-shadow: 0 0 0 4px ${theme.colors.p300}; - &::-moz-focus-inner { - border: 0; - } -`; + &::-moz-focus-inner { + border: 0; + } + `; +}; /** * A CSS hack to force an element to self-clear its floated children. From 96d1bc50d631e14fa9cbf332f53b7572c8df8c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= Date: Sun, 3 May 2020 13:00:16 +0200 Subject: [PATCH 02/15] feat(components): add focus outline to Badge feature/focus-outline --- src/components/Badge/Badge.docs.mdx | 6 ++ src/components/Badge/Badge.js | 78 +++++++++++-------- src/components/Badge/Badge.spec.js | 2 +- src/components/Badge/Badge.story.js | 7 ++ .../Badge/__snapshots__/Badge.spec.js.snap | 32 ++++---- 5 files changed, 77 insertions(+), 48 deletions(-) diff --git a/src/components/Badge/Badge.docs.mdx b/src/components/Badge/Badge.docs.mdx index 1744ff6f4a..df326bf79c 100644 --- a/src/components/Badge/Badge.docs.mdx +++ b/src/components/Badge/Badge.docs.mdx @@ -39,3 +39,9 @@ The badges come in a number of colors based on their semantic meaning. Badges that receive the `circle` prop can be used to indicate notifications. + +### Clickable badges + +Badges that receive the `onClick` prop can be interacted with. + + diff --git a/src/components/Badge/Badge.js b/src/components/Badge/Badge.js index d83bc4039b..6c5074337d 100644 --- a/src/components/Badge/Badge.js +++ b/src/components/Badge/Badge.js @@ -19,7 +19,7 @@ import styled from '@emotion/styled'; import { css } from '@emotion/core'; import { size } from 'polished'; -import { subHeadingKilo } from '../../styles/style-helpers'; +import { subHeadingKilo, focusOutline } from '../../styles/style-helpers'; import { colorNames } from '../../styles/constants'; const COLOR_MAP = { @@ -49,35 +49,10 @@ const COLOR_MAP = { active: 'n900' } }; - -const colorStyles = ({ theme, color, onClick }) => { - const currentColor = COLOR_MAP[color]; - - if (!currentColor) { - return null; - } - - return css` - label: ${`badge--${color}`}; - background-color: ${theme.colors[currentColor.default]}; - ${onClick && - ` - &:hover { - background-color: ${theme.colors[currentColor.hover]}; - } - - &:active { - background-color: ${theme.colors[currentColor.active]}; - } - `}; - `; -}; - -const baseStyles = ({ theme, onClick }) => css` +const baseStyles = ({ theme }) => css` label: badge; - border-radius: 100px; + border-radius: ${theme.borderRadius.pill}; color: ${theme.colors.white}; - cursor: ${onClick ? 'pointer' : 'default'}; display: inline-block; padding: 0 ${theme.spacings.byte}; ${subHeadingKilo({ theme })}; @@ -87,6 +62,17 @@ const baseStyles = ({ theme, onClick }) => css` text-align: center; `; +const colorStyles = ({ theme, color }) => { + const currentColor = COLOR_MAP[color]; + if (!currentColor) { + return null; + } + return css` + label: ${`badge--${color}`}; + background-color: ${theme.colors[currentColor.default]}; + `; +}; + const circleStyles = ({ circle }) => circle && css` @@ -97,11 +83,37 @@ const circleStyles = ({ circle }) => ${size(24)}; `; -const StyledBadge = styled('div')` - ${baseStyles}; - ${colorStyles}; - ${circleStyles}; -`; +const clickableStyles = ({ theme, onClick, color }) => { + const currentColor = COLOR_MAP[color]; + if (!onClick || !currentColor) { + return null; + } + return css` + label: badge--clickable; + border: 0; + outline: 0; + cursor: pointer; + + &:hover { + background-color: ${theme.colors[currentColor.hover]}; + } + + &:active { + background-color: ${theme.colors[currentColor.active]}; + } + + &:focus { + ${focusOutline({ theme })}; + } + `; +}; + +const StyledBadge = styled('div')( + baseStyles, + colorStyles, + circleStyles, + clickableStyles +); /** * A badge for displaying update notifications etc. diff --git a/src/components/Badge/Badge.spec.js b/src/components/Badge/Badge.spec.js index b26b43bf44..3c7ef5c8c0 100644 --- a/src/components/Badge/Badge.spec.js +++ b/src/components/Badge/Badge.spec.js @@ -49,7 +49,7 @@ describe('Badge', () => { }); it('should have hover/active styles only when the onClick handler is provided', () => { - const actual = create( {}} />); + const actual = create(); expect(actual).toMatchSnapshot(); }); diff --git a/src/components/Badge/Badge.story.js b/src/components/Badge/Badge.story.js index 1b2f18bf2d..a7ae2466d2 100644 --- a/src/components/Badge/Badge.story.js +++ b/src/components/Badge/Badge.story.js @@ -15,6 +15,7 @@ import React, { Fragment } from 'react'; import { select, boolean } from '@storybook/addon-knobs/react'; +import { action } from '@storybook/addon-actions'; import { values } from 'lodash/fp'; import { colorNames } from '../../styles/constants'; @@ -50,3 +51,9 @@ export const circular = () => ( 42 ); + +export const clickable = () => ( + + Click me + +); diff --git a/src/components/Badge/__snapshots__/Badge.spec.js.snap b/src/components/Badge/__snapshots__/Badge.spec.js.snap index be4ca24e69..110ea1ab93 100644 --- a/src/components/Badge/__snapshots__/Badge.spec.js.snap +++ b/src/components/Badge/__snapshots__/Badge.spec.js.snap @@ -2,9 +2,8 @@ exports[`Badge rendering color variations should render with danger colors 1`] = ` .circuit-0 { - border-radius: 100px; + border-radius: 999999px; color: #FFFFFF; - cursor: default; display: inline-block; padding: 0 8px; font-size: 12px; @@ -27,9 +26,8 @@ exports[`Badge rendering color variations should render with danger colors 1`] = exports[`Badge rendering color variations should render with primary colors 1`] = ` .circuit-0 { - border-radius: 100px; + border-radius: 999999px; color: #FFFFFF; - cursor: default; display: inline-block; padding: 0 8px; font-size: 12px; @@ -52,9 +50,8 @@ exports[`Badge rendering color variations should render with primary colors 1`] exports[`Badge rendering color variations should render with success colors 1`] = ` .circuit-0 { - border-radius: 100px; + border-radius: 999999px; color: #FFFFFF; - cursor: default; display: inline-block; padding: 0 8px; font-size: 12px; @@ -77,9 +74,8 @@ exports[`Badge rendering color variations should render with success colors 1`] exports[`Badge rendering color variations should render with warning colors 1`] = ` .circuit-0 { - border-radius: 100px; + border-radius: 999999px; color: #FFFFFF; - cursor: default; display: inline-block; padding: 0 8px; font-size: 12px; @@ -102,9 +98,8 @@ exports[`Badge rendering color variations should render with warning colors 1`] exports[`Badge should have hover/active styles only when the onClick handler is provided 1`] = ` .circuit-0 { - border-radius: 100px; + border-radius: 999999px; color: #FFFFFF; - cursor: pointer; display: inline-block; padding: 0 8px; font-size: 12px; @@ -117,6 +112,9 @@ exports[`Badge should have hover/active styles only when the onClick handler is user-select: none; text-align: center; background-color: #9DA7B1; + border: 0; + outline: 0; + cursor: pointer; } .circuit-0:hover { @@ -127,6 +125,14 @@ exports[`Badge should have hover/active styles only when the onClick handler is background-color: #212933; } +.circuit-0:focus { + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus::-moz-focus-inner { + border: 0; +} +
Date: Sun, 3 May 2020 13:04:28 +0200 Subject: [PATCH 03/15] feat(components): update focus styles of Checkbox feature/focus-outline --- src/components/Checkbox/Checkbox.js | 5 ++- .../__snapshots__/Checkbox.spec.js.snap | 35 +++++++++++++------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/components/Checkbox/Checkbox.js b/src/components/Checkbox/Checkbox.js index 4a7c791639..15671193be 100644 --- a/src/components/Checkbox/Checkbox.js +++ b/src/components/Checkbox/Checkbox.js @@ -20,7 +20,7 @@ import styled from '@emotion/styled'; import { hideVisually, size } from 'polished'; import { Check } from '@sumup/icons'; -import { disableVisually } from '../../styles/style-helpers'; +import { disableVisually, focusOutline } from '../../styles/style-helpers'; import { childrenPropType } from '../../util/shared-prop-types'; import { uniqueId } from '../../util/id'; import Tooltip from '../Tooltip'; @@ -100,8 +100,7 @@ const inputStyles = ({ theme }) => css` ${hideVisually()}; &:focus + label::before { - border-width: 2px; - border-color: ${theme.colors.p500}; + ${focusOutline({ theme })}; } &:checked + label > svg { diff --git a/src/components/Checkbox/__snapshots__/Checkbox.spec.js.snap b/src/components/Checkbox/__snapshots__/Checkbox.spec.js.snap index 40dca69349..3c53931399 100644 --- a/src/components/Checkbox/__snapshots__/Checkbox.spec.js.snap +++ b/src/components/Checkbox/__snapshots__/Checkbox.spec.js.snap @@ -23,8 +23,11 @@ exports[`Checkbox should render with a tooltip when passed a validation hint 1`] } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label > svg { @@ -187,8 +190,11 @@ exports[`Checkbox should render with checked styles when passed the checked prop } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label > svg { @@ -306,8 +312,11 @@ exports[`Checkbox should render with default styles 1`] = ` } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label > svg { @@ -424,8 +433,11 @@ exports[`Checkbox should render with disabled styles when passed the disabled pr } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label > svg { @@ -562,8 +574,11 @@ exports[`Checkbox should render with invalid styles when passed the invalid prop } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label > svg { From 50163f4b67b549cb7aabf65b71fa02502e83d262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= Date: Sun, 3 May 2020 13:07:50 +0200 Subject: [PATCH 04/15] feat(components): update focus styles of RadioButton feature/focus-outline --- src/components/RadioButton/RadioButton.js | 20 ++++++------- .../__snapshots__/RadioButton.spec.js.snap | 28 +++++++++++++------ .../RadioButtonGroup.spec.js.snap | 7 +++-- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/components/RadioButton/RadioButton.js b/src/components/RadioButton/RadioButton.js index 818df9656f..b218b9c0ce 100644 --- a/src/components/RadioButton/RadioButton.js +++ b/src/components/RadioButton/RadioButton.js @@ -19,7 +19,7 @@ import styled from '@emotion/styled'; import { css } from '@emotion/core'; import { hideVisually, size } from 'polished'; -import { disableVisually } from '../../styles/style-helpers'; +import { disableVisually, focusOutline } from '../../styles/style-helpers'; import { childrenPropType } from '../../util/shared-prop-types'; import { uniqueId } from '../../util/id'; @@ -95,11 +95,9 @@ const labelDisabledStyles = ({ theme, disabled }) => const inputStyles = ({ theme }) => css` label: radio-button__input; - ${hideVisually()}; &:focus + label::before { - border-width: 2px; - border-color: ${theme.colors.p500}; + ${focusOutline({ theme })} } &:checked + label { @@ -114,15 +112,13 @@ const inputStyles = ({ theme }) => css` } `; -const RadioButtonInput = styled('input')` - ${inputStyles}; -`; +const RadioButtonInput = styled('input')(hideVisually, inputStyles); -const RadioButtonLabel = styled('label')` - ${labelBaseStyles}; - ${labelDisabledStyles}; - ${labelInvalidStyles}; -`; +const RadioButtonLabel = styled('label')( + labelBaseStyles, + labelDisabledStyles, + labelInvalidStyles +); /** * RadioButton component for forms. diff --git a/src/components/RadioButton/__snapshots__/RadioButton.spec.js.snap b/src/components/RadioButton/__snapshots__/RadioButton.spec.js.snap index a39cd83cdb..50c8a75274 100644 --- a/src/components/RadioButton/__snapshots__/RadioButton.spec.js.snap +++ b/src/components/RadioButton/__snapshots__/RadioButton.spec.js.snap @@ -16,8 +16,11 @@ HTMLCollection [ } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label::before { @@ -107,8 +110,11 @@ HTMLCollection [ } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label::before { @@ -197,8 +203,11 @@ HTMLCollection [ } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label::before { @@ -307,8 +316,11 @@ HTMLCollection [ } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label::before { diff --git a/src/components/RadioButtonGroup/__snapshots__/RadioButtonGroup.spec.js.snap b/src/components/RadioButtonGroup/__snapshots__/RadioButtonGroup.spec.js.snap index aede6b4775..e19e43d979 100644 --- a/src/components/RadioButtonGroup/__snapshots__/RadioButtonGroup.spec.js.snap +++ b/src/components/RadioButtonGroup/__snapshots__/RadioButtonGroup.spec.js.snap @@ -15,8 +15,11 @@ exports[`RadioButtonGroup should render with default styles 1`] = ` } .circuit-0:focus + label::before { - border-width: 2px; - border-color: #3388FF; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; } .circuit-0:checked + label::before { From bbc55920c5a96038d94f55b45cfe435582dea5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= Date: Sun, 3 May 2020 13:20:51 +0200 Subject: [PATCH 05/15] feat(utils): remove default focus ring styles feature/focus-outline --- .../Badge/__snapshots__/Badge.spec.js.snap | 5 ++++ .../__snapshots__/Checkbox.spec.js.snap | 25 +++++++++++++++++++ .../__snapshots__/RadioButton.spec.js.snap | 20 +++++++++++++++ .../RadioButtonGroup.spec.js.snap | 5 ++++ src/styles/style-helpers.spec.js | 5 ++++ src/styles/style-helpers.ts | 5 ++++ 6 files changed, 65 insertions(+) diff --git a/src/components/Badge/__snapshots__/Badge.spec.js.snap b/src/components/Badge/__snapshots__/Badge.spec.js.snap index 110ea1ab93..a2aba17e10 100644 --- a/src/components/Badge/__snapshots__/Badge.spec.js.snap +++ b/src/components/Badge/__snapshots__/Badge.spec.js.snap @@ -133,6 +133,11 @@ exports[`Badge should have hover/active styles only when the onClick handler is border: 0; } +.circuit-0:focus:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} +
svg { -webkit-transform: translateY(-50%) scale(1,1); -ms-transform: translateY(-50%) scale(1,1); @@ -197,6 +202,11 @@ exports[`Checkbox should render with checked styles when passed the checked prop border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label > svg { -webkit-transform: translateY(-50%) scale(1,1); -ms-transform: translateY(-50%) scale(1,1); @@ -319,6 +329,11 @@ exports[`Checkbox should render with default styles 1`] = ` border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label > svg { -webkit-transform: translateY(-50%) scale(1,1); -ms-transform: translateY(-50%) scale(1,1); @@ -440,6 +455,11 @@ exports[`Checkbox should render with disabled styles when passed the disabled pr border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label > svg { -webkit-transform: translateY(-50%) scale(1,1); -ms-transform: translateY(-50%) scale(1,1); @@ -581,6 +601,11 @@ exports[`Checkbox should render with invalid styles when passed the invalid prop border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label > svg { -webkit-transform: translateY(-50%) scale(1,1); -ms-transform: translateY(-50%) scale(1,1); diff --git a/src/components/RadioButton/__snapshots__/RadioButton.spec.js.snap b/src/components/RadioButton/__snapshots__/RadioButton.spec.js.snap index 50c8a75274..31cb6a5e44 100644 --- a/src/components/RadioButton/__snapshots__/RadioButton.spec.js.snap +++ b/src/components/RadioButton/__snapshots__/RadioButton.spec.js.snap @@ -23,6 +23,11 @@ HTMLCollection [ border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label::before { border-color: #3388FF; } @@ -117,6 +122,11 @@ HTMLCollection [ border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label::before { border-color: #3388FF; } @@ -210,6 +220,11 @@ HTMLCollection [ border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label::before { border-color: #3388FF; } @@ -323,6 +338,11 @@ HTMLCollection [ border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label::before { border-color: #3388FF; } diff --git a/src/components/RadioButtonGroup/__snapshots__/RadioButtonGroup.spec.js.snap b/src/components/RadioButtonGroup/__snapshots__/RadioButtonGroup.spec.js.snap index e19e43d979..8ceee857d1 100644 --- a/src/components/RadioButtonGroup/__snapshots__/RadioButtonGroup.spec.js.snap +++ b/src/components/RadioButtonGroup/__snapshots__/RadioButtonGroup.spec.js.snap @@ -22,6 +22,11 @@ exports[`RadioButtonGroup should render with default styles 1`] = ` border: 0; } +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-0:checked + label::before { border-color: #3388FF; } diff --git a/src/styles/style-helpers.spec.js b/src/styles/style-helpers.spec.js index 7bdae60a31..df9036d1ce 100644 --- a/src/styles/style-helpers.spec.js +++ b/src/styles/style-helpers.spec.js @@ -236,6 +236,11 @@ describe('Style helpers', () => { &::-moz-focus-inner { border: 0; } + + &:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; + } " `); }); diff --git a/src/styles/style-helpers.ts b/src/styles/style-helpers.ts index 42bca2d559..84a1c532a8 100644 --- a/src/styles/style-helpers.ts +++ b/src/styles/style-helpers.ts @@ -116,6 +116,11 @@ export const focusOutline = (args: ThemeArgs): SerializedStyles => { &::-moz-focus-inner { border: 0; } + + &:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; + } `; }; From 96af7499e9eb0cbfa46fa20f40319a994e612ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= Date: Sun, 3 May 2020 13:24:42 +0200 Subject: [PATCH 06/15] feat(components): add focus outline to Selector feature/focus-outline --- src/components/Selector/Selector.js | 12 ++++--- .../__snapshots__/Selector.spec.js.snap | 33 +++++++++++++++++-- .../__snapshots__/SelectorGroup.spec.js.snap | 11 ++++++- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/components/Selector/Selector.js b/src/components/Selector/Selector.js index 8634ccb0c5..2681584571 100644 --- a/src/components/Selector/Selector.js +++ b/src/components/Selector/Selector.js @@ -20,7 +20,11 @@ import { css } from '@emotion/core'; import { hideVisually } from 'polished'; import { childrenPropType } from '../../util/shared-prop-types'; -import { shadowSingle, shadowDouble } from '../../styles/style-helpers'; +import { + shadowSingle, + shadowDouble, + focusOutline +} from '../../styles/style-helpers'; import { uniqueId } from '../../util/id'; const wrapperStyles = ({ theme }) => css` @@ -84,10 +88,8 @@ const inputStyles = ({ theme }) => css` label: selector__input; ${hideVisually()}; - &:focus + label { - &::before { - border-width: ${theme.borderWidth.mega}; - } + &:focus + label::before { + ${focusOutline({ theme })}; } &:checked + label { diff --git a/src/components/Selector/__snapshots__/Selector.spec.js.snap b/src/components/Selector/__snapshots__/Selector.spec.js.snap index 61b07fa061..bc944ddfae 100644 --- a/src/components/Selector/__snapshots__/Selector.spec.js.snap +++ b/src/components/Selector/__snapshots__/Selector.spec.js.snap @@ -20,7 +20,16 @@ exports[`Selector should render a checked selector 1`] = ` } .circuit-0:focus + label::before { - border-width: 2px; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; +} + +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; } .circuit-0:checked + label { @@ -104,7 +113,16 @@ exports[`Selector should render a default selector 1`] = ` } .circuit-0:focus + label::before { - border-width: 2px; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; +} + +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; } .circuit-0:checked + label { @@ -187,7 +205,16 @@ exports[`Selector should render a disabled selector 1`] = ` } .circuit-0:focus + label::before { - border-width: 2px; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; +} + +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; } .circuit-0:checked + label { diff --git a/src/components/SelectorGroup/__snapshots__/SelectorGroup.spec.js.snap b/src/components/SelectorGroup/__snapshots__/SelectorGroup.spec.js.snap index b0aebfcf64..d85768c6d8 100644 --- a/src/components/SelectorGroup/__snapshots__/SelectorGroup.spec.js.snap +++ b/src/components/SelectorGroup/__snapshots__/SelectorGroup.spec.js.snap @@ -20,7 +20,16 @@ exports[`SelectorGroup should render with default styles 1`] = ` } .circuit-0:focus + label::before { - border-width: 2px; + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus + label::before::-moz-focus-inner { + border: 0; +} + +.circuit-0:focus + label::before:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; } .circuit-0:checked + label { From 970d1e0453bd93746ce8c1119227de9ea950dbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= Date: Sun, 3 May 2020 13:37:06 +0200 Subject: [PATCH 07/15] feat(components): add focus outline to Tabs feature/focus-outline --- .../Tabs/__snapshots__/Tabs.spec.js.snap | 52 +++++++++++++++++++ src/components/Tabs/components/Tab/Tab.js | 7 ++- .../Tab/__snapshots__/Tab.spec.js.snap | 26 ++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/components/Tabs/__snapshots__/Tabs.spec.js.snap b/src/components/Tabs/__snapshots__/Tabs.spec.js.snap index 5d9c9a2406..cfb160dc6c 100644 --- a/src/components/Tabs/__snapshots__/Tabs.spec.js.snap +++ b/src/components/Tabs/__snapshots__/Tabs.spec.js.snap @@ -66,6 +66,19 @@ exports[`Tabs styles should render with default styles 1`] = ` outline: none; } +.circuit-0:focus { + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus::-moz-focus-inner { + border: 0; +} + +.circuit-0:focus:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-2 { font-size: 16px; line-height: 24px; @@ -99,6 +112,19 @@ exports[`Tabs styles should render with default styles 1`] = ` color: #212933; } +.circuit-2:focus { + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-2:focus::-moz-focus-inner { + border: 0; +} + +.circuit-2:focus:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-2::after { content: ' '; position: absolute; @@ -179,6 +205,19 @@ exports[`Tabs styles should render with stretched styles 1`] = ` outline: none; } +.circuit-0:focus { + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus::-moz-focus-inner { + border: 0; +} + +.circuit-0:focus:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-2 { font-size: 16px; line-height: 24px; @@ -212,6 +251,19 @@ exports[`Tabs styles should render with stretched styles 1`] = ` color: #212933; } +.circuit-2:focus { + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-2:focus::-moz-focus-inner { + border: 0; +} + +.circuit-2:focus:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + .circuit-2::after { content: ' '; position: absolute; diff --git a/src/components/Tabs/components/Tab/Tab.js b/src/components/Tabs/components/Tab/Tab.js index b984c5264a..cad0c0cc5f 100644 --- a/src/components/Tabs/components/Tab/Tab.js +++ b/src/components/Tabs/components/Tab/Tab.js @@ -18,7 +18,7 @@ import PropTypes from 'prop-types'; import styled from '@emotion/styled'; import { css } from '@emotion/core'; -import { textMega } from '../../../../styles/style-helpers'; +import { textMega, focusOutline } from '../../../../styles/style-helpers'; const defaultTabStyles = ({ theme }) => css` label: tab; @@ -29,7 +29,6 @@ const defaultTabStyles = ({ theme }) => css` cursor: pointer; background-color: transparent; border: none; - white-space: nowrap; height: 100%; align-items: center; @@ -38,6 +37,10 @@ const defaultTabStyles = ({ theme }) => css` flex-direction: column; justify-content: center; outline: none; + + &:focus { + ${focusOutline({ theme })}; + } `; const selectedTabStyles = ({ theme, selected }) => diff --git a/src/components/Tabs/components/Tab/__snapshots__/Tab.spec.js.snap b/src/components/Tabs/components/Tab/__snapshots__/Tab.spec.js.snap index be2c099361..fceb71972a 100644 --- a/src/components/Tabs/components/Tab/__snapshots__/Tab.spec.js.snap +++ b/src/components/Tabs/components/Tab/__snapshots__/Tab.spec.js.snap @@ -32,6 +32,19 @@ exports[`Tab styles should render with default styles 1`] = ` outline: none; } +.circuit-0:focus { + box-shadow: 0 0 0 4px #AFD0FE; +} + +.circuit-0:focus::-moz-focus-inner { + border: 0; +} + +.circuit-0:focus:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} +