From 6c2672100d43784d390f6f6fbc632afa7a63d251 Mon Sep 17 00:00:00 2001 From: GCHQ-Developer-847 <111882109+GCHQ-Developer-847@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:04:35 +0000 Subject: [PATCH] fix(canary-web-components): update tree view to improve FOUC Update tree view to prevent FOUC - set tree items visibility to hidden until loaded when inherited props from tree view used. Removed timeouts on truncation - tree view now truncates when ready rather than waiting 0.1 seconds to help reduce flashing. --- .../components/ic-tree-item/ic-tree-item.tsx | 11 +++--- .../__snapshots__/ic-tree-item.spec.ts.snap | 34 ++++++++--------- .../components/ic-tree-view/ic-tree-view.css | 10 +++++ .../ic-tree-view/ic-tree-view.stories.mdx | 4 +- .../components/ic-tree-view/ic-tree-view.tsx | 38 +++++++++++++++---- .../__snapshots__/ic-tree-view.spec.ts.snap | 32 ++++++++++------ 6 files changed, 85 insertions(+), 44 deletions(-) diff --git a/packages/canary-web-components/src/components/ic-tree-item/ic-tree-item.tsx b/packages/canary-web-components/src/components/ic-tree-item/ic-tree-item.tsx index 98ba5860ea..c549ef8c0f 100644 --- a/packages/canary-web-components/src/components/ic-tree-item/ic-tree-item.tsx +++ b/packages/canary-web-components/src/components/ic-tree-item/ic-tree-item.tsx @@ -141,9 +141,7 @@ export class TreeItem { componentWillLoad(): void { removeDisabledFalse(this.disabled, this.el); - } - componentDidLoad(): void { this.childTreeItems = Array.from((this.el as HTMLElement).children).filter( (child) => child.tagName === this.treeItemTag ) as HTMLIcTreeItemElement[]; @@ -151,15 +149,13 @@ export class TreeItem { if (this.childTreeItems.length > 0) { this.isParent = true; } + } + componentDidLoad(): void { this.setTreeItemPadding(); this.updateAriaLabel(); - setTimeout(() => { - this.truncateTreeItem && this.truncateTreeItemLabel(this.el); - }, 100); - !isSlotUsed(this.el, "label") && onComponentRequiredPropUndefined( [{ prop: this.label, propName: "label" }], @@ -175,6 +171,9 @@ export class TreeItem { } componentDidUpdate(): void { + // Runs on second render - when truncateTreeItem prop has now been applied in the DOM + this.truncateTreeItem && this.truncateTreeItemLabel(this.el); + if (this.hasParentExpanded) { this.childTreeItems.forEach((child: HTMLIcTreeItemElement) => { child.truncateTreeItem && this.truncateTreeItemLabel(child); diff --git a/packages/canary-web-components/src/components/ic-tree-item/test/basic/__snapshots__/ic-tree-item.spec.ts.snap b/packages/canary-web-components/src/components/ic-tree-item/test/basic/__snapshots__/ic-tree-item.spec.ts.snap index 533fd3c441..1671c58653 100644 --- a/packages/canary-web-components/src/components/ic-tree-item/test/basic/__snapshots__/ic-tree-item.spec.ts.snap +++ b/packages/canary-web-components/src/components/ic-tree-item/test/basic/__snapshots__/ic-tree-item.spec.ts.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ic-tree-item component should render 1`] = ` - + -
+
Item 1 @@ -13,7 +13,7 @@ exports[`ic-tree-item component should render 1`] = ` `; exports[`ic-tree-item component should render disabled 1`] = ` - +
@@ -25,7 +25,7 @@ exports[`ic-tree-item component should render disabled 1`] = ` `; exports[`ic-tree-item component should render disabled: disabled-removed 1`] = ` - +
@@ -37,9 +37,9 @@ exports[`ic-tree-item component should render disabled: disabled-removed 1`] = ` `; exports[`ic-tree-item component should render selected 1`] = ` - + -
+
Item 1 @@ -49,9 +49,9 @@ exports[`ic-tree-item component should render selected 1`] = ` `; exports[`ic-tree-item component should render with child tree items 1`] = ` - + -
+
@@ -60,18 +60,18 @@ exports[`ic-tree-item component should render with child tree items 1`] = `
- + -
+
Item 1.1
- + -
+
Item 1.2 @@ -82,9 +82,9 @@ exports[`ic-tree-item component should render with child tree items 1`] = ` `; exports[`ic-tree-item component should render with icon 1`] = ` - + -
+
@@ -101,7 +101,7 @@ exports[`ic-tree-item component should render with icon 1`] = ` `; exports[`ic-tree-item component should render with router item slot 1`] = ` - + @@ -112,9 +112,9 @@ exports[`ic-tree-item component should render with router item slot 1`] = ` `; exports[`ic-tree-item component should render with slotted label 1`] = ` - + -
+
diff --git a/packages/canary-web-components/src/components/ic-tree-view/ic-tree-view.css b/packages/canary-web-components/src/components/ic-tree-view/ic-tree-view.css index 6bf7441361..c6d5045f2b 100644 --- a/packages/canary-web-components/src/components/ic-tree-view/ic-tree-view.css +++ b/packages/canary-web-components/src/components/ic-tree-view/ic-tree-view.css @@ -42,6 +42,7 @@ .icon-container { width: var(--ic-space-lg); + min-width: var(--ic-space-lg); height: var(--ic-space-lg); margin: 0 var(--ic-space-xs) 0 0; } @@ -60,6 +61,15 @@ overflow: hidden; } +/* Ensures truncation works - accounts for text width increase as component hydrates */ +.tree-view-header.with-padding { + padding-right: var(--ic-space-xs); +} + +.tree-items-container-hidden { + visibility: hidden; +} + ::slotted([slot="icon"]) { fill: var(--ic-tree-view-icon); } diff --git a/packages/canary-web-components/src/components/ic-tree-view/ic-tree-view.stories.mdx b/packages/canary-web-components/src/components/ic-tree-view/ic-tree-view.stories.mdx index 9fbf66e437..c10ccd0c94 100644 --- a/packages/canary-web-components/src/components/ic-tree-view/ic-tree-view.stories.mdx +++ b/packages/canary-web-components/src/components/ic-tree-view/ic-tree-view.stories.mdx @@ -597,7 +597,7 @@ An example with truncated tree items. When the heading/label exceeds the width o d="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" /> - + - + { - this.truncateHeading && this.truncateTreeViewHeading(); - }, 100); + this.truncateHeading && this.truncateTreeViewHeading(); this.addSlotChangeListener(); @@ -118,6 +117,8 @@ export class TreeView { this.hostMutationObserver.observe(this.el, { childList: true, }); + + this.isLoaded = true; } @Listen("icTreeItemSelected") @@ -294,7 +295,15 @@ export class TreeView { }; render() { - const { heading, size, theme } = this; + const { + focusInset, + heading, + isLoaded, + size, + theme, + truncateHeading, + truncateTreeItems, + } = this; return (
)} - + {isSlotUsed(this.el, "heading") ? ( ) : ( @@ -323,7 +338,16 @@ export class TreeView {
)} - +
+ +
); } diff --git a/packages/canary-web-components/src/components/ic-tree-view/test/basic/__snapshots__/ic-tree-view.spec.ts.snap b/packages/canary-web-components/src/components/ic-tree-view/test/basic/__snapshots__/ic-tree-view.spec.ts.snap index 4c3e24b538..f86899f4df 100644 --- a/packages/canary-web-components/src/components/ic-tree-view/test/basic/__snapshots__/ic-tree-view.spec.ts.snap +++ b/packages/canary-web-components/src/components/ic-tree-view/test/basic/__snapshots__/ic-tree-view.spec.ts.snap @@ -1,20 +1,22 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ic-tree-view component should render 1`] = ` - +
Heading
- +
+ +
`; exports[`ic-tree-view component should render with icon 1`] = ` - +
@@ -24,7 +26,9 @@ exports[`ic-tree-view component should render with icon 1`] = ` Heading
- +
+ +
@@ -34,7 +38,7 @@ exports[`ic-tree-view component should render with icon 1`] = ` `; exports[`ic-tree-view component should render with slotted heading 1`] = ` - +
@@ -44,7 +48,9 @@ exports[`ic-tree-view component should render with slotted heading 1`] = `
- +
+ +
@@ -56,27 +62,29 @@ exports[`ic-tree-view component should render with slotted heading 1`] = ` `; exports[`ic-tree-view component should render with tree items 1`] = ` - +
Heading
- +
+ +
- + -
+
Item 1
- + -
+
Item 2