Skip to content

Commit

Permalink
fix: support native aria property reflection
Browse files Browse the repository at this point in the history
Signed-off-by: Cory Rylan <splintercode.cb@gmail.com>
  • Loading branch information
coryrylan committed Nov 10, 2021
1 parent de9d17e commit a41bcfe
Show file tree
Hide file tree
Showing 22 changed files with 193 additions and 73 deletions.
4 changes: 3 additions & 1 deletion packages/core/rollup.config.js
Expand Up @@ -29,7 +29,7 @@ const config = {
baseDir: './src',
outDir: './dist/core',
entryPoints: {
modules: ['./src', './src/internal', './src/test'],
modules: ['./src', './src/internal', './src/polyfills', './src/test'],
components: [
'./src/accordion',
'./src/alert',
Expand Down Expand Up @@ -83,13 +83,15 @@ const config = {
explicitExports: [
{ input: './icon/shapes/*', output: './icon/shapes/*' },
{ input: './icon/icon.service.js', output: './icon/icon.service.js' },
{ input: './polyfills/index.js', output: './polyfills/index.js' },
{ input: './tokens/tokens.js', output: './tokens/tokens.js' },
{ input: './tokens/tokens.d.ts', output: './tokens/tokens.d.ts' },
{ input: './tokens/tokens.json', output: './tokens/tokens.json' },
{ input: './tokens/tokens.scss', output: './tokens/tokens.scss' },
{ input: './tokens/tokens.ios.swift', output: './tokens/tokens.ios.swift' },
{ input: './tokens/tokens.android.xml', output: './tokens/tokens.android.xml' },
],
explicitSideEffects: ['./polyfills/index.js', './polyfills/aria-reflect.js'],
},
};

Expand Down
7 changes: 4 additions & 3 deletions packages/core/rollup.utils.js
Expand Up @@ -168,9 +168,10 @@ export const addComponentEntryPoints = (packageFile, config) => {
${[modules, explicitExports, components, styles].join(',')}
}`);

const sideEffects = config.entryPoints.components.map(
name => `.${resolve(name).replace(resolve(config.baseDir), '')}/register.js`
);
const sideEffects = [
...config.entryPoints.components.map(name => `.${resolve(name).replace(resolve(config.baseDir), '')}/register.js`),
...config.entryPoints.explicitSideEffects,
];

return JSON.stringify({ ...JSON.parse(packageFile), sideEffects, exports }, null, 2);
};
Expand Down
11 changes: 5 additions & 6 deletions packages/core/src/alert/alert-group.element.ts
Expand Up @@ -70,12 +70,6 @@ export class CdsAlertGroup extends LitElement {
@property({ type: String })
type: AlertGroupTypes = 'default';

/**
* Autosets the alert groups aria role to 'region'
*/
@property({ type: String })
role = 'region';

/**
* Sets the status of the alerts inside the alert group
* @type {neutral | info | success | warning | danger | alt | loading}
Expand Down Expand Up @@ -111,6 +105,11 @@ export class CdsAlertGroup extends LitElement {
`;
}

connectedCallback() {
super.connectedCallback();
this.role = 'region';
}

firstUpdated(props: Map<string, any>) {
super.firstUpdated(props);
this.setupAlertsUpdate();
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/alert/alert.performance.ts
Expand Up @@ -16,7 +16,7 @@ describe('cds-badge performance', () => {
`;

it(`should bundle and treeshake alert`, async () => {
expect((await testBundleSize('@cds/core/alert/register.js')).kb).toBeLessThan(23);
expect((await testBundleSize('@cds/core/alert/register.js')).kb).toBeLessThan(23.5);
});

it(`should render 1 alert under 20ms`, async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/badge/badge.performance.ts
Expand Up @@ -11,7 +11,7 @@ describe('cds-badge performance', () => {
const badge = html`<cds-badge></cds-badge>`;

it(`should bundle and treeshake badge`, async () => {
expect((await testBundleSize('@cds/core/badge/register.js')).kb).toBeLessThan(12);
expect((await testBundleSize('@cds/core/badge/register.js')).kb).toBeLessThan(12.5);
});

it(`should render 1 badge under 20ms`, async () => {
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/breadcrumb/breadcrumb.element.ts
Expand Up @@ -23,13 +23,12 @@ import styles from './breadcrumb.element.scss';
* @cssprop --color
*/
export class CdsBreadcrumb extends LitElement {
@state({ type: String, reflect: true, attribute: 'role' })
protected role = 'navigation';

@state({ type: Array }) private navItems: Element[] = [];

@querySlot('[slot="cds-separator"]') private customSeparator: HTMLElement;

role = 'navigation';

render() {
return html`
<div class="private-host">
Expand All @@ -47,6 +46,7 @@ export class CdsBreadcrumb extends LitElement {
<slot @slotchange=${this.assignSlots}></slot>
`;
}

private get separator() {
if (this.customSeparator) {
const separatorClone = this.customSeparator.cloneNode(true) as Element;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/card/card.element.ts
@@ -1,5 +1,5 @@
import { css } from 'lit';
import { property, globalStyle } from '@cds/core/internal';
import { globalStyle } from '@cds/core/internal';
import { CdsInternalPanel } from '@cds/core/internal-components/panel';
import styles from './card.element.scss';

Expand Down Expand Up @@ -49,7 +49,7 @@ import styles from './card.element.scss';
* @cssprop --cds-card-remove-margin
*/
export class CdsCard extends CdsInternalPanel {
@property({ type: String, reflect: true }) role = 'region';
role = 'region';

@globalStyle() globalStyles = css`
[cds-card-remove-margin] {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/icon/icon.performance.ts
Expand Up @@ -18,7 +18,7 @@ describe('cds-icon performance', () => {
import '@cds/core/icon/register.js';
ClarityIcons.addIcons(userIcon);
`;
expect((await testBundleSize(bundle)).kb).toBeLessThan(14);
expect((await testBundleSize(bundle)).kb).toBeLessThan(14.5);
});

it(`should bundle all icons`, async () => {
Expand Down
Expand Up @@ -101,7 +101,8 @@ export class CdsInternalOverlay extends CdsBaseFocusTrap implements Animatable {
// renderRoot needs delegatesFocus so that focus can cross the shadowDOM
// inside an element with aria-modal set to true
/** @private */
static get shadowRootOptions() {
static get shadowRootOptions(): any {
// any is used until TS 4.4.x adopted through other @cds/* libraries. Can be removed in 6.0
return { ...super.shadowRootOptions, delegatesFocus: true };
}

Expand Down
5 changes: 1 addition & 4 deletions packages/core/src/internal/base/button.base.ts
Expand Up @@ -24,16 +24,12 @@ export class CdsBaseButton extends LitElement {

@property({ type: Boolean }) disabled = false;

@state({ type: String, attribute: 'aria-disabled', reflect: true }) ariaDisabled: 'true' | 'false' | null = 'false';

@state({ type: Number, attribute: 'tabindex', reflect: true }) protected tabIndexAttr: number | null; // don't override native prop as it stops native focus behavior

@state({ type: Boolean, reflect: true }) protected focused = false;

@state({ type: Boolean, reflect: true }) protected active = false;

@state({ type: String, reflect: true, attribute: 'role' }) protected role: string | null = 'button';

@state({ type: Boolean, reflect: true }) protected isAnchor = false;

@querySlot('cds-icon') protected icon: HTMLElement;
Expand All @@ -56,6 +52,7 @@ export class CdsBaseButton extends LitElement {
connectedCallback() {
super.connectedCallback();
this.tabIndex = 0; // initialize immediately so button can be focused synchronously
this.role = 'button';
}

protected updated(props: Map<string, any>) {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/internal/index.ts
Expand Up @@ -4,10 +4,10 @@
* The full license information can be found in LICENSE in the root directory of this project.
*/

/** @internal private module to Clarity Core */

import '@cds/core/polyfills';
import styles from './base/base.element.scss';

/** @internal private module to Clarity Core */
export const baseStyles = styles;
export * from './base/button.base.js';
export * from './base/focus-trap.base.js';
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/internal/utils/exists.ts
Expand Up @@ -14,7 +14,8 @@ export const existsIn = curryN(2, (pathToCheck: string[], obj: object): boolean
return typeof pathExists !== 'undefined';
});

export function elementExists(tagName: string, registry?: { get: (name: string) => {} }): boolean {
export function elementExists(tagName: string, registry?: any): boolean {
// any should be CustomElementRegistry but waiting until TS 4.4.x adopted through other @cds/* libraries. Cane be updated in 6.0
if (!registry) {
registry = window && window.customElements;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/modal/modal-content.element.ts
Expand Up @@ -35,7 +35,8 @@ export class CdsModalContent extends LitElement {
// inside modal-content with a tabindex of -1. we need the tabindex so a
// modal's content can scroll if it needs to.
/** @private */
static get shadowRootOptions() {
static get shadowRootOptions(): any {
// any is used until TS 4.4.x adopted through other @cds/* libraries. Can be removed in 6.0
return { ...super.shadowRootOptions, delegatesFocus: true };
}

Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/navigation/navigation-item.element.ts
Expand Up @@ -50,9 +50,6 @@ export class CdsNavigationItem extends LitElement implements FocusableItem {
@property({ type: Boolean, reflect: true })
disabled = false;

@property({ type: String, reflect: true })
role = 'listitem';

@state({ type: Boolean })
expanded = false;

Expand All @@ -74,6 +71,8 @@ export class CdsNavigationItem extends LitElement implements FocusableItem {
@querySlotAll('[cds-navigation-sr-text]')
itemText: NodeListOf<HTMLSpanElement>;

role = 'listitem';

connectedCallback() {
super.connectedCallback();
if (!this.id) {
Expand Down
15 changes: 4 additions & 11 deletions packages/core/src/navigation/navigation.element.ts
Expand Up @@ -84,9 +84,6 @@ export class CdsNavigation extends LitElement implements Animatable {
@property({ type: String })
cdsMotion = 'on';

@property({ type: String })
role = 'list';

@event()
protected expandedChange: EventEmitter<boolean>;

Expand All @@ -102,12 +99,6 @@ export class CdsNavigation extends LitElement implements Animatable {
@state({ type: Boolean })
protected groupItem = true;

/**
* Set and update the aria-active descended value onto the navigation.
*/
@state({ type: String })
ariaActiveDescendant: any;

/**
*
* Vertical navigation elements can be either wide or narrow. Expanded indicates it should be wide.
Expand Down Expand Up @@ -183,6 +174,8 @@ export class CdsNavigation extends LitElement implements Animatable {
@querySlotAll('cds-navigation-group')
protected navigationGroupRefs: NodeListOf<CdsNavigationGroup>;

role = 'list';

private toggle() {
this.expandedChange.emit(!this.expanded);
}
Expand Down Expand Up @@ -310,7 +303,7 @@ export class CdsNavigation extends LitElement implements Animatable {
if (this.currentActiveItem?.tagName === 'CDS-NAVIGATION-ITEM' && !!groupParent) {
const groupStartElement = groupParent?.querySelector('cds-navigation-start');
removeFocus(this.currentActiveItem as FocusableElement);
this.ariaActiveDescendant = groupStartElement?.id;
this.ariaActiveDescendant = groupStartElement?.id ?? null;
setFocus(groupStartElement as FocusableElement);
return;
}
Expand Down Expand Up @@ -389,7 +382,7 @@ export class CdsNavigation extends LitElement implements Animatable {
${this.startTemplate}
<slot name="cds-navigation-substart"></slot>
<nav class="navigation-body-wrapper">
<div aria-activedescendant="${this.ariaActiveDescendant}" tabindex="0" id="item-container">
<div .ariaActiveDescendant=${this.ariaActiveDescendant} tabindex="0" id="item-container">
<div class="navigation-body" cds-layout="vertical wrap:none align:horizontal-stretch">
<slot></slot>
</div>
Expand Down
9 changes: 4 additions & 5 deletions packages/core/src/password/password.element.ts
Expand Up @@ -51,13 +51,12 @@ export class CdsPassword extends CdsControl {
ClarityIcons.addIcons(eyeIcon, eyeHideIcon);
}

private get ariaLabel() {
return this.showPassword ? this.i18n.hideButtonAriaLabel : this.i18n.showButtonAriaLabel;
}

protected get suffixDefaultTemplate() {
return html`
<cds-control-action @click=${() => this.togglePasswordVisibility()} aria-label="${this.ariaLabel}">
<cds-control-action
@click=${() => this.togglePasswordVisibility()}
.ariaLabel=${this.showPassword ? this.i18n.hideButtonAriaLabel : this.i18n.showButtonAriaLabel}
>
<cds-icon shape="${this.showPassword ? 'eye-hide' : 'eye'}"></cds-icon>
</cds-control-action>
`;
Expand Down

0 comments on commit a41bcfe

Please sign in to comment.