Skip to content

Commit f5160f8

Browse files
refactor: label docs and tests
1 parent f4191c3 commit f5160f8

File tree

8 files changed

+92
-101
lines changed

8 files changed

+92
-101
lines changed
Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,25 @@
1-
import { component$, useStyles$ } from '@builder.io/qwik';
1+
import { component$, useStylesScoped$ } from '@builder.io/qwik';
22
import { Label } from '@qwik-ui/headless';
3-
import styles from './label.css?inline';
3+
import styles from '../snippets/label.css?inline';
44

55
export default component$(() => {
6-
useStyles$(styles);
6+
useStylesScoped$(styles);
77

88
return (
99
<div
10+
class="label-container"
1011
style={{
1112
display: 'flex',
1213
padding: '0 20px',
1314
flexWrap: 'wrap',
1415
gap: 15,
1516
alignItems: 'center',
1617
}}
17-
data-testid="root"
1818
>
19-
<Label class="LabelRoot" for="firstName" data-testid="label">
19+
<Label class="label" for="firstName">
2020
First name
2121
</Label>
22-
<input
23-
class="Input"
24-
type="text"
25-
id="firstName"
26-
placeholder="John Doe"
27-
data-testid="input"
28-
/>
22+
<input class="input" type="text" id="firstName" placeholder="John Doe" />
2923
</div>
3024
);
3125
});

apps/website/src/routes/docs/headless/label/index.mdx

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ Renders an accessible label associated with controls.
1414

1515
<Showcase name="hero" />
1616

17-
### Features
17+
This component is based on the native label element, it will automatically apply the correct labelling when wrapping controls or using the for attribute.
18+
19+
For your own custom controls to work correctly, ensure they use native elements such as button or input as a base.
20+
21+
## ✨ Features
1822

1923
<FeatureList
2024
features={[
@@ -23,34 +27,9 @@ Renders an accessible label associated with controls.
2327
]}
2428
/>
2529

26-
<div class="mb-6 flex flex-col gap-2">
27-
[View Source Code ↗️](https://github.com/qwikifiers/qwik-ui/tree/main/packages/kit-headless/src/components/label)
28-
29-
[Report an issue 🚨](https://github.com/qwikifiers/qwik-ui/issues)
30-
31-
[Edit This Page 🗒️](<https://github.com/qwikifiers/qwik-ui/edit/main/apps/website/src/routes/docs/headless/(components)/label/index.mdx>)
32-
33-
</div>
34-
3530
## Building blocks
3631

37-
```tsx
38-
import { component$, useStyles$ } from '@builder.io/qwik';
39-
import { Label } from '@qwik-ui/headless';
40-
41-
export default component$(() => {
42-
return (
43-
<div>
44-
<Label for="firstName">First name</Label>
45-
<input type="text" id="firstName" placeholder="John Doe" />
46-
</div>
47-
);
48-
});
49-
```
50-
51-
## Accessibility
52-
53-
This component is based on the native label element, it will automatically apply the correct labelling when wrapping controls or using the for attribute. For your own custom controls to work correctly, ensure they use native elements such as button or input as a base.
32+
<CodeSnippet name="building-blocks" />
5433

5534
### 🎨 Anatomy
5635

@@ -62,3 +41,15 @@ This component is based on the native label element, it will automatically apply
6241
},
6342
]}
6443
/>
44+
45+
## Why use a headless label?
46+
47+
The Qwik UI headless label component keeps focus on the input when double clicking.
48+
49+
The native behavior will try to select and focus the text of the label. This is often times not the desired behavior.
50+
51+
{/* Not caught up to main, but would have an issues prop here from FeatureList */}
52+
53+
## Example CSS
54+
55+
<CodeSnippet name="label.css" />
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { component$ } from '@builder.io/qwik';
2+
import { Label } from '@qwik-ui/headless';
3+
4+
export default component$(() => {
5+
return (
6+
<div>
7+
<Label for="firstName">First name</Label>
8+
<input type="text" id="firstName" placeholder="John Doe" />
9+
</div>
10+
);
11+
});

apps/website/src/routes/docs/headless/label/examples/label.css renamed to apps/website/src/routes/docs/headless/label/snippets/label.css

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ input {
33
all: unset;
44
}
55

