Skip to content

Commit 8f8181b

Browse files
authored
Fix fullWidth focus on Select component (#660)
* fix fullWidth focus on Select component * Create sixty-rules-trade.md * update changeset * add back aria-label
1 parent 6f2949b commit 8f8181b

17 files changed

+154
-11
lines changed

.changeset/sixty-rules-trade.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/react-brand': patch
3+
---
4+
5+
Fixed width of the focus outline in the `Select` component to fill the entire width of the control when `fullWidth` option has bene applied.

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Loading
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from 'react'
2+
import {Meta, StoryFn} from '@storybook/react'
3+
import {userEvent, waitFor} from '@storybook/test'
4+
5+
import {Select} from '.'
6+
7+
export default {
8+
title: 'Components/Forms/Select/Features',
9+
component: Select,
10+
} as Meta<typeof Select>
11+
12+
const Template: StoryFn<typeof Select> = args => (
13+
<Select {...args} aria-label="Standalone select input" defaultValue="select a handle" {...args}>
14+
<Select.Option value="select a handle" disabled>
15+
Select a handle
16+
</Select.Option>
17+
<Select.Option value="mona">Monalisa</Select.Option>
18+
<Select.Option value="hubot">Hubot</Select.Option>
19+
</Select>
20+
)
21+
22+
export const FullWidth = Template.bind({})
23+
FullWidth.args = {
24+
fullWidth: true,
25+
}
26+
27+
export const FullWidthFocussed = Template.bind({})
28+
FullWidthFocussed.args = {
29+
fullWidth: true,
30+
}
31+
32+
FullWidthFocussed.play = async () => {
33+
await waitFor(async () => {
34+
userEvent.tab()
35+
})
36+
}
37+
38+
export const Disabled = Template.bind({})
39+
Disabled.args = {
40+
disabled: true,
41+
}
42+
43+
export const Large = Template.bind({})
44+
Large.args = {
45+
size: 'large',
46+
}
47+
48+
export const LargeFullWidth = Template.bind({})
49+
LargeFullWidth.args = {
50+
fullWidth: true,
51+
size: 'large',
52+
}
53+
54+
export const ValidationSuccess = Template.bind({})
55+
ValidationSuccess.args = {
56+
validationStatus: 'success',
57+
}
58+
59+
export const ValidationError = Template.bind({})
60+
ValidationError.args = {
61+
validationStatus: 'error',
62+
}

packages/react/src/forms/Select/Select.module.css

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
}
5757

5858
.Select-wrapper--medium::after {
59-
margin-inline-end: var(--base-size-8);
59+
margin-inline-end: calc(var(--brand-control-medium-paddingInline-condensed) / 2);
6060
}
6161

6262
.Select--medium {
@@ -72,7 +72,7 @@
7272
}
7373

7474
.Select-wrapper--large::after {
75-
margin-inline-end: var(--base-size-12);
75+
margin-inline-end: var(--base-size-8);
7676
}
7777

7878
.Select--large {
@@ -105,10 +105,12 @@
105105
}
106106

