Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(switch): add new checked property/attribute and deprecate on property #815

Merged
merged 1 commit into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dev/pages/switch/switch.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</div>

<div>
<h3 class="forge-typography--heading2">Disabled (on)</h3>
<h3 class="forge-typography--heading2">Disabled (checked)</h3>
<forge-switch disabled selected>off/on</forge-switch>
</div>

Expand Down
2 changes: 1 addition & 1 deletion src/dev/src/partials/controls/switch.ejs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<forge-switch label-position="start" id="<%= control.id %>" <%= control.defaultValue ? 'selected' : null %> <%= control.disabled ? 'disabled' : null %>>
<forge-switch label-position="start" id="<%= control.id %>" <%= control.defaultValue ? 'checked' : null %> <%= control.disabled ? 'disabled' : null %>>
<span><%= control.label %></span>
</forge-switch>
18 changes: 9 additions & 9 deletions src/lib/switch/switch-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { getShadowElement, toggleClass } from '@tylertech/forge-core';
import { internals, isFocusable, setDefaultAria, setValidity } from '../constants';
import { isFocusable, setDefaultAria, setValidity } from '../constants';
import { BaseAdapter, IBaseAdapter } from '../core';
import { StateLayerComponent } from '../state-layer';
import { ISwitchComponent } from './switch';
import { SwitchIconVisibility, SwitchLabelPosition, SWITCH_CONSTANTS } from './switch-constants';