6-
.LabelRoot {
6+
.label-container {
77
font-size: 15px;
88
font-weight: 500;
99
line-height: 35px;
10-
color: black;
10+
color: hsl(var(--foreground));
1111
}
1212

13-
.Input {
13+
input {
1414
width: 200px;
1515
display: inline-flex;
1616
align-items: center;
@@ -20,13 +20,15 @@ input {
2020
height: 35px;
2121
font-size: 15px;
2222
line-height: 1;
23-
background-color: white;
24-
box-shadow: 0 0 0 1px black;
23+
background-color: hsl(var(--background));
24+
box-shadow: 0 0 0 1px hsl(var(--foreground));
2525
}
26-
.Input:focus {
27-
box-shadow: 0 0 0 2px black;
26+
27+
input:focus {
28+
box-shadow: 0 0 0 2px hsl(var(--foreground));
2829
}
29-
.Input::selection {
30+
31+
input::selection {
3032
background-color: var(--black-a9);
3133
color: white;
3234
}

apps/website/src/routes/docs/headless/progress/index.mdx

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,11 @@ Qwik UI's Progress implementation follows the [WAI-Aria](https://www.w3.org/WAI/
2020
features={['Provides context for assistive technology to read the progress of a task.']}
2121
/>
2222

23-
<div class="mb-6 flex flex-col gap-2">
24-
[View Source Code ↗️](https://github.com/qwikifiers/qwik-ui/tree/main/packages/kit-headless/src/components/progress)
25-
26-
[Report an issue 🚨](https://github.com/qwikifiers/qwik-ui/issues)
27-
28-
[Edit This Page 🗒️](<https://github.com/qwikifiers/qwik-ui/edit/main/apps/website/src/routes/docs/headless/(components)/progress/index.mdx>)
29-
30-
</div>
31-
3223
## Building blocks
3324

34-
```tsx
35-
import { component$ } from '@builder.io/qwik';
36-
import { Progress, ProgressIndicator } from '@qwik-ui/headless';
37-
38-
export default component$(() => {
39-
const progress = 30;
40-
41-
return (
42-
<Progress value={progress} class="progress">
43-
<ProgressIndicator
44-
class="progress-indicator"
45-
style={{
46-
transform: `translateX(-${100 - progress}%)`,
47-
}}
48-
/>
49-
</Progress>
50-
);
51-
});
52-
```
25+
<CodeSnippet name="building-blocks" />
26+
27+
{/* TODO: Match docs conventions with the select, collapsible, or label. */}
5328

5429
## Accessibility
5530

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { component$ } from '@builder.io/qwik';
2+
import { Progress, ProgressIndicator } from '@qwik-ui/headless';
3+
4+
export default component$(() => {
5+
const progress = 30;
6+
7+
return (
8+
<Progress value={progress} class="progress">
9+
<ProgressIndicator
10+
class="progress-indicator"
11+
style={{
12+
transform: `translateX(-${100 - progress}%)`,
13+
}}
14+
/>
15+
</Progress>
16+
);
17+
});

packages/kit-headless/src/components/label/label.driver.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,17 @@ import { type Locator, type Page } from '@playwright/test';
22
export type DriverLocator = Locator | Page;
33

44
export function createTestDriver<T extends DriverLocator>(rootLocator: T) {
5-
const getRoot = () => {
6-
return rootLocator;
7-
};
8-
95
const getLabel = () => {
10-
return rootLocator.getByTestId('label');
6+
return rootLocator.locator('label');
117
};
128

13-
const getForElement = () => {
14-
return rootLocator.getByTestId('input');
9+
const getInput = () => {
10+
return rootLocator.locator('input');
1511
};
1612

1713
return {
1814
...rootLocator,
19-
getRoot,
2015
getLabel,
21-
getForElement,
16+
getInput,
2217
};
2318
}

packages/kit-headless/src/components/label/label.test.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,38 @@ import { createTestDriver } from './label.driver';
33

44
async function setup(page: Page, exampleName: string) {
55
await page.goto(`/headless/label/${exampleName}`);
6-
const driver = createTestDriver(page.getByTestId('root'));
7-
const { getLabel, getForElement } = driver;
6+
const driver = createTestDriver(page);
87

9-
return { driver, getLabel, getForElement };
8+
return { driver };
109
}
1110

12-
test.describe('Label usaged', () => {
13-
test('should have a label', async ({ page }) => {
14-
const { getLabel } = await setup(page, 'hero');
15-
await expect(getLabel()).toBeVisible();
11+
test.describe('Label usage', () => {
12+
test(`GIVEN a label
13+
WHEN a label is rendered
14+
THEN it should be visible
15+
`, async ({ page }) => {
16+
const { driver: d } = await setup(page, 'hero');
17+
18+
await expect(d.getLabel()).toBeVisible();
1619
});
1720

18-
test('should focus on for', async ({ page }) => {
19-
const { getLabel, getForElement } = await setup(page, 'hero');
20-
const label = getLabel();
21-
const forElement = getForElement();
21+
test(`GIVEN a label and an input
22+
WHEN the label is clicked
23+
THEN the input should be focused
24+
`, async ({ page }) => {
25+
const { driver: d } = await setup(page, 'hero');
2226

23-
await label.click();
24-
await expect(forElement).toBeFocused();
27+
await d.getLabel().click();
28+
await expect(d.getInput()).toBeFocused();
2529
});
2630

27-
test('should not select the text on label', async ({ page }) => {
28-
const { getLabel } = await setup(page, 'hero');
29-
const label = getLabel();
31+
test(`GIVEN a label
32+
WHEN the label is double clicked
33+
THEN the label text should not be selected
34+
`, async ({ page }) => {
35+
const { driver: d } = await setup(page, 'hero');
3036

31-
await label.dblclick();
37+
await d.getLabel().dblclick();
3238
const selection = await page.evaluate(() => window.getSelection()?.toString());
3339
expect(selection).toBeFalsy();
3440
});

0 commit comments

Comments
 (0)