107107
.Select-wrapper::after {
108+
content: '';
109+
position: absolute;
110+
right: 0;
108111
width: var(--base-size-16);
109112
height: var(--base-size-16);
110113
pointer-events: none;
111-
content: '';
112114
background-color: var(--brand-control-color-fg-default);
113115
mask: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0iIzU4NjA2OSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNC40MjcgOS40MjdsMy4zOTYgMy4zOTZhLjI1MS4yNTEgMCAwMC4zNTQgMGwzLjM5Ni0zLjM5NkEuMjUuMjUgMCAwMDExLjM5NiA5SDQuNjA0YS4yNS4yNSAwIDAwLS4xNzcuNDI3ek00LjQyMyA2LjQ3TDcuODIgMy4wNzJhLjI1LjI1IDAgMDEuMzU0IDBMMTEuNTcgNi40N2EuMjUuMjUgMCAwMS0uMTc3LjQyN0g0LjZhLjI1LjI1IDAgMDEtLjE3Ny0uNDI3eiIgLz48L3N2Zz4=');
114116
-webkit-mask: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0iIzU4NjA2OSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNC40MjcgOS40MjdsMy4zOTYgMy4zOTZhLjI1MS4yNTEgMCAwMC4zNTQgMGwzLjM5Ni0zLjM5NkEuMjUuMjUgMCAwMDExLjM5NiA5SDQuNjA0YS4yNS4yNSAwIDAwLS4xNzcuNDI3ek00LjQyMyA2LjQ3TDcuODIgMy4wNzJhLjI1LjI1IDAgMDEuMzU0IDBMMTEuNTcgNi40N2EuMjUuMjUgMCAwMS0uMTc3LjQyN0g0LjZhLjI1LjI1IDAgMDEtLjE3Ny0uNDI3eiIgLz48L3N2Zz4=');

packages/react/src/forms/Select/Select.stories.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,10 @@ export const Playground: StoryFn<typeof Select> = args => (
6262
</Select>
6363
)
6464

65-
Playground.storyName = 'Select - Playground'
65+
export const Default: StoryFn<typeof Select> = () => (
66+
<Select aria-label="Standalone select input">
67+
<Select.Option value="select a handle">Select a handle</Select.Option>
68+
<Select.Option value="mona">Monalisa</Select.Option>
69+
<Select.Option value="hubot">Hubot</Select.Option>
70+
</Select>
71+
)

packages/react/src/forms/Select/Select.visual.spec.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,78 @@ import {test, expect} from '@playwright/test'
77

88
// eslint-disable-next-line i18n-text/no-en
99
test.describe('Visual Comparison: Select', () => {
10-
test('Select / Select - Playground', async ({page}) => {
10+
test('Select / Full Width', async ({page}) => {
11+
await page.goto(
12+
'http://localhost:6006/iframe.html?args=&id=components-forms-select-features--full-width&viewMode=story',
13+
)
14+
15+
await page.waitForTimeout(500)
16+
expect(await page.screenshot()).toMatchSnapshot()
17+
})
18+
19+
test('Select / Full Width Focussed', async ({page}) => {
20+
await page.goto(
21+
'http://localhost:6006/iframe.html?args=&id=components-forms-select-features--full-width-focussed&viewMode=story',
22+
)
23+
24+
await page.waitForTimeout(500)
25+
expect(await page.screenshot()).toMatchSnapshot()
26+
})
27+
28+
test('Select / Disabled', async ({page}) => {
29+
await page.goto(
30+
'http://localhost:6006/iframe.html?args=&id=components-forms-select-features--disabled&viewMode=story',
31+
)
32+
33+
await page.waitForTimeout(500)
34+
expect(await page.screenshot()).toMatchSnapshot()
35+
})
36+
37+
test('Select / Large', async ({page}) => {
38+
await page.goto('http://localhost:6006/iframe.html?args=&id=components-forms-select-features--large&viewMode=story')
39+
40+
await page.waitForTimeout(500)
41+
expect(await page.screenshot()).toMatchSnapshot()
42+
})
43+
44+
test('Select / Large Full Width', async ({page}) => {
45+
await page.goto(
46+
'http://localhost:6006/iframe.html?args=&id=components-forms-select-features--large-full-width&viewMode=story',
47+
)
48+
49+
await page.waitForTimeout(500)
50+
expect(await page.screenshot()).toMatchSnapshot()
51+
})
52+
53+
test('Select / Validation Success', async ({page}) => {
54+
await page.goto(
55+
'http://localhost:6006/iframe.html?args=&id=components-forms-select-features--validation-success&viewMode=story',
56+
)
57+
58+
await page.waitForTimeout(500)
59+
expect(await page.screenshot()).toMatchSnapshot()
60+
})
61+
62+
test('Select / Validation Error', async ({page}) => {
63+
await page.goto(
64+
'http://localhost:6006/iframe.html?args=&id=components-forms-select-features--validation-error&viewMode=story',
65+
)
66+
67+
await page.waitForTimeout(500)
68+
expect(await page.screenshot()).toMatchSnapshot()
69+
})
70+
71+
test('Select / Playground', async ({page}) => {
1172
await page.goto('http://localhost:6006/iframe.html?args=&id=components-forms-select--playground&viewMode=story')
1273

1374
await page.waitForTimeout(500)
1475
expect(await page.screenshot()).toMatchSnapshot()
1576
})
77+
78+
test('Select / Default', async ({page}) => {
79+
await page.goto('http://localhost:6006/iframe.html?args=&id=components-forms-select--default&viewMode=story')
80+
81+
await page.waitForTimeout(500)
82+
expect(await page.screenshot()).toMatchSnapshot()
83+
})
1684
})
Loading
Loading
Loading

0 commit comments

Comments
 (0)