Skip to content

Commit

Permalink
Web Component Switch (#26517)
Browse files Browse the repository at this point in the history
* switch init

* provides export path

* yarn change

* removes dead code

* adds table docs

* updates attribute to use attr syntax

* removes on/off text for label only

* addresses PR feedback

* updates label font-weight

* removes dead code

* updates styles

* adds required styles for switch

* Update change/@fluentui-web-components-a74d6518-0d94-4e22-bd9f-70ea63a066ab.json

Co-authored-by: Miroslav Stastny <[email protected]>

* removes unuses import

* api report

* removes dead code

* updates styles and story

* optimizes styles

* reverts api report

* removes unchecked checked message styles

* updates labelPosition type to include undefined

* updates helper import

* optimizes css

* cleans up styles

* optimizes styles

* uses design tokens

* removes dead import

* removes dead code

* removes required styling from label

* adds switch readme

* fixes docs

* fixes switch hover styles

* formats switch styles

* alphabetizes exports

---------

Co-authored-by: Miroslav Stastny <[email protected]>
  • Loading branch information
2 people authored and radium-v committed May 2, 2024
1 parent 56fb795 commit 9f0ae19
Show file tree
Hide file tree
Showing 12 changed files with 431 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "feat(switch): Add switch web component",
"packageName": "@fluentui/web-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
4 changes: 4 additions & 0 deletions packages/web-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
"types": "./dist/esm/progress-bar/define.d.ts",
"default": "./dist/esm/progress-bar/define.js"
},
"./switch": {
"types": "./dist/esm/switch/define.d.ts",
"default": "./dist/esm/switch/define.js"
},
"./spinner": {
"types": "./dist/esm/spinner/define.d.ts",
"default": "./dist/esm/spinner/define.js"
Expand Down
1 change: 1 addition & 0 deletions packages/web-components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './badge/index.js';
export * from './counter-badge/index.js';
export * from './progress-bar/index.js';
export * from './spinner/index.js';
export * from './switch/index.js';
export * from './text/index.js';

export * from './theme/index.js';
121 changes: 121 additions & 0 deletions packages/web-components/src/switch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Switch

> An implementation of a [switch](https://w3c.github.io/aria/#switch) as a form-connected web-component.
<br />

## **Design Spec**

[Link to Switch Design Spec in Figma](https://www.figma.com/file/TPQVDN5cxYBqkP9urETsCp/Switch?node-id=655%3A1158&t=kJMaMie08ejCnL7H-0)

<br />

## **Engineering Spec**

Fluent WC3 Switch extends from the [FAST Switch](https://www.fast.design/docs/components/switch/) and is intended to be as close to the Fluent UI React 9 Switch implementation as possible. However, due to the nature of web components there will not be 100% parity between the two.

### Use Case

Typical use cases include, but are not limited to, turning a feature on and off or showing or hiding a piece of UI

<br />

## Class: `Switch`

<br />

### **Component Name**

`fluent-switch`

<br />

### **Variables**

<br />

### **Fields**

| Name | Privacy | Type | Default | Description |
| --------------- | ------- | ------------------------------ | ---------- | ------------------------------------------------------ |
| `checked` | public | `boolean` | | Specifies whether switch input is checked |
| `required` | public | `boolean` | `false` | Specifies required styling for switch |
| `disabled` | public | `boolean` | `false` | Sets disabled state for switch |
| `labelPosition` | public | `"small"` `"medium"` `"large"` | `"medium"` | Specifies position of the label relative to the switch |

<br />

### **Methods**

<br />

### **Events**

| Name | Type | Description | Inherited From |
| ------ | ---- | ----------- | ---------------------------------------------------------- | --- |
| change | | | Emits a custom change event when the checked state changes | |

<br />

### **Attributes**

| Name | Field |
| ---------------- | ------------- |
| `required` | required |
| `disabled` | disabled |
| `checked` | checked |
| `label-position` | labelPosition |

<br />

### **Slots**

| Name | Description |
| ---- | ------------------------------------- |
| | Default slotted content for the label |

<br />
<hr />
<br />

### **Template**

`switchTemplate` from FastFoundation

<br />

## **Accessibility**

[W3 Switch Spec](https://w3c.github.io/aria/#switch)

<br />

### **WAI-ARIA Roles, States, and Properties**

- `aria-checked`
- `aria-disabled`

<br />
<hr />
<br />

## **Preparation**

<br />

### **Fluent Web Component v3 v.s Fluent React 9**

<br />

**Component and Slot Mapping**

| Fluent UI React 9 | Fluent Web Components 3 |
| ----------------- | ----------------------- |
| `<Switch>` | `<fluent-switch>` |

<br />

**Property Mapping**
| Fluent UI React 9 | Fluent Web Components 3 | Description of difference |
|--------------------- |------------------------ |---------------------------|
| `<Switch label="">` | default slotted content | React implementation requires user to pass label through `prop` on the Switch <br /> The web components implementation requires user to pass the label through the default slotted content
4 changes: 4 additions & 0 deletions packages/web-components/src/switch/define.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { FluentDesignSystem } from '../fluent-design-system.js';
import { definition } from './switch.definition.js';

definition.define(FluentDesignSystem.registry);
5 changes: 5 additions & 0 deletions packages/web-components/src/switch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './switch.js';
export * from './switch.options.js';
export { definition } from './switch.definition.js';
export { styles as switchStyles } from './switch.styles.js';
export { template as switchTemplate } from './switch.template.js';
17 changes: 17 additions & 0 deletions packages/web-components/src/switch/switch.definition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FluentDesignSystem } from '../fluent-design-system.js';
import { Switch } from './switch.js';
import { template } from './switch.template.js';
import { styles } from './switch.styles.js';

/**
* The Fluent Switch Element.
*
* @public
* @remarks
* HTML Element: \<fluent-switch\>
*/
export const definition = Switch.compose({
name: `${FluentDesignSystem.prefix}-switch`,
template,
styles,
});
17 changes: 17 additions & 0 deletions packages/web-components/src/switch/switch.options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ValuesOf } from '@microsoft/fast-foundation';

/**
* SwitchLabelPosition Constants
* @public
*/
export const SwitchLabelPosition = {
above: 'above',
after: 'after',
before: 'before',
} as const;

/**
* Applies label position
* @public
*/
export type SwitchLabelPosition = ValuesOf<typeof SwitchLabelPosition>;
88 changes: 88 additions & 0 deletions packages/web-components/src/switch/switch.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { html } from '@microsoft/fast-element';
import type { Args, Meta } from '@storybook/html';
import { renderComponent } from '../helpers.stories.js';
import type { Switch as FluentSwitch } from './switch.js';
import './define.js';
import { SwitchLabelPosition } from './switch.options.js';

type SwitchStoryArgs = Args & FluentSwitch;
type SwitchStoryMeta = Meta<SwitchStoryArgs>;

const storyTemplate = html<SwitchStoryArgs>`
<div>
<fluent-switch
?checked=${x => x.checked}
?disabled=${x => x.disabled}
?required=${x => x.required}
label-position=${x => x.labelPosition}
value="${x => x.value}"
>
${x => x.value}
</fluent-switch>
</div>
`;

export default {
title: 'Components/Switch',
args: {
checked: false,
disabled: false,
required: false,
labelPosition: 'after',
},
argTypes: {
labelPosition: {
options: Object.values(SwitchLabelPosition),
control: {
type: 'select',
},
table: {
type: {
summary: 'Sets the position of label',
},
defaultValue: {
summary: 'after',
},
},
},
checked: {
control: 'boolean',
table: {
type: {
summary: 'Sets checked state',
},
defaultValue: {
summary: 'false',
},
},
},
disabled: {
control: 'boolean',
table: {
type: {
summary: 'Sets disabled state',
},
defaultValue: {
summary: 'false',
},
},
},
required: {
control: 'boolean',
table: {
type: {
summary: 'Sets required state',
},
defaultValue: {
summary: 'false',
},
},
},
value: {
control: 'text',
defaultValue: 'This is a label',
},
},
} as SwitchStoryMeta;

export const Switch = renderComponent(storyTemplate).bind({});
Loading

0 comments on commit 9f0ae19

Please sign in to comment.