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

fix: use Stencil watchers instead of global attributes util #8407

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
40 changes: 1 addition & 39 deletions packages/calcite-components/conventions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,45 +366,7 @@ There are utilities for common workflows in [`src/utils`](../src/utils).

### Global attributes

The [`globalAttributes`](../src/utils/globalAttributes.ts) util was specifically made to access the `lang` global attribute when set on a Calcite component. However, it can be extended to allow additional [global attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) by adding to the [`allowedGlobalAttributes`](https://github.com/Esri/calcite-design-system/blob/a33aa0df0c5bf103f91187826e6b12b8ff266d90/src/utils/globalAttributes.ts#L4-L5) array. The util is used in [`calcite-pagination`](../src/components/pagination/pagination.tsx), which you can use as a reference.

#### Usage steps

1. Import the interface and watch/unwatch methods

```js
import { GlobalAttrComponent, watchGlobalAttributes, unwatchGlobalAttributes } from "../../utils/globalAttributes";
```

2. Implement the interface

```js
export class ComponentName implements GlobalAttrComponent {
```

3. Add `globalAttributes` state

```js
@State() globalAttributes = {};
```

4. Add connect/disconnect callbacks

```js
connectedCallback(): void {
watchGlobalAttributes(this, ["lang"]);
}

disconnectedCallback(): void {
unwatchGlobalAttributes(this);
}
```

5. Use the state to access `lang` (or another global attribute that may be allowed in the future).

```js
const lang = this.globalAttributes["lang"] || document.documentElement.lang || "en";
```
Watching global attributes on components is now possible with Stencil v4. Please refer to the [documentation page](https://stenciljs.com/docs/reactive-data#watching-native-html-attributes) for more information.

### BigDecimal

Expand Down
38 changes: 24 additions & 14 deletions packages/calcite-components/src/components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import { Build, Component, Element, h, Method, Prop, State, VNode, Watch } from "@stencil/core";
import {
Build,
Component,
Element,
forceUpdate,
h,
Method,
Prop,
State,
VNode,
Watch,
} from "@stencil/core";
import { findAssociatedForm, FormOwner, resetForm, submitForm } from "../../utils/form";
import {
connectInteractive,
Expand Down Expand Up @@ -27,11 +38,6 @@ import { Appearance, FlipContext, Kind, Scale, Width } from "../interfaces";
import { ButtonMessages } from "./assets/button/t9n";
import { ButtonAlignment } from "./interfaces";
import { CSS } from "./resources";
import {
GlobalAttrComponent,
unwatchGlobalAttributes,
watchGlobalAttributes,
} from "../../utils/globalAttributes";
import { toAriaBoolean } from "../../utils/dom";

/** Passing a 'href' will render an anchor link, instead of a button. Role will be set to link, or button, depending on this. */
Expand All @@ -46,7 +52,6 @@ import { toAriaBoolean } from "../../utils/dom";
})
export class Button
implements
GlobalAttrComponent,
LabelableComponent,
InteractiveComponent,
FormOwner,
Expand All @@ -56,6 +61,17 @@ export class Button
{
//--------------------------------------------------------------------------
//
// Global attributes
//
//--------------------------------------------------------------------------

@Watch("aria-expanded")
handleGlobalAttributesChanged(): void {
forceUpdate(this);
}

// --------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
Expand Down Expand Up @@ -183,7 +199,6 @@ export class Button
connectInteractive(this);
connectLocalized(this);
connectMessages(this);
watchGlobalAttributes(this, ["aria-expanded"]);
this.hasLoader = this.loading;
this.setupTextContentObserver();
connectLabel(this);
Expand All @@ -198,7 +213,6 @@ export class Button
disconnectMessages(this);
this.resizeObserver?.disconnect();
this.formEl = null;
unwatchGlobalAttributes(this);
}

async componentWillLoad(): Promise<void> {
Expand Down Expand Up @@ -260,6 +274,7 @@ export class Button
return (
<Tag
aria-disabled={childElType === "a" ? toAriaBoolean(this.disabled || this.loading) : null}
aria-expanded={this.el.getAttribute("aria-expanded")}
aria-label={!this.loading ? getLabelText(this) : this.messages.loading}
aria-live="polite"
class={{
Expand All @@ -278,7 +293,6 @@ export class Button
target={childElType === "a" && this.target}
title={this.tooltipText}
type={childElType === "button" && this.type}
{...this.globalAttributes}
// eslint-disable-next-line react/jsx-sort-props -- ref should be last so node attrs/props are in sync (see https://github.com/Esri/calcite-design-system/pull/6530)
ref={this.setChildEl}
>
Expand Down Expand Up @@ -357,10 +371,6 @@ export class Button

resizeObserver = createObserver("resize", () => this.setTooltipText());

@State() globalAttributes = {
ariaExpanded: undefined,
};

//--------------------------------------------------------------------------
//
// Private Methods
Expand Down
38 changes: 21 additions & 17 deletions packages/calcite-components/src/components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Watch,
Method,
VNode,
forceUpdate,
} from "@stencil/core";
import { focusElement, focusElementInGroup, slotChangeGetAssignedElements } from "../../utils/dom";
import {
Expand All @@ -26,11 +27,6 @@ import {
updateMessages,
} from "../../utils/t9n";
import { MenuMessages } from "./assets/menu/t9n";
import {
GlobalAttrComponent,
unwatchGlobalAttributes,
watchGlobalAttributes,
} from "../../utils/globalAttributes";

type Layout = "horizontal" | "vertical";

Expand All @@ -42,12 +38,22 @@ type Layout = "horizontal" | "vertical";
},
assetsDirs: ["assets"],
})
export class CalciteMenu
implements GlobalAttrComponent, LocalizedComponent, T9nComponent, LoadableComponent
{
export class CalciteMenu implements LocalizedComponent, T9nComponent, LoadableComponent {
//--------------------------------------------------------------------------
//
// Public Properties
// Global attributes
//
//--------------------------------------------------------------------------

@Watch("role")
handleGlobalAttributesChanged(): void {
forceUpdate(this);
this.setMenuItemLayout(this.menuItems, this.layout);
}

//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------

Expand Down Expand Up @@ -102,10 +108,6 @@ export class CalciteMenu
updateMessages(this, this.effectiveLocale);
}

@State() globalAttributes = {
role: "menubar",
};

menuItems: HTMLCalciteMenuItemElement[] = [];

//--------------------------------------------------------------------------
Expand All @@ -117,7 +119,6 @@ export class CalciteMenu
connectedCallback(): void {
connectLocalized(this);
connectMessages(this);
watchGlobalAttributes(this, ["role"]);
}

async componentWillLoad(): Promise<void> {
Expand All @@ -132,7 +133,6 @@ export class CalciteMenu
disconnectedCallback(): void {
disconnectLocalized(this);
disconnectMessages(this);
unwatchGlobalAttributes(this);
}

//--------------------------------------------------------------------------
Expand Down Expand Up @@ -220,13 +220,17 @@ export class CalciteMenu
setMenuItemLayout(items: HTMLCalciteMenuItemElement[], layout: Layout): void {
items.forEach((item) => {
item.layout = layout;
if (this.globalAttributes.role === "menubar") {
if (this.getEffectiveRole() === "menubar") {
item.isTopLevelItem = true;
item.topLevelMenuLayout = this.layout;
}
});
}

private getEffectiveRole(): string {
return this.el.getAttribute("role") || "menubar";
}

// --------------------------------------------------------------------------
//
// Render Methods
Expand All @@ -236,7 +240,7 @@ export class CalciteMenu
render(): VNode {
return (
<Host>
<ul aria-label={this.label} {...this.globalAttributes}>
<ul aria-label={this.label} role={this.getEffectiveRole()}>
<slot onSlotchange={this.handleMenuSlotChange} />
</ul>
</Host>
Expand Down
97 changes: 0 additions & 97 deletions packages/calcite-components/src/utils/globalAttributes.spec.ts

This file was deleted.

Loading
Loading