Skip to content

Commit

Permalink
Merge pull request #14 from GreenTeaCake/add-switch
Browse files Browse the repository at this point in the history
Add switch
  • Loading branch information
GreenTeaCake committed Apr 7, 2024
2 parents a73d597 + b76bdd9 commit 21d1222
Show file tree
Hide file tree
Showing 16 changed files with 245 additions and 181 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
"start": "stencil build --dev --watch --serve",
"test": "stencil test --spec --e2e",
"test:unit": "stencil test --spec",
"test:unit:watch": "stencil test --spec --watchAll",
"test:e2e": "stencil test --e2e",
"test.watch": "stencil test --spec --e2e --watchAll",
"test:e2e:watch": "stencil test --e2e --watchAll",
"generate": "stencil generate",
"prepare": "husky",
"storybook": "storybook dev -p 6006",
Expand Down
32 changes: 0 additions & 32 deletions src/components/my-component/my-component.e2e.ts

This file was deleted.

15 changes: 0 additions & 15 deletions src/components/my-component/my-component.scss

This file was deleted.

35 changes: 0 additions & 35 deletions src/components/my-component/my-component.spec.ts

This file was deleted.

26 changes: 0 additions & 26 deletions src/components/my-component/my-component.stories.ts

This file was deleted.

33 changes: 0 additions & 33 deletions src/components/my-component/my-component.tsx

This file was deleted.

42 changes: 42 additions & 0 deletions src/components/switch/switch.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
$switch-width: 40px;
$switch-height: 20px;

$marker-size: 16px;
$marker-color: #ffffff;

$spacing: calc(($switch-height - $marker-size) / 2);

:host {
display: inline-block;
height: $switch-height;

.gtc-switch {
display: inline-block;
width: $switch-width;
height: $switch-height;
border-radius: calc($switch-height / 2);
background-color: #c9c7c7;
position: relative;
cursor: pointer;

.gtc-switch-marker {
display: inline-block;
width: $marker-size;
height: $marker-size;
border-radius: calc($marker-size / 2);
background-color: $marker-color;

position: absolute;
top: $spacing;
left: $spacing;
}

&__checked {
background-color: #398368;

.gtc-switch-marker {
left: calc($switch-width - $marker-size - $spacing);
}
}
}
}
28 changes: 28 additions & 0 deletions src/components/switch/switch.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
type Args = {
checked?: boolean;
label: string;
};

type Example<T> = {
args: T;
};

export default {
title: 'Components/Switch',
tags: ['autodocs'],
render: (args: Args) => {
const { checked, label } = args;
return `<gtc-switch checked="${checked}" label="${label}" />`;
},
argTypes: {
checked: { control: 'boolean' },
label: { control: 'text' },
},
};

export const Basic: Example<Args> = {
args: {
checked: true,
label: 'Switch example',
},
};
70 changes: 70 additions & 0 deletions src/components/switch/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Component, Event, type EventEmitter, Host, Prop, h } from '@stencil/core';

/**
* @link https://www.w3.org/WAI/ARIA/apg/patterns/switch/
* @link https://www.w3.org/WAI/ARIA/apg/patterns/switch/examples/switch/
* @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/switch_role
*/
@Component({
tag: 'gtc-switch',
shadow: true,
styleUrl: 'switch.scss',
})
export class Switch {
/**
* The reflective property that allows to control the state of the switch.
*
* If `true`, the switch is checked.
*/
@Prop({ reflect: true }) public checked = false;

/**
* Text value used for `aria-label` property.
*/
@Prop() public label!: string;

/**
* Emitted when the value has changed
*/
@Event() private change: EventEmitter<boolean>;

render() {
return (
<Host>
<div
aria-checked={this.checked ? 'true' : 'false'}
aria-label={this.label}
class={{
'gtc-switch': true,
'gtc-switch__checked': this.checked,
}}
onClick={this.onClick}
onKeyDown={this.onKeyDown}
role="switch"
tabIndex={0}
>
<div class="gtc-switch-marker" />
</div>
</Host>
);
}

private onClick = (event: MouseEvent) => {
event.stopPropagation();
this.change.emit(!this.checked);
};

private onKeyDown = (event: KeyboardEvent) => {
switch (event.key) {
case 'Enter':
case ' ': {
event.stopPropagation();
this.change.emit(!this.checked);
break;
}
default: {
// nothing to do
}
}
};
}
49 changes: 49 additions & 0 deletions src/components/switch/test/switch.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { newE2EPage } from '@stencil/core/testing';

describe('gtc-switch', () => {
it('renders', async () => {
const page = await newE2EPage();
await page.setContent('<gtc-switch></gtc-switch>');

const element = await page.find('gtc-switch');
expect(element).toHaveClass('hydrated');
});

describe('intially checked', () => {
it('renders changes to the checked property', async () => {
const page = await newE2EPage();

await page.setContent('<gtc-switch checked="true"></gtc-switch>');
const component = await page.find('gtc-switch');
const element = await page.find('gtc-switch >>> div.gtc-switch');
expect(element.getAttribute('aria-checked')).toEqual(`true`);

component.setProperty('checked', 'false');
await page.waitForChanges();
expect(element.getAttribute('aria-checked')).toEqual(`false`);

component.setProperty('checked', 'true');
await page.waitForChanges();
expect(element.getAttribute('aria-checked')).toEqual(`true`);
});
});

describe('intially unchecked', () => {
it('renders changes to the checked property', async () => {
const page = await newE2EPage();

await page.setContent('<gtc-switch checked="false"></gtc-switch>');
const component = await page.find('gtc-switch');
const element = await page.find('gtc-switch >>> div.gtc-switch');
expect(element.getAttribute('aria-checked')).toEqual(`false`);

component.setProperty('checked', 'true');
await page.waitForChanges();
expect(element.getAttribute('aria-checked')).toEqual(`true`);

component.setProperty('checked', 'false');
await page.waitForChanges();
expect(element.getAttribute('aria-checked')).toEqual(`false`);
});
});
});
Loading

0 comments on commit 21d1222

Please sign in to comment.