Skip to content

Commit c199131

Browse files
authored
Background styles for focused action list items (#1158)
1 parent 2e3c3f7 commit c199131

File tree

8 files changed

+83
-25
lines changed

8 files changed

+83
-25
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/components": patch
3+
---
4+
5+
Add background styles for focused action list items, instead of using default `outline`

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"author": "GitHub, Inc.",
4747
"license": "MIT",
4848
"dependencies": {
49-
"@primer/octicons-react": "^11.3.0",
49+
"@primer/octicons-react": "^13.0.0",
5050
"@primer/primitives": "0.0.0-202121782215",
5151
"@styled-system/css": "5.1.5",
5252
"@styled-system/props": "5.1.4",

src/ActionList/Item.tsx

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,37 @@ import {ItemInput} from './List'
77
import styled from 'styled-components'
88
import {StyledHeader} from './Header'
99
import {StyledDivider} from './Divider'
10+
import {useColorSchemeVar, useTheme} from '../ThemeProvider'
11+
12+
/**
13+
* These colors are not yet in our default theme. Need to remove this once they are added.
14+
*/
15+
const customItemThemes = {
16+
default: {
17+
hover: {
18+
light: 'rgba(46, 77, 108, 0.06)',
19+
dark: 'rgba(201, 206, 212, 0.12)',
20+
dark_dimmed: 'rgba(201, 206, 212, 0.12)'
21+
},
22+
focus: {
23+
light: 'rgba(54, 77, 100, 0.16)',
24+
dark: 'rgba(201, 206, 212, 0.24)',
25+
dark_dimmed: 'rgba(201, 206, 212, 0.24)'
26+
}
27+
},
28+
danger: {
29+
hover: {
30+
light: 'rgba(234, 74, 90, 0.08)',
31+
dark: 'rgba(248, 81, 73, 0.16)',
32+
dark_dimmed: 'rgba(248, 81, 73, 0.16)'
33+
},
34+
focus: {
35+
light: 'rgba(234, 74, 90, 0.14)',
36+
dark: 'rgba(248, 81, 73, 0.24)',
37+
dark_dimmed: 'rgba(248, 81, 73, 0.24)'
38+
}
39+
}
40+
} as const
1041

1142
/**
1243
* Contract for props passed to the `Item` component.
@@ -95,7 +126,6 @@ const getItemVariant = (variant = 'default', disabled?: boolean) => {
95126
color: get('colors.text.disabled'),
96127
iconColor: get('colors.text.disabled'),
97128
annotationColor: get('colors.text.disabled'),
98-
hoverBackground: 'inherit',
99129
hoverCursor: 'default'
100130
}
101131
}
@@ -106,15 +136,13 @@ const getItemVariant = (variant = 'default', disabled?: boolean) => {
106136
color: get('colors.text.danger'),
107137
iconColor: get('colors.icon.danger'),
108138
annotationColor: get('colors.text.disabled'),
109-
hoverBackground: get('colors.bg.danger'),
110139
hoverCursor: 'pointer'
111140
}
112141
default:
113142
return {
114143
color: 'inherit',
115-
iconColor: get('colors.text.disabled'),
116-
annotationColor: get('colors.text.disabled'),
117-
hoverBackground: get('colors.selectMenu.tapHighlight'),
144+
iconColor: get('colors.text.secondary'),
145+
annotationColor: get('colors.text.secondary'),
118146
hoverCursor: 'pointer'
119147
}
120148
}
@@ -125,7 +153,13 @@ const StyledItemContent = styled.div`
125153
`
126154

127155
const StyledItem = styled.div<
128-
{variant: ItemProps['variant']; showDivider: ItemProps['showDivider']; item?: ItemInput} & SxProp
156+
{
157+
variant: ItemProps['variant']
158+
showDivider: ItemProps['showDivider']
159+
item?: ItemInput
160+
hoverBackground: string
161+
focusBackground: string
162+
} & SxProp
129163
>`
130164
/* 6px vertical padding + 20px line height = 32px total height
131165
*
@@ -139,7 +173,7 @@ const StyledItem = styled.div<
139173
140174
@media (hover: hover) and (pointer: fine) {
141175
:hover {
142-
background: ${({variant, item}) => getItemVariant(variant, item?.disabled).hoverBackground};
176+
background: ${({hoverBackground}) => hoverBackground};
143177
cursor: ${({variant, item}) => getItemVariant(variant, item?.disabled).hoverCursor};
144178
}
145179
}
@@ -159,6 +193,11 @@ const StyledItem = styled.div<
159193
}
160194
}
161195
196+
&:focus {
197+
background: ${({focusBackground}) => focusBackground};
198+
outline: none;
199+
}
200+
162201
${sx}
163202
`
164203

@@ -176,18 +215,21 @@ const BaseVisualContainer = styled.div<{variant?: ItemProps['variant']; disabled
176215
flex-shrink: 0;
177216
display: flex;
178217
flex-direction: column;
218+
flex-shrink: 0;
179219
justify-content: center;
180220
margin-right: ${get('space.2')};
221+
`
181222

223+
const ColoredVisualContainer = styled(BaseVisualContainer)`
182224
svg {
183225
fill: ${({variant, disabled}) => getItemVariant(variant, disabled).iconColor};
184226
font-size: ${get('fontSizes.0')};
185227
}
186228
`
187229

188-
const LeadingVisualContainer = styled(BaseVisualContainer)``
230+
const LeadingVisualContainer = styled(ColoredVisualContainer)``
189231

190-
const TrailingVisualContainer = styled(BaseVisualContainer)`
232+
const TrailingVisualContainer = styled(ColoredVisualContainer)`
191233
color: ${({variant, disabled}) => getItemVariant(variant, disabled).annotationColor}};
192234
margin-left: auto;
193235
margin-right: 0;
@@ -260,6 +302,12 @@ export function Item(itemProps: Partial<ItemProps> & {item?: ItemInput}): JSX.El
260302
[onAction, disabled, itemProps, onClick]
261303
)
262304

305+
const customItemTheme = customItemThemes[variant]
306+
const hoverBackground = useColorSchemeVar(customItemTheme.hover, 'inherit')
307+
const focusBackground = useColorSchemeVar(customItemTheme.focus, 'inherit')
308+
309+
const {theme} = useTheme()
310+
263311
return (
264312
<StyledItem
265313
tabIndex={disabled ? undefined : -1}
@@ -270,9 +318,11 @@ export function Item(itemProps: Partial<ItemProps> & {item?: ItemInput}): JSX.El
270318
data-id={id}
271319
onKeyPress={keyPressHandler}
272320
onClick={clickHandler}
321+
hoverBackground={disabled ? 'inherit' : hoverBackground}
322+
focusBackground={disabled ? 'inherit' : focusBackground}
273323
>
274324
{!!selected === selected && (
275-
<LeadingVisualContainer>
325+
<BaseVisualContainer>
276326
{selectionVariant === 'multiple' ? (
277327
<>
278328
{/*
@@ -282,9 +332,9 @@ export function Item(itemProps: Partial<ItemProps> & {item?: ItemInput}): JSX.El
282332
<input type="checkbox" checked={selected} aria-label={text} readOnly aria-readonly="false" />
283333
</>
284334
) : (
285-
selected && <CheckIcon />
335+
selected && <CheckIcon fill={theme?.colors.text.primary} />
286336
)}
287-
</LeadingVisualContainer>
337+
</BaseVisualContainer>
288338
)}
289339
{LeadingVisual && (
290340
<LeadingVisualContainer variant={variant} disabled={disabled}>

src/ThemeProvider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export function useTheme() {
9090
return React.useContext(ThemeContext)
9191
}
9292

93-
export function useColorSchemeVar(values: Partial<Record<string, string>>, fallback?: string) {
93+
export function useColorSchemeVar(values: Partial<Record<string, string>>, fallback: string) {
9494
const {colorScheme = ''} = useTheme()
9595
return values[colorScheme] ?? fallback
9696
}

src/__tests__/ThemeProvider.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -377,11 +377,14 @@ describe('useColorSchemeVar', () => {
377377
}
378378

379379
function CustomBg() {
380-
const customBg = useColorSchemeVar({
381-
light: 'red',
382-
dark: 'blue',
383-
dark_dimmed: 'green'
384-
})
380+
const customBg = useColorSchemeVar(
381+
{
382+
light: 'red',
383+
dark: 'blue',
384+
dark_dimmed: 'green'
385+
},
386+
'inherit'
387+
)
385388

386389
return <Text bg={customBg}>Hello</Text>
387390
}

src/__tests__/__snapshots__/CircleOcticon.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ exports[`CircleOcticon renders consistently 1`] = `
4444
>
4545
<svg
4646
aria-hidden="true"
47-
className="octicon"
47+
className="octicon octicon-check"
4848
dangerouslySetInnerHTML={
4949
Object {
5050
"__html": "<path fill-rule=\\"evenodd\\" d=\\"M21.03 5.72a.75.75 0 010 1.06l-11.5 11.5a.75.75 0 01-1.072-.012l-5.5-5.75a.75.75 0 111.084-1.036l4.97 5.195L19.97 5.72a.75.75 0 011.06 0z\\"></path>",

src/__tests__/__snapshots__/Dialog.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Array [
160160
>
161161
<svg
162162
aria-hidden="true"
163-
className="octicon"
163+
className="octicon octicon-x"
164164
dangerouslySetInnerHTML={
165165
Object {
166166
"__html": "<path fill-rule=\\"evenodd\\" d=\\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\\"></path>",

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,10 +1833,10 @@
18331833
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.7.2.tgz#00644825ce478065101954bdb2f7f2d062365b7f"
18341834
integrity sha512-3LC1/M2ZFcmDrSkD1byT/hZzoPehZkDucbDShLnZ+/Gwkr6CAxiQ2kWy1UtJeLGADe58hTWkx22YEHqjPGUKzw==
18351835

1836-
"@primer/octicons-react@^11.3.0":
1837-
version "11.3.0"
1838-
resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-11.3.0.tgz#794641d95ff5749a9438a2e0c201956b2a377b60"
1839-
integrity sha512-4sVhkrBKuj3h+PFw69yOyO/l3nQB/mm95V+Kz7LRSlIrbZr6hZarZD5Ft4ewdONPROkIHQM/6KSK90+OAimxsQ==
1836+
"@primer/octicons-react@^13.0.0":
1837+
version "13.0.0"
1838+
resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-13.0.0.tgz#a7f2288fd9cf9cabc1e75553a0dd9f00d74b68c1"
1839+
integrity sha512-j5XppNRCvgaMZLPsVvvmp6GSh7P5pq6PUbsfLNBWi2Kz3KYDeoGDWbPr5MjoxFOGUn6Hjnt6qjHPRxahd11vLQ==
18401840

18411841
18421842
version "0.0.0-202121782215"

0 commit comments

Comments
 (0)