Compare commits

...

2 Commits

6 changed files with 230 additions and 95 deletions

View File

@@ -3,37 +3,68 @@ title: Switch / Toggle
---
<style>
ha-switch {
display: block;
.wrapper {
display: flex;
gap: 24px;
align-items: center;
}
</style>
# Switch `<ha-switch>`
A toggle switch can represent two states: on and off.
A toggle switch representing two states: on and off.
## Examples
## Implementation
Switch in on state
### Example usage
<div class="wrapper">
<ha-switch checked></ha-switch>
<ha-switch></ha-switch>
<ha-switch disabled></ha-switch>
<ha-switch disabled checked></ha-switch>
</div>
```html
<ha-switch checked></ha-switch>
Switch in off state
<ha-switch></ha-switch>
Disabled switch
<ha-switch disabled></ha-switch>
## CSS variables
<ha-switch disabled checked></ha-switch>
```
For the switch / toggle there are always two variables, one for the on / checked state and one for the off / unchecked state.
### API
The track element (background rounded rectangle that the round circular handle travels on) is set to being half transparent, so the final color will also be impacted by the color behind the track.
This component is based on the webawesome switch component.
Check the [webawesome documentation](https://webawesome.com/docs/components/switch/) for more details.
`switch-checked-color` / `switch-unchecked-color`
Set both the color of the round handle and the track behind it. If you want to control them separately, use the variables below instead.
**Properties/Attributes**
`switch-checked-button-color` / `switch-unchecked-button-color`
Color of the round handle
| Name | Type | Default | Description |
| -------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
| checked | Boolean | false | The checked state of the switch. |
| disabled | Boolean | false | Disables the switch and prevents user interaction. |
| required | Boolean | false | Makes the switch a required field. |
| haptic | Boolean | false | Enables haptic vibration on toggle. Only use when the new state is applied immediately (not when save is required). |
`switch-checked-track-color` / `switch-unchecked-track-color`
Color of the track behind the round handle
**CSS Custom Properties**
- `--ha-switch-size` - The size of the switch track height. Defaults to `14px`.
- `--ha-switch-thumb-size` - The size of the thumb. Defaults to `20px`.
- `--ha-switch-width` - The width of the switch track. Defaults to `36px`.
- `--ha-switch-box-shadow` - The box shadow of the thumb. Defaults to `var(--ha-box-shadow-s)`.
- `--ha-switch-background-color` - Background color of the unchecked track.
- `--ha-switch-border-color` - Border color of the unchecked track and thumb.
- `--ha-switch-thumb-background-color` - Background color of the unchecked thumb.
- `--ha-switch-background-color-hover` - Background color of the unchecked track on hover.
- `--ha-switch-thumb-background-color-hover` - Background color of the unchecked thumb on hover.
- `--ha-switch-checked-background-color` - Background color of the checked track.
- `--ha-switch-checked-border-color` - Border color of the checked track.
- `--ha-switch-checked-thumb-background-color` - Background color of the checked thumb.
- `--ha-switch-checked-thumb-border-color` - Border color of the checked thumb.
- `--ha-switch-checked-background-color-hover` - Background color of the checked track on hover.
- `--ha-switch-checked-thumb-background-color-hover` - Background color of the checked thumb on hover.
- `--ha-switch-required-marker` - The marker shown after the label for required fields. Defaults to `"*"`.
- `--ha-switch-required-marker-offset` - Offset of the required marker. Defaults to `0.1rem`.

View File

@@ -67,7 +67,6 @@
"@material/mwc-formfield": "patch:@material/mwc-formfield@npm%3A0.27.0#~/.yarn/patches/@material-mwc-formfield-npm-0.27.0-9528cb60f6.patch",
"@material/mwc-list": "patch:@material/mwc-list@npm%3A0.27.0#~/.yarn/patches/@material-mwc-list-npm-0.27.0-5344fc9de4.patch",
"@material/mwc-radio": "0.27.0",
"@material/mwc-switch": "0.27.0",
"@material/mwc-top-app-bar": "0.27.0",
"@material/mwc-top-app-bar-fixed": "0.27.0",
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",

View File

@@ -1,49 +1,195 @@
import { SwitchBase } from "@material/mwc-switch/deprecated/mwc-switch-base";
import { styles } from "@material/mwc-switch/deprecated/mwc-switch.css";
import { css } from "lit";
import Switch from "@home-assistant/webawesome/dist/components/switch/switch";
import { css, type CSSResultGroup, type PropertyValues } from "lit";
import { customElement, property } from "lit/decorators";
import { forwardHaptic } from "../data/haptics";
/**
* Home Assistant switch component
*
* @element ha-switch
* @extends {Switch}
*
* @summary
* A toggle switch component supporting Home Assistant theming, based on the webawesome switch.
* Represents two states: on and off.
*
* @cssprop --ha-switch-size - The size of the switch track height. Defaults to `14px`.
* @cssprop --ha-switch-thumb-size - The size of the thumb. Defaults to `20px`.
* @cssprop --ha-switch-width - The width of the switch track. Defaults to `36px`.
* @cssprop --ha-switch-box-shadow - The box shadow of the thumb. Defaults to `var(--ha-box-shadow-s)`.
* @cssprop --ha-switch-background-color - Background color of the unchecked track.
* @cssprop --ha-switch-border-color - Border color of the unchecked track and thumb.
* @cssprop --ha-switch-thumb-background-color - Background color of the unchecked thumb.
* @cssprop --ha-switch-background-color-hover - Background color of the unchecked track on hover.
* @cssprop --ha-switch-thumb-background-color-hover - Background color of the unchecked thumb on hover.
* @cssprop --ha-switch-checked-background-color - Background color of the checked track.
* @cssprop --ha-switch-checked-border-color - Border color of the checked track.
* @cssprop --ha-switch-checked-thumb-background-color - Background color of the checked thumb.
* @cssprop --ha-switch-checked-thumb-border-color - Border color of the checked thumb.
* @cssprop --ha-switch-checked-background-color-hover - Background color of the checked track on hover.
* @cssprop --ha-switch-checked-thumb-background-color-hover - Background color of the checked thumb on hover.
* @cssprop --ha-switch-required-marker - The marker shown after the label for required fields. Defaults to `"*"`.
* @cssprop --ha-switch-required-marker-offset - Offset of the required marker. Defaults to `0.1rem`.
*
* @attr {boolean} checked - The checked state of the switch.
* @attr {boolean} disabled - Disables the switch and prevents user interaction.
* @attr {boolean} required - Makes the switch a required field.
* @attr {boolean} haptic - Enables haptic vibration on toggle. Only use when the new state is applied immediately (not when a save action is required).
*/
@customElement("ha-switch")
export class HaSwitch extends SwitchBase {
// Generate a haptic vibration.
// Only set to true if the new value of the switch is applied right away when toggling.
// Do not add haptic when a user is required to press save.
export class HaSwitch extends Switch {
/**
* Enables haptic vibration on toggle.
* Only set to true if the new value of the switch is applied right away when toggling.
* Do not add haptic when a user is required to press save.
*/
@property({ type: Boolean }) public haptic = false;
protected firstUpdated() {
super.firstUpdated();
this.addEventListener("change", () => {
public updated(changedProperties: PropertyValues<typeof this>) {
super.updated(changedProperties);
if (changedProperties.has("haptic")) {
if (this.haptic) {
forwardHaptic(this, "light");
this.addEventListener("change", this._forwardHaptic);
} else {
this.removeEventListener("change", this._forwardHaptic);
}
});
}
}
static override styles = [
styles,
css`
:host {
--mdc-theme-secondary: var(--switch-checked-color);
}
.mdc-switch.mdc-switch--checked .mdc-switch__thumb {
background-color: var(--switch-checked-button-color);
border-color: var(--switch-checked-button-color);
}
.mdc-switch.mdc-switch--checked .mdc-switch__track {
background-color: var(--switch-checked-track-color);
border-color: var(--switch-checked-track-color);
}
.mdc-switch:not(.mdc-switch--checked) .mdc-switch__thumb {
background-color: var(--switch-unchecked-button-color);
border-color: var(--switch-unchecked-button-color);
}
.mdc-switch:not(.mdc-switch--checked) .mdc-switch__track {
background-color: var(--switch-unchecked-track-color);
border-color: var(--switch-unchecked-track-color);
}
`,
];
public disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener("change", this._forwardHaptic);
}
private _forwardHaptic = () => {
forwardHaptic(this, "light");
};
static get styles(): CSSResultGroup {
return [
Switch.styles,
css`
:host {
--wa-form-control-toggle-size: var(--ha-switch-size, 14px);
--wa-form-control-required-content: var(
--ha-switch-required-marker,
var(--ha-input-required-marker, "*")
);
--wa-form-control-required-content-offset: var(
--ha-switch-required-marker-offset,
0.1rem
);
--thumb-size: var(--ha-switch-thumb-size, 20px);
--width: var(--ha-switch-width, 36px);
}
label {
height: max(var(--thumb-size), var(--wa-form-control-toggle-size));
padding: 0 3px;
}
.switch {
background-color: var(
--ha-switch-background-color,
var(--ha-color-form-background)
);
border-color: var(
--ha-switch-border-color,
var(--ha-color-border-neutral-normal)
);
}
.switch .thumb {
background-color: var(
--ha-switch-thumb-background-color,
var(--ha-color-form-background)
);
border-color: var(
--ha-switch-border-color,
var(--ha-color-border-neutral-normal)
);
border-style: var(--wa-form-control-border-style);
border-width: var(--wa-form-control-border-width);
box-shadow: var(--ha-switch-box-shadow, var(--ha-box-shadow-s));
}
label:not(.disabled):hover .switch,
label:not(.disabled) .input:focus-visible ~ .switch,
label:not(.disabled):active .switch {
background-color: var(
--ha-switch-background-color-hover,
var(
--ha-switch-background-color,
var(--ha-color-fill-neutral-normal-hover)
)
);
}
label:not(.disabled):hover .switch .thumb,
label:not(.disabled) .input:focus-visible ~ .switch .thumb,
label:not(.disabled):active .switch .thumb {
background-color: var(
--ha-switch-thumb-background-color-hover,
var(
--ha-switch-thumb-background-color,
var(--ha-color-form-background-hover)
)
);
}
.checked .switch {
background-color: var(
--ha-switch-checked-background-color,
var(--ha-color-fill-primary-normal-resting)
);
border-color: var(
--ha-switch-checked-border-color,
var(--ha-color-border-primary-loud)
);
}
.checked .switch .thumb {
background-color: var(
--ha-switch-checked-thumb-background-color,
var(--ha-color-fill-primary-loud-resting)
);
border-color: var(
--ha-switch-checked-thumb-border-color,
var(--ha-color-fill-primary-loud-resting)
);
}
label:not(.disabled).checked:hover .switch,
label:not(.disabled).checked .input:focus-visible ~ .switch,
label:not(.disabled).checked:active .switch {
background-color: var(
--ha-switch-checked-background-color-hover,
var(
--ha-switch-checked-background-color,
var(--ha-color-fill-primary-normal-hover)
)
);
}
label:not(.disabled).checked:hover .switch .thumb,
label:not(.disabled).checked .input:focus-visible ~ .switch .thumb,
label:not(.disabled).checked:active .switch .thumb {
background-color: var(
--ha-switch-checked-thumb-background-color-hover,
var(
--ha-switch-checked-thumb-background-color,
var(--ha-color-fill-primary-loud-hover)
)
);
}
label.disabled {
opacity: 0.5;
cursor: not-allowed;
}
`,
];
}
}
declare global {

View File

@@ -34,6 +34,7 @@ class EntityIdPickerRow extends LitElement {
>
<ha-switch
slot="end"
haptic
.checked=${!!this.coreUserData &&
!!this.coreUserData.showEntityIdPicker}
.disabled=${this.coreUserData === undefined}

View File

@@ -266,11 +266,6 @@ export const colorStyles = css`
--sidebar-selected-text-color: var(--primary-color);
--sidebar-selected-icon-color: var(--primary-color);
--sidebar-icon-color: rgba(var(--rgb-primary-text-color), 0.6);
--switch-checked-color: var(--primary-color);
--switch-checked-button-color: var(--switch-checked-color, var(--primary-background-color));
--switch-checked-track-color: var(--switch-checked-color, #000000);
--switch-unchecked-button-color: var(--switch-unchecked-color, var(--primary-background-color));
--switch-unchecked-track-color: var(--switch-unchecked-color, #000000);
--slider-color: var(--primary-color);
--slider-secondary-color: var(--light-primary-color);
--slider-track-color: var(--scrollbar-thumb-color);
@@ -352,8 +347,6 @@ export const darkColorStyles = css`
--primary-text-color: #e1e1e1;
--secondary-text-color: #9b9b9b;
--disabled-text-color: #6f6f6f;
--switch-unchecked-button-color: #999999;
--switch-unchecked-track-color: #9b9b9b;
--divider-color: rgba(225, 225, 225, 0.12);
--outline-color: rgba(225, 225, 225, 0.12);
--outline-hover-color: rgba(225, 225, 225, 0.24);

View File

@@ -2690,19 +2690,6 @@ __metadata:
languageName: node
linkType: hard
"@material/mwc-switch@npm:0.27.0":
version: 0.27.0
resolution: "@material/mwc-switch@npm:0.27.0"
dependencies:
"@material/mwc-base": "npm:^0.27.0"
"@material/mwc-ripple": "npm:^0.27.0"
"@material/switch": "npm:=14.0.0-canary.53b3cad2f.0"
lit: "npm:^2.0.0"
tslib: "npm:^2.0.1"
checksum: 10/620d55add1ee7064e21f4ab649b2d017ec235106a0dcd5f3f29c26a0ea2ec3f8b3c01489081609574f8475a8daa38a4b24fe6129b0fcc82d69e6d58e5483b7c2
languageName: node
linkType: hard
"@material/mwc-top-app-bar-fixed@npm:0.27.0":
version: 0.27.0
resolution: "@material/mwc-top-app-bar-fixed@npm:0.27.0"
@@ -2833,27 +2820,6 @@ __metadata:
languageName: node
linkType: hard
"@material/switch@npm:=14.0.0-canary.53b3cad2f.0":
version: 14.0.0-canary.53b3cad2f.0
resolution: "@material/switch@npm:14.0.0-canary.53b3cad2f.0"
dependencies:
"@material/animation": "npm:14.0.0-canary.53b3cad2f.0"
"@material/base": "npm:14.0.0-canary.53b3cad2f.0"
"@material/density": "npm:14.0.0-canary.53b3cad2f.0"
"@material/dom": "npm:14.0.0-canary.53b3cad2f.0"
"@material/elevation": "npm:14.0.0-canary.53b3cad2f.0"
"@material/feature-targeting": "npm:14.0.0-canary.53b3cad2f.0"
"@material/focus-ring": "npm:14.0.0-canary.53b3cad2f.0"
"@material/ripple": "npm:14.0.0-canary.53b3cad2f.0"
"@material/rtl": "npm:14.0.0-canary.53b3cad2f.0"
"@material/shape": "npm:14.0.0-canary.53b3cad2f.0"
"@material/theme": "npm:14.0.0-canary.53b3cad2f.0"
"@material/tokens": "npm:14.0.0-canary.53b3cad2f.0"
tslib: "npm:^2.1.0"
checksum: 10/445415165ac20c6c80854bf5c8688ea9c2bc88844602b1ebe1f4a9325c9802a295b90c15b860e2af831657b163bd45f64ea5eb6e99e90de8198b100d6c9e52bc
languageName: node
linkType: hard
"@material/theme@npm:14.0.0-canary.53b3cad2f.0":
version: 14.0.0-canary.53b3cad2f.0
resolution: "@material/theme@npm:14.0.0-canary.53b3cad2f.0"
@@ -8900,7 +8866,6 @@ __metadata:
"@material/mwc-formfield": "patch:@material/mwc-formfield@npm%3A0.27.0#~/.yarn/patches/@material-mwc-formfield-npm-0.27.0-9528cb60f6.patch"
"@material/mwc-list": "patch:@material/mwc-list@npm%3A0.27.0#~/.yarn/patches/@material-mwc-list-npm-0.27.0-5344fc9de4.patch"
"@material/mwc-radio": "npm:0.27.0"
"@material/mwc-switch": "npm:0.27.0"
"@material/mwc-top-app-bar": "npm:0.27.0"
"@material/mwc-top-app-bar-fixed": "npm:0.27.0"
"@material/top-app-bar": "npm:=14.0.0-canary.53b3cad2f.0"