Skip to content

Commit

Permalink
refactor(responsive): use JS module to create breakpoints lookup obje…
Browse files Browse the repository at this point in the history
…ct (#8051)

**Related Issue:** N/A

## Summary

Stems from
#8041 (comment).

This changes how breakpoints are built and used (`responsive` module):

* uses design tokens JS output target to reference breakpoint values
* prevents possible disconnect between stylesheet and conditional
rendering breakpoint values (only the latter could be overridden via CSS
props)
* the breakpoints lookup object no longer needs to be obtained
asynchronously

This also updates and unskips the `responsive` spec test.

**Note**: this includes an update to the testing Jest config to apply
Stencil's transformer to the design token's headless ESM file as the
default one was not transforming properly and leading to `Jest
encountered an unexpected token` errors when running the spec test.
  • Loading branch information
jcfranco authored Nov 10, 2023
1 parent 9c0208c commit e7165cc
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 63 deletions.
9 changes: 3 additions & 6 deletions packages/calcite-components/src/components/alert/alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ import { KindIcons } from "../resources";
import { AlertMessages } from "./assets/alert/t9n";
import { AlertDuration, Sync, Unregister } from "./interfaces";
import { CSS, DURATIONS, SLOTS } from "./resources";
import { Breakpoints, getBreakpoints } from "../../utils/responsive";
import { createObserver } from "../../utils/observers";
import { breakpoints } from "../../utils/responsive";

/**
* Alerts are meant to provide a way to communicate urgent or important information to users, frequently as a result of an action they took in your app. Alerts are positioned
Expand Down Expand Up @@ -182,8 +182,7 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen

async componentWillLoad(): Promise<void> {
setUpLoadableComponent(this);
const [, breakpoints] = await Promise.all([setUpMessages(this), getBreakpoints()]);
this.breakpoints = breakpoints;
await setUpMessages(this);
if (this.open) {
onToggleOpenCloseComponent(this);
}
Expand Down Expand Up @@ -218,7 +217,7 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen
const { hasEndActions } = this;
const { open, autoClose, responsiveContainerWidth, label, placement, queued } = this;
const role = autoClose ? "alert" : "alertdialog";
const widthBreakpoints = this.breakpoints.width;
const widthBreakpoints = breakpoints.width;
const lessThanSmall = responsiveContainerWidth < widthBreakpoints.small;
const greaterOrEqualThanSmall = responsiveContainerWidth >= widthBreakpoints.small;
const hidden = !open;
Expand Down Expand Up @@ -439,8 +438,6 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen

private autoCloseTimeoutId: number = null;

private breakpoints: Breakpoints;

private closeButton: HTMLButtonElement;

private initialOpenTime: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { Scale } from "../interfaces";
import { PaginationMessages } from "./assets/pagination/t9n";
import { CSS, ICONS } from "./resources";
import { createObserver } from "../../utils/observers";
import { Breakpoints, getBreakpoints } from "../../utils/responsive";
import { breakpoints } from "../../utils/responsive";
import { getIconScale } from "../../utils/component";

export interface PaginationDetail {
Expand Down Expand Up @@ -151,8 +151,6 @@ export class Pagination

@State() totalPages: number;

private breakpoints: Breakpoints;

private resizeObserver = createObserver("resize", (entries) =>
entries.forEach(this.resizeHandler)
);
Expand Down Expand Up @@ -181,8 +179,7 @@ export class Pagination
}

async componentWillLoad(): Promise<void> {
const [, breakpoints] = await Promise.all([setUpMessages(this), getBreakpoints()]);
this.breakpoints = breakpoints;
await setUpMessages(this);
setUpLoadableComponent(this);
this.handleTotalPages();
}
Expand Down Expand Up @@ -230,8 +227,6 @@ export class Pagination
// --------------------------------------------------------------------------

private setMaxItemsToBreakpoint(width: number): void {
const { breakpoints } = this;

if (!breakpoints || !width) {
return;
}
Expand Down
22 changes: 4 additions & 18 deletions packages/calcite-components/src/utils/responsive.spec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,9 @@
import { getBreakpoints } from "./responsive";
import { breakpoints } from "./responsive";
import { toBeInteger } from "../tests/utils";

describe("getBreakpoints()", () => {
// skipped due to JSDOM bugs with inheritance/getComputedStyle
// see https://github.com/jsdom/jsdom/issues/2160 and https://github.com/jsdom/jsdom/issues/3563
it.skip("returns breakpoints lookup object", async () => {
document.head.innerHTML = `
<style>
:root {
--calcite-app-breakpoint-width-lg: 10000px;
--calcite-app-breakpoint-width-md: 1000px;
--calcite-app-breakpoint-width-sm: 100px;
--calcite-app-breakpoint-width-xs: 10px;
--calcite-app-breakpoint-width-xxs: 1px;
}
</style>
`;

expect(await getBreakpoints()).toMatchObject({
describe("breakpoints", () => {
it("provides a breakpoints lookup object", async () => {
expect(breakpoints).toMatchObject({
width: {
large: toBeInteger(),
medium: toBeInteger(),
Expand Down
52 changes: 20 additions & 32 deletions packages/calcite-components/src/utils/responsive.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import {
CoreBreakpointWidthDefaultLg,
CoreBreakpointWidthDefaultMd,
CoreBreakpointWidthDefaultSm,
CoreBreakpointWidthDefaultXs,
CoreBreakpointWidthDefaultXxs,
} from "@esri/calcite-design-tokens/dist/es6/calcite-headless";

export interface Breakpoints {
width: {
large: number;
Expand All @@ -8,39 +16,19 @@ export interface Breakpoints {
};
}

let getBreakpointsPromise: Promise<Breakpoints>;

function breakpointTokenToNumericalValue(style: CSSStyleDeclaration, tokenName: string): number {
return parseInt(style.getPropertyValue(tokenName));
}

/**
* This util will return a breakpoints lookup object.
*
* Note that the breakpoints will be evaluated at the root and cached for reuse.
*
* @returns {Promise<Breakpoints>} The Breakpoints object.
* A breakpoints lookup object.
*/
export async function getBreakpoints(): Promise<Breakpoints> {
if (getBreakpointsPromise) {
return getBreakpointsPromise;
}

getBreakpointsPromise = new Promise<Breakpoints>((resolve) => {
requestAnimationFrame(() => {
const rootStyles = getComputedStyle(document.body);

resolve({
width: {
large: breakpointTokenToNumericalValue(rootStyles, "--calcite-app-breakpoint-width-lg"),
medium: breakpointTokenToNumericalValue(rootStyles, "--calcite-app-breakpoint-width-md"),
small: breakpointTokenToNumericalValue(rootStyles, "--calcite-app-breakpoint-width-sm"),
xsmall: breakpointTokenToNumericalValue(rootStyles, "--calcite-app-breakpoint-width-xs"),
xxsmall: breakpointTokenToNumericalValue(rootStyles, "--calcite-app-breakpoint-width-xxs"),
},
});
});
});
export const breakpoints: Breakpoints = {
width: {
large: cssLengthToNumber(CoreBreakpointWidthDefaultLg),
medium: cssLengthToNumber(CoreBreakpointWidthDefaultMd),
small: cssLengthToNumber(CoreBreakpointWidthDefaultSm),
xsmall: cssLengthToNumber(CoreBreakpointWidthDefaultXs),
xxsmall: cssLengthToNumber(CoreBreakpointWidthDefaultXxs),
},
};

return getBreakpointsPromise;
function cssLengthToNumber(length: string): number {
return parseInt(length);
}
4 changes: 4 additions & 0 deletions packages/calcite-components/stencil.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ export const create: () => Config = () => ({
"^lodash-es$": "lodash",
},
setupFilesAfterEnv: ["<rootDir>/src/tests/setupTests.ts"],
transform: {
"calcite-design-tokens/dist/es6/calcite-headless\\.js$":
"<rootDir>../../node_modules/@stencil/core/testing/jest-preprocessor.js",
},
},
hydratedFlag: {
selector: "attribute",
Expand Down

0 comments on commit e7165cc

Please sign in to comment.