export interface ISwitchAdapter extends IBaseAdapter {
setOn(value: boolean): void;
setChecked(value: boolean): void;
setDisabled(value: boolean): void;
setRequired(value: boolean): void;
setReadonly(value: boolean): void;
Expand All @@ -18,21 +18,21 @@ export interface ISwitchAdapter extends IBaseAdapter {
export class SwitchAdapter extends BaseAdapter<ISwitchComponent> implements ISwitchAdapter {
private readonly _rootElement: HTMLElement;
private readonly _labelElement: HTMLElement;
private readonly _iconOnElement: HTMLElement;
private readonly _iconOffElement: HTMLElement;
private readonly _iconCheckedElement: HTMLElement;
private readonly _iconUncheckedElement: HTMLElement;
private readonly _stateLayerElement: StateLayerComponent;

constructor(component: ISwitchComponent) {
super(component);

this._rootElement = getShadowElement(component, SWITCH_CONSTANTS.selectors.ROOT);
this._labelElement = getShadowElement(component, SWITCH_CONSTANTS.selectors.LABEL);
this._iconOnElement = getShadowElement(component, SWITCH_CONSTANTS.selectors.ICON_ON);
this._iconOffElement = getShadowElement(component, SWITCH_CONSTANTS.selectors.ICON_OFF);
this._iconCheckedElement = getShadowElement(component, SWITCH_CONSTANTS.selectors.ICON_ON);
this._iconUncheckedElement = getShadowElement(component, SWITCH_CONSTANTS.selectors.ICON_OFF);
this._stateLayerElement = getShadowElement(component, SWITCH_CONSTANTS.selectors.STATE_LAYER) as StateLayerComponent;
}

public setOn(value: boolean): void {
public setChecked(value: boolean): void {
this._component[setValidity]();
this._component[setDefaultAria]({ ariaChecked: value ? 'true' : 'false' });
}
Expand All @@ -56,8 +56,8 @@ export class SwitchAdapter extends BaseAdapter<ISwitchComponent> implements ISwi
public setIconVisibility(value: SwitchIconVisibility): void {
const hideOn = value === 'none' || value === 'off';
const hideOff = value === 'none' || value === 'on';
toggleClass(this._iconOnElement, hideOn, SWITCH_CONSTANTS.classes.HIDDEN);
toggleClass(this._iconOffElement, hideOff, SWITCH_CONSTANTS.classes.HIDDEN);
toggleClass(this._iconCheckedElement, hideOn, SWITCH_CONSTANTS.classes.HIDDEN);
toggleClass(this._iconUncheckedElement, hideOff, SWITCH_CONSTANTS.classes.HIDDEN);
}

public setLabelPosition(value: SwitchLabelPosition): void {
Expand Down
17 changes: 17 additions & 0 deletions src/lib/switch/switch-component-delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,37 @@ export class SwitchComponentDelegate extends FormFieldComponentDelegate<ISwitchC
this._element.value = value;
}

public get checked(): boolean {
return this._element.checked;
}
public set checked(value: boolean) {
this._element.checked = value;
}

/** @deprecated Use `checked` instead */
public get on(): boolean {
return this._element.on;
}
public set on(value: boolean) {
this._element.on = value;
}

/** @deprecated Use `checked` instead */
public get selected(): boolean {
return this._element.selected;
}
public set selected(value: boolean) {
this._element.selected = value;
}

public get defaultChecked(): boolean {
return this._element.defaultChecked;
}
public set defaultChecked(value: boolean) {
this._element.defaultChecked = value;
}

/** @deprecated Use `defaultChecked` instead */
public get defaultOn(): boolean {
return this._element.defaultOn;
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib/switch/switch-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import { COMPONENT_NAME_PREFIX } from '../constants';
const elementName: keyof HTMLElementTagNameMap = `${COMPONENT_NAME_PREFIX}switch`;

const observedAttributes = {
CHECKED: 'checked',
/** @deprecated use `CHECKED` instead. */
ON: 'on',
/** @deprecated use `CHECKED` instead. */
SELECTED: 'selected',
DEFAULT_CHECKED: 'default-checked',
/** @deprecated use `DEFAULT_CHECKED` instead. */
DEFAULT_ON: 'default-on',
VALUE: 'value',
DENSE: 'dense',
Expand Down
55 changes: 28 additions & 27 deletions src/lib/switch/switch-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { ISwitchAdapter } from './switch-adapter';
import { SWITCH_CONSTANTS, SwitchIconVisibility, SwitchLabelPosition } from './switch-constants';

export interface ISwitchCore {
on: boolean;
defaultOn: boolean;
checked: boolean;
defaultChecked: boolean;
value: string;
dense: boolean;
disabled: boolean;
Expand All @@ -15,8 +15,8 @@ export interface ISwitchCore {

export class SwitchCore implements ISwitchCore {
// State
private _on = false;
private _defaultOn = false;
private _checked = false;
private _defaultChecked = false;
private _value = 'on';
private _dense = false;
private _disabled = false;
Expand All @@ -26,7 +26,7 @@ export class SwitchCore implements ISwitchCore {
private _labelPosition: SwitchLabelPosition = 'end';

private get _submittedValue(): string | null {
return this._on ? this._value : null;
return this._checked ? this._value : null;
}

// Listeners
Expand Down Expand Up @@ -61,10 +61,10 @@ export class SwitchCore implements ISwitchCore {
return;
}

const oldValue = this._on;
const newValue = !this._on;
const oldValue = this._checked;
const newValue = !this._checked;

this._on = newValue;
this._checked = newValue;

const event = new Event('change', { cancelable: true, bubbles: true });
const forgeEvent = new CustomEvent(SWITCH_CONSTANTS.events.CHANGE, {
Expand All @@ -74,39 +74,40 @@ export class SwitchCore implements ISwitchCore {
});
this._adapter.dispatchHostEvent(event);
this._adapter.dispatchHostEvent(forgeEvent);
this._on = oldValue;
this._checked = oldValue;
if (event.defaultPrevented || forgeEvent.defaultPrevented) {
return;
}

this.on = newValue;
this.checked = newValue;
}

private _setOnAttribute(): void {
this._adapter.toggleHostAttribute(SWITCH_CONSTANTS.attributes.ON, this._on);
// Also set selected for backwards compatibility
this._adapter.toggleHostAttribute(SWITCH_CONSTANTS.attributes.SELECTED, this._on);
private _setCheckedAttribute(): void {
this._adapter.toggleHostAttribute(SWITCH_CONSTANTS.attributes.CHECKED, this._checked);
// Also set the following for backwards compatibility
this._adapter.toggleHostAttribute(SWITCH_CONSTANTS.attributes.ON, this._checked);
this._adapter.toggleHostAttribute(SWITCH_CONSTANTS.attributes.SELECTED, this._checked);
}

public get on(): boolean {
return this._on;
public get checked(): boolean {
return this._checked;
}
public set on(value: boolean) {
if (this._on !== value) {
this._on = value;
this._adapter.setOn(this._on);
public set checked(value: boolean) {
if (this._checked !== value) {
this._checked = value;
this._adapter.setChecked(this._checked);
this._adapter.syncValue(this._submittedValue);
this._setOnAttribute();
this._setCheckedAttribute();
}
}

public get defaultOn(): boolean {
return this._defaultOn;
public get defaultChecked(): boolean {
return this._defaultChecked;
}
public set defaultOn(value: boolean) {
if (this._defaultOn !== value) {
this._defaultOn = value;
this._adapter.toggleHostAttribute(SWITCH_CONSTANTS.attributes.DEFAULT_ON, this._defaultOn);
public set defaultChecked(value: boolean) {
if (this._defaultChecked !== value) {
this._defaultChecked = value;
this._adapter.toggleHostAttribute(SWITCH_CONSTANTS.attributes.DEFAULT_CHECKED, this._defaultChecked);
}
}

Expand Down
Loading