diff --git a/.changeset/silent-falcons-exist.md b/.changeset/silent-falcons-exist.md new file mode 100644 index 00000000000..aad227a4aa9 --- /dev/null +++ b/.changeset/silent-falcons-exist.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Finishes updating components with the global focus styles defined in Primer CSS ([this PR](https://github.com/primer/css/pull/1744)) diff --git a/docs/content/SubNav.md b/docs/content/SubNav.md index 701dc47e262..50f56913394 100644 --- a/docs/content/SubNav.md +++ b/docs/content/SubNav.md @@ -39,7 +39,7 @@ This ensures that the NavLink gets `activeClassName='selected'` Support - + ``` @@ -64,7 +64,7 @@ This ensures that the NavLink gets `activeClassName='selected'` - + diff --git a/docs/src/@primer/gatsby-theme-doctocat/components/live-preview-wrapper.js b/docs/src/@primer/gatsby-theme-doctocat/components/live-preview-wrapper.js index 80e851b9ca9..a2871551839 100644 --- a/docs/src/@primer/gatsby-theme-doctocat/components/live-preview-wrapper.js +++ b/docs/src/@primer/gatsby-theme-doctocat/components/live-preview-wrapper.js @@ -1,24 +1,33 @@ -import {BaseStyles, Box, ThemeProvider, useTheme} from '@primer/react' -import {DropdownMenu, DropdownButton} from '@primer/react/deprecated' import React from 'react' +import {ActionMenu, ActionList, BaseStyles, Box, ThemeProvider, useTheme} from '@primer/react' function ThemeSwitcher() { const {theme, dayScheme, setDayScheme} = useTheme() - const items = Object.keys(theme.colorSchemes).map(scheme => ({text: scheme.replace(/_/g, ' '), key: scheme})) + const items = Object.keys(theme.colorSchemes).map(scheme => ({name: scheme.replace(/_/g, ' '), key: scheme})) const selectedItem = React.useMemo(() => items.find(item => item.key === dayScheme), [items, dayScheme]) + const itemsKeys = items.map(item => item.key) + const [selectedIndex, setSelectedIndex] = React.useState(itemsKeys.indexOf(dayScheme)) + return ( - ( - - {children} - - )} - items={items} - selectedItem={selectedItem} - onChange={item => { - setDayScheme(item.key) - }} - /> + + {selectedItem?.name} + + + {items.map((type, index) => ( + { + setSelectedIndex(index) + setDayScheme(items[index].key) + }} + > + {type.name} + + ))} + + + ) } diff --git a/src/Button/styles.ts b/src/Button/styles.ts index 1417f3cb647..c586faa0d58 100644 --- a/src/Button/styles.ts +++ b/src/Button/styles.ts @@ -2,17 +2,6 @@ import {VariantType} from './types' import {Theme} from '../ThemeProvider' export const TEXT_ROW_HEIGHT = '20px' // custom value off the scale -const focusOutlineStyles = { - outline: '2px solid', - outlineColor: 'accent.fg', - outlineOffset: '-2px' -} -const fallbackFocus = { - ...focusOutlineStyles, - ':not(:focus-visible)': { - outline: 'solid 1px transparent' - } -} export const getVariantStyles = (variant: VariantType = 'default', theme?: Theme) => { const style = { @@ -23,11 +12,6 @@ export const getVariantStyles = (variant: VariantType = 'default', theme?: Theme '&:hover:not([disabled])': { backgroundColor: 'btn.hoverBg' }, - // focus must come before :active so that the active box shadow overrides - '&:focus:not([disabled])': { - ...fallbackFocus - }, - '&:focus-visible:not([disabled])': focusOutlineStyles, '&:active:not([disabled])': { backgroundColor: 'btn.activeBg', borderColor: 'btn.activeBorder' @@ -52,13 +36,10 @@ export const getVariantStyles = (variant: VariantType = 'default', theme?: Theme color: 'btn.primary.hoverText', backgroundColor: 'btn.primary.hoverBg' }, - // focus must come before :active so that the active box shadow overrides '&:focus:not([disabled])': { - boxShadow: 'inset 0 0 0 3px', - ...fallbackFocus + boxShadow: 'inset 0 0 0 3px' }, '&:focus-visible:not([disabled])': { - ...focusOutlineStyles, boxShadow: 'inset 0 0 0 3px' }, '&:active:not([disabled])': { @@ -95,11 +76,6 @@ export const getVariantStyles = (variant: VariantType = 'default', theme?: Theme color: 'btn.danger.hoverText' } }, - // focus must come before :active so that the active box shadow overrides - '&:focus:not([disabled])': { - ...fallbackFocus - }, - '&:focus-visible:not([disabled])': focusOutlineStyles, '&:active:not([disabled])': { color: 'btn.danger.selectedText', backgroundColor: 'btn.danger.selectedBg', @@ -134,11 +110,6 @@ export const getVariantStyles = (variant: VariantType = 'default', theme?: Theme '&:hover:not([disabled])': { backgroundColor: 'btn.hoverBg' }, - // focus must come before :active so that the active box shadow overrides - '&:focus:not([disabled])': { - ...fallbackFocus - }, - '&:focus-visible:not([disabled])': focusOutlineStyles, '&:active:not([disabled])': { backgroundColor: 'btn.selectedBg' }, @@ -168,11 +139,6 @@ export const getVariantStyles = (variant: VariantType = 'default', theme?: Theme color: 'inherit' } }, - // focus must come before :active so that the active box shadow overrides - '&:focus:not([disabled])': { - ...fallbackFocus - }, - '&:focus-visible:not([disabled])': focusOutlineStyles, '&:active:not([disabled])': { color: 'btn.outline.selectedText', backgroundColor: 'btn.outline.selectedBg', diff --git a/src/Button/types.ts b/src/Button/types.ts index 10c7188bc1a..7568bd3910d 100644 --- a/src/Button/types.ts +++ b/src/Button/types.ts @@ -2,8 +2,12 @@ import React, {HTMLAttributes, ComponentPropsWithRef} from 'react' import styled from 'styled-components' import {IconProps} from '@primer/octicons-react' import sx, {SxProp} from '../sx' +import getGlobalFocusStyles from '../_getGlobalFocusStyles' -export const StyledButton = styled.button(sx) +export const StyledButton = styled.button` + ${getGlobalFocusStyles('-2px')}; + ${sx}; +` export type VariantType = 'default' | 'primary' | 'invisible' | 'danger' | 'outline' diff --git a/src/Checkbox.tsx b/src/Checkbox.tsx index bbad54491ca..058aa1b2e63 100644 --- a/src/Checkbox.tsx +++ b/src/Checkbox.tsx @@ -4,6 +4,7 @@ import React, {ChangeEventHandler, InputHTMLAttributes, ReactElement, useContext import sx, {SxProp} from './sx' import {FormValidationStatus} from './utils/types/FormValidationStatus' import {CheckboxGroupContext} from './CheckboxGroup' +import getGlobalFocusStyles from './_getGlobalFocusStyles' export type CheckboxProps = { /** @@ -38,6 +39,7 @@ const StyledCheckbox = styled.input` cursor: pointer; ${props => props.disabled && `cursor: not-allowed;`} + ${getGlobalFocusStyles(0)}; ${sx} ` diff --git a/src/Pagination/Pagination.tsx b/src/Pagination/Pagination.tsx index 8a13794f3f7..cb16f146d46 100644 --- a/src/Pagination/Pagination.tsx +++ b/src/Pagination/Pagination.tsx @@ -3,6 +3,7 @@ import styled from 'styled-components' import Box from '../Box' import {get} from '../constants' import sx, {SxProp} from '../sx' +import getGlobalFocusStyles from '../_getGlobalFocusStyles' import {buildComponentData, buildPaginationModel} from './model' const Page = styled.a` @@ -37,6 +38,8 @@ const Page = styled.a` transition-duration: 0.1s; } + ${getGlobalFocusStyles(0)}; + &:active { border-color: ${get('colors.border.muted')}; } diff --git a/src/Radio.tsx b/src/Radio.tsx index 64616927adc..ee660497768 100644 --- a/src/Radio.tsx +++ b/src/Radio.tsx @@ -3,6 +3,7 @@ import React, {ChangeEventHandler, InputHTMLAttributes, ReactElement, useContext import sx, {SxProp} from './sx' import {FormValidationStatus} from './utils/types/FormValidationStatus' import {RadioGroupContext} from './RadioGroup' +import getGlobalFocusStyles from './_getGlobalFocusStyles' export type RadioProps = { /** @@ -41,6 +42,7 @@ const StyledRadio = styled.input` cursor: pointer; ${props => props.disabled && `cursor: not-allowed;`} + ${getGlobalFocusStyles(0)}; ${sx} ` diff --git a/src/SubNav.tsx b/src/SubNav.tsx index 72d31ed7c28..b21f46d362e 100644 --- a/src/SubNav.tsx +++ b/src/SubNav.tsx @@ -96,7 +96,7 @@ const SubNavLink = styled.a.attrs(props => ({ &:focus { text-decoration: none; background-color: ${get('colors.canvas.subtle')}; - transition: 0.2s ease; + transition: background-color 0.2s ease; .SubNav-octicon { color: ${get('colors.fg.muted')}; diff --git a/src/TabNav.tsx b/src/TabNav.tsx index c4204d406f9..dc7ff810571 100644 --- a/src/TabNav.tsx +++ b/src/TabNav.tsx @@ -5,6 +5,7 @@ import styled from 'styled-components' import {get} from './constants' import sx, {SxProp} from './sx' import {ComponentProps} from './utils/types' +import getGlobalFocusStyles from './_getGlobalFocusStyles' const ITEM_CLASS = 'TabNav-item' const SELECTED_CLASS = 'selected' @@ -49,6 +50,8 @@ const TabNavLink = styled.a.attrs(props => ({ border: 1px solid transparent; border-bottom: 0; + ${getGlobalFocusStyles('-6px')}; + &:hover, &:focus { color: ${get('colors.fg.default')}; diff --git a/src/UnderlineNav.tsx b/src/UnderlineNav.tsx index bc743179121..3237d8a4e67 100644 --- a/src/UnderlineNav.tsx +++ b/src/UnderlineNav.tsx @@ -5,6 +5,7 @@ import styled from 'styled-components' import {get} from './constants' import sx, {SxProp} from './sx' import {ComponentProps} from './utils/types' +import getGlobalFocusStyles from './_getGlobalFocusStyles' const ITEM_CLASS = 'PRC-UnderlineNav-item' const SELECTED_CLASS = 'PRC-selected' @@ -86,7 +87,7 @@ const UnderlineNavLink = styled.a.attrs(props => ({ color: ${get('colors.fg.default')}; text-decoration: none; border-bottom-color: ${get('colors.neutral.muted')}; - transition: 0.2s ease; + transition: border-bottom-color 0.2s ease; .PRC-UnderlineNav-octicon { color: ${get('colors.fg.muted')}; @@ -102,6 +103,8 @@ const UnderlineNavLink = styled.a.attrs(props => ({ } } + ${getGlobalFocusStyles('-8px')}; + ${sx}; ` diff --git a/src/_TextInputWrapper.tsx b/src/_TextInputWrapper.tsx index 7d8f7a0daf4..d30a27c46f1 100644 --- a/src/_TextInputWrapper.tsx +++ b/src/_TextInputWrapper.tsx @@ -65,20 +65,22 @@ export type StyledWrapperProps = { const textInputBasePadding = '12px' export const textInputHorizPadding = textInputBasePadding -// TODO: figure out how to type a themed CSS function (e.g.: css`color: blue;`) -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const renderFocusStyles = (hasTrailingAction: boolean, isInputFocused: boolean, focusStyles: any) => { +const renderFocusStyles = (hasTrailingAction: boolean, isInputFocused: boolean) => { if (hasTrailingAction) { return ( isInputFocused && css` - ${focusStyles} + border-color: ${get('colors.accent.fg')}; + outline: none; + box-shadow: inset 0 0 0 1px ${get('colors.accent.fg')}; ` ) } return css` &:focus-within { - ${focusStyles} + border-color: ${get('colors.accent.fg')}; + outline: none; + box-shadow: inset 0 0 0 1px ${get('colors.accent.fg')}; } ` } @@ -110,15 +112,7 @@ export const TextInputBaseWrapper = styled.span` color: ${get('colors.fg.subtle')}; } - ${props => - renderFocusStyles( - Boolean(props.hasTrailingAction), - Boolean(props.isInputFocused), - css` - border-color: ${get('colors.accent.emphasis')}; - box-shadow: ${get('shadows.primer.shadow.focus')}; - ` - )} + ${props => renderFocusStyles(Boolean(props.hasTrailingAction), Boolean(props.isInputFocused))} > textarea { padding: ${textInputBasePadding}; @@ -154,14 +148,7 @@ export const TextInputBaseWrapper = styled.span` props.validationStatus === 'error' && css` border-color: ${get('colors.danger.emphasis')}; - ${renderFocusStyles( - Boolean(props.hasTrailingAction), - Boolean(props.isInputFocused), - css` - border-color: ${get('colors.danger.emphasis')}; - box-shadow: ${get('shadows.btn.danger.focusShadow')}; - ` - )} + ${renderFocusStyles(Boolean(props.hasTrailingAction), Boolean(props.isInputFocused))} `} @@ -169,14 +156,6 @@ export const TextInputBaseWrapper = styled.span` props.validationStatus === 'success' && css` border-color: ${get('colors.success.emphasis')}; - ${renderFocusStyles( - Boolean(props.hasTrailingAction), - Boolean(props.isInputFocused), - css` - border-color: ${get('colors.success.emphasis')}; - box-shadow: 0 0 0 3px ${get('colors.success.muted')}; - ` - )} `} ${props => @@ -230,14 +209,7 @@ const TextInputWrapper = styled(TextInputBaseWrapper)` props.validationStatus === 'warning' && css` border-color: ${get('colors.attention.emphasis')}; - ${renderFocusStyles( - Boolean(props.hasTrailingAction), - Boolean(props.isInputFocused), - css` - border-color: ${get('colors.attention.emphasis')}; - box-shadow: 0 0 0 3px ${get('colors.attention.muted')}; - ` - )} + ${renderFocusStyles(Boolean(props.hasTrailingAction), Boolean(props.isInputFocused))} `} ${sx}; diff --git a/src/__tests__/Pagination/__snapshots__/Pagination.test.tsx.snap b/src/__tests__/Pagination/__snapshots__/Pagination.test.tsx.snap index f0f13c18b48..4d8a364a6d6 100644 --- a/src/__tests__/Pagination/__snapshots__/Pagination.test.tsx.snap +++ b/src/__tests__/Pagination/__snapshots__/Pagination.test.tsx.snap @@ -43,6 +43,22 @@ exports[`Pagination renders consistently 1`] = ` transition-duration: 0.1s; } +.c2:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: 0; +} + +.c2:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c2:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: 0; +} + .c2:active { border-color: hsla(210,18%,87%,1); } diff --git a/src/__tests__/__snapshots__/ActionMenu.test.tsx.snap b/src/__tests__/__snapshots__/ActionMenu.test.tsx.snap index a73796df9c5..d44220a337a 100644 --- a/src/__tests__/__snapshots__/ActionMenu.test.tsx.snap +++ b/src/__tests__/__snapshots__/ActionMenu.test.tsx.snap @@ -44,6 +44,22 @@ exports[`ActionMenu renders consistently 1`] = ` box-shadow: 0 1px 0 rgba(27,31,36,0.04),inset 0 1px 0 rgba(255,255,255,0.25); } +.c1:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + +.c1:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c1:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + .c1:disabled { cursor: default; color: #8c959f; @@ -81,22 +97,6 @@ exports[`ActionMenu renders consistently 1`] = ` background-color: #f3f4f6; } -.c1:focus:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - -.c1:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c1:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - .c1:active:not([disabled]) { background-color: hsla(220,14%,93%,1); border-color: rgba(27,31,36,0.15); diff --git a/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap b/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap index c329674b9e5..43c754dffc5 100644 --- a/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +++ b/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap @@ -54,7 +54,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -213,7 +214,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -407,7 +409,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -1364,7 +1367,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -2231,7 +2235,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -3109,7 +3114,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -4117,7 +4123,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { diff --git a/src/__tests__/__snapshots__/Button.test.tsx.snap b/src/__tests__/__snapshots__/Button.test.tsx.snap index 132275194b1..f54c410ac25 100644 --- a/src/__tests__/__snapshots__/Button.test.tsx.snap +++ b/src/__tests__/__snapshots__/Button.test.tsx.snap @@ -33,6 +33,22 @@ exports[`Button renders consistently 1`] = ` box-shadow: 0 1px 0 rgba(27,31,36,0.04),inset 0 1px 0 rgba(255,255,255,0.25); } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + .c0:disabled { cursor: default; color: #8c959f; @@ -70,22 +86,6 @@ exports[`Button renders consistently 1`] = ` background-color: #f3f4f6; } -.c0:focus:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - -.c0:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c0:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - .c0:active:not([disabled]) { background-color: hsla(220,14%,93%,1); border-color: rgba(27,31,36,0.15); @@ -139,6 +139,22 @@ exports[`Button styles danger button appropriately 1`] = ` box-shadow: undefined; } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + .c0:disabled { cursor: default; color: btn.danger.disabledText; @@ -189,22 +205,6 @@ exports[`Button styles danger button appropriately 1`] = ` color: btn.danger.hoverText; } -.c0:focus:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - -.c0:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c0:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - .c0:active:not([disabled]) { color: btn.danger.selectedText; background-color: btn.danger.selectedBg; @@ -270,6 +270,22 @@ exports[`Button styles icon only button to make it a square 1`] = ` box-shadow: undefined,undefined; } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + .c0:disabled { cursor: default; color: primer.fg.disabled; @@ -291,22 +307,6 @@ exports[`Button styles icon only button to make it a square 1`] = ` background-color: btn.hoverBg; } -.c0:focus:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - -.c0:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c0:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - .c0:active:not([disabled]) { background-color: btn.activeBg; border-color: btn.activeBorder; @@ -381,6 +381,22 @@ exports[`Button styles invisible button appropriately 1`] = ` box-shadow: none; } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + .c0:disabled { cursor: default; color: primer.fg.disabled; @@ -418,22 +434,6 @@ exports[`Button styles invisible button appropriately 1`] = ` background-color: btn.hoverBg; } -.c0:focus:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - -.c0:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c0:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - .c0:active:not([disabled]) { background-color: btn.selectedBg; } @@ -492,6 +492,22 @@ exports[`Button styles outline button appropriately 1`] = ` background-color: btn.bg; } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + .c0:disabled { cursor: default; color: btn.outline.disabledText; @@ -542,22 +558,6 @@ exports[`Button styles outline button appropriately 1`] = ` color: inherit; } -.c0:focus:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - -.c0:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c0:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - .c0:active:not([disabled]) { color: btn.outline.selectedText; background-color: btn.outline.selectedBg; @@ -622,6 +622,22 @@ exports[`Button styles primary button appropriately 1`] = ` box-shadow: undefined; } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid; + outline-offset: -2px; +} + .c0:disabled { cursor: default; color: btn.primary.disabledText; @@ -665,19 +681,9 @@ exports[`Button styles primary button appropriately 1`] = ` .c0:focus:not([disabled]) { box-shadow: inset 0 0 0 3px; - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; -} - -.c0:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; } .c0:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: accent.fg; - outline-offset: -2px; box-shadow: inset 0 0 0 3px; } diff --git a/src/__tests__/__snapshots__/Checkbox.test.tsx.snap b/src/__tests__/__snapshots__/Checkbox.test.tsx.snap index 1f1f73e7285..f830ba182ef 100644 --- a/src/__tests__/__snapshots__/Checkbox.test.tsx.snap +++ b/src/__tests__/__snapshots__/Checkbox.test.tsx.snap @@ -5,6 +5,22 @@ exports[`Checkbox renders consistently 1`] = ` cursor: pointer; } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: 0; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: 0; +} +
textarea { @@ -176,7 +177,8 @@ exports[`TextInput renders block 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -294,7 +296,8 @@ exports[`TextInput renders consistently 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -412,7 +415,8 @@ exports[`TextInput renders contrast 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -531,7 +535,8 @@ exports[`TextInput renders error 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -539,8 +544,9 @@ exports[`TextInput renders error 1`] = ` } .c0:focus-within { - border-color: #cf222e; - box-shadow: 0 0 0 3px rgba(164,14,38,0.4); + border-color: #0969da; + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 >:not(:last-child) { @@ -659,7 +665,8 @@ exports[`TextInput renders large 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -778,7 +785,8 @@ exports[`TextInput renders leadingVisual 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -924,7 +932,8 @@ exports[`TextInput renders monospace 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -1042,7 +1051,8 @@ exports[`TextInput renders placeholder 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -1168,7 +1178,8 @@ exports[`TextInput renders small 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -1274,6 +1285,22 @@ exports[`TextInput renders trailingAction icon button 1`] = ` position: relative; } +.c4:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + +.c4:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c4:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + .c4:disabled { cursor: default; color: #8c959f; @@ -1295,22 +1322,6 @@ exports[`TextInput renders trailingAction icon button 1`] = ` background-color: #f3f4f6; } -.c4:focus:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - -.c4:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c4:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - .c4:active:not([disabled]) { background-color: hsla(220,14%,94%,1); } @@ -1752,6 +1763,22 @@ exports[`TextInput renders trailingAction text button 1`] = ` position: relative; } +.c3:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + +.c3:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c3:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + .c3:disabled { cursor: default; color: #8c959f; @@ -1789,22 +1816,6 @@ exports[`TextInput renders trailingAction text button 1`] = ` background-color: #f3f4f6; } -.c3:focus:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - -.c3:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c3:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - .c3:active:not([disabled]) { background-color: hsla(220,14%,94%,1); } @@ -2000,6 +2011,22 @@ exports[`TextInput renders trailingAction text button with a tooltip 1`] = ` position: relative; } +.c4:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + +.c4:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c4:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -2px; +} + .c4:disabled { cursor: default; color: #8c959f; @@ -2037,22 +2064,6 @@ exports[`TextInput renders trailingAction text button with a tooltip 1`] = ` background-color: #f3f4f6; } -.c4:focus:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - -.c4:focus:not([disabled]):not(:focus-visible) { - outline: solid 1px transparent; -} - -.c4:focus-visible:not([disabled]) { - outline: 2px solid; - outline-color: #0969da; - outline-offset: -2px; -} - .c4:active:not([disabled]) { background-color: hsla(220,14%,94%,1); } @@ -2489,7 +2500,8 @@ exports[`TextInput renders trailingVisual 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -2635,7 +2647,8 @@ exports[`TextInput renders warning 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -2664,8 +2677,9 @@ exports[`TextInput renders warning 1`] = ` } .c0:focus-within { - border-color: #bf8700; - box-shadow: 0 0 0 3px rgba(212,167,44,0.4); + border-color: #0969da; + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c1 { @@ -2767,7 +2781,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -2933,7 +2948,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -3143,7 +3159,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -3313,7 +3330,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -3563,7 +3581,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -3813,7 +3832,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -4063,7 +4083,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -4269,7 +4290,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -4519,7 +4541,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -4736,7 +4759,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -5027,7 +5051,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -5322,7 +5347,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -5601,7 +5627,8 @@ exports[`TextInput should render a password input 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { diff --git a/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap b/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap index 3d88d924137..4d7f5009ddf 100644 --- a/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap +++ b/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap @@ -97,7 +97,8 @@ exports[`TextInputWithTokens renders a leadingVisual and trailingVisual 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -832,7 +833,8 @@ exports[`TextInputWithTokens renders a truncated set of tokens 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -1255,7 +1257,8 @@ exports[`TextInputWithTokens renders as block layout 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -1430,7 +1433,8 @@ exports[`TextInputWithTokens renders at a maximum height when specified 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -2120,7 +2124,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -2810,7 +2815,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 2`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -3493,7 +3499,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 3`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -4176,7 +4183,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 4`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -4859,7 +4867,8 @@ exports[`TextInputWithTokens renders tokens at the specified sizes 5`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -5544,7 +5553,8 @@ exports[`TextInputWithTokens renders tokens on a single line when specified 1`] .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -6227,7 +6237,8 @@ exports[`TextInputWithTokens renders tokens without a remove button when specifi .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -6627,7 +6638,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -7359,7 +7371,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -8135,7 +8148,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -8871,7 +8885,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -9687,7 +9702,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -10503,7 +10519,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -11319,7 +11336,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -12091,7 +12109,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -12907,7 +12926,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -13690,7 +13710,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -14546,7 +14567,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -15402,7 +15424,8 @@ Array [ .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -16246,7 +16269,8 @@ exports[`TextInputWithTokens renders with tokens 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -16929,7 +16953,8 @@ exports[`TextInputWithTokens renders with tokens using a custom token component .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { @@ -17617,7 +17642,8 @@ exports[`TextInputWithTokens renders without tokens 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { diff --git a/src/__tests__/__snapshots__/Textarea.test.tsx.snap b/src/__tests__/__snapshots__/Textarea.test.tsx.snap index 85164a08bac..291f828423b 100644 --- a/src/__tests__/__snapshots__/Textarea.test.tsx.snap +++ b/src/__tests__/__snapshots__/Textarea.test.tsx.snap @@ -49,7 +49,8 @@ exports[`Textarea renders consistently 1`] = ` .c0:focus-within { border-color: #0969da; - box-shadow: 0 0 0 3px rgba(9,105,218,0.3); + outline: none; + box-shadow: inset 0 0 0 1px #0969da; } .c0 > textarea { diff --git a/src/__tests__/__snapshots__/UnderlineNavLink.test.tsx.snap b/src/__tests__/__snapshots__/UnderlineNavLink.test.tsx.snap index efa505ce3e9..aa17839844d 100644 --- a/src/__tests__/__snapshots__/UnderlineNavLink.test.tsx.snap +++ b/src/__tests__/__snapshots__/UnderlineNavLink.test.tsx.snap @@ -19,8 +19,8 @@ exports[`UnderlineNav.Link adds activeClassName={SELECTED_CLASS} when it gets a -webkit-text-decoration: none; text-decoration: none; border-bottom-color: rgba(175,184,193,0.2); - -webkit-transition: 0.2s ease; - transition: 0.2s ease; + -webkit-transition: border-bottom-color 0.2s ease; + transition: border-bottom-color 0.2s ease; } .c0:hover .PRC-UnderlineNav-octicon, @@ -37,6 +37,22 @@ exports[`UnderlineNav.Link adds activeClassName={SELECTED_CLASS} when it gets a color: #24292f; } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -8px; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -8px; +} +
@@ -105,8 +137,8 @@ exports[`UnderlineNav.Link respects the "selected" prop 1`] = ` -webkit-text-decoration: none; text-decoration: none; border-bottom-color: rgba(175,184,193,0.2); - -webkit-transition: 0.2s ease; - transition: 0.2s ease; + -webkit-transition: border-bottom-color 0.2s ease; + transition: border-bottom-color 0.2s ease; } .c0:hover .PRC-UnderlineNav-octicon, @@ -123,6 +155,22 @@ exports[`UnderlineNav.Link respects the "selected" prop 1`] = ` color: #24292f; } +.c0:focus:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -8px; +} + +.c0:focus:not(:disabled):not(:focus-visible) { + outline: solid 1px transparent; +} + +.c0:focus-visible:not(:disabled) { + box-shadow: none; + outline: 2px solid #0969da; + outline-offset: -8px; +} +