From c19a5375524a9c29bc4380119f40d3d829c104ce Mon Sep 17 00:00:00 2001 From: Lukas Maurer Date: Tue, 13 Aug 2024 15:45:18 +0200 Subject: [PATCH] fix(core/tree): handle text overflow (#1428) --- .changeset/lemon-pants-act.md | 5 + packages/core/component-doc.json | 10 +- packages/core/src/components.d.ts | 8 +- .../src/components/tree-item/tree-item.scss | 6 ++ .../src/components/tree-item/tree-item.tsx | 16 ++-- packages/core/src/components/tree/tree.tsx | 23 +++-- .../core/src/tests/tree/overflow/index.html | 86 ++++++++++++++++++ packages/core/src/tests/tree/tree.e2e.ts | 19 ++++ ...-1-chromium---theme-classic-dark-linux.png | Bin 0 -> 2411 bytes ...1-chromium---theme-classic-light-linux.png | Bin 0 -> 2576 bytes 10 files changed, 147 insertions(+), 26 deletions(-) create mode 100644 .changeset/lemon-pants-act.md create mode 100644 packages/core/src/tests/tree/overflow/index.html create mode 100644 packages/core/src/tests/tree/tree.e2e.ts-snapshots/tree-item-overflow-1-chromium---theme-classic-dark-linux.png create mode 100644 packages/core/src/tests/tree/tree.e2e.ts-snapshots/tree-item-overflow-1-chromium---theme-classic-light-linux.png diff --git a/.changeset/lemon-pants-act.md b/.changeset/lemon-pants-act.md new file mode 100644 index 0000000000..afc24a616b --- /dev/null +++ b/.changeset/lemon-pants-act.md @@ -0,0 +1,5 @@ +--- +"@siemens/ix": patch +--- + +fix(core/tree): handle text overflow gracefully diff --git a/packages/core/component-doc.json b/packages/core/component-doc.json index 8147aa03b4..f2c59fc719 100644 --- a/packages/core/component-doc.json +++ b/packages/core/component-doc.json @@ -16216,6 +16216,7 @@ "reflectToAttr": false, "docs": "Tree model", "docsTags": [], + "default": "{}", "values": [ { "type": "{ [x: string]: TreeItem; }" @@ -16264,7 +16265,7 @@ "type": "(index: number, data: T, dataList: T[], context: TreeContext, update: (callback: UpdateCallback) => void) => HTMLElement" } ], - "optional": false, + "optional": true, "required": false }, { @@ -16286,7 +16287,7 @@ } ], "optional": false, - "required": false + "required": true } ], "methods": [], @@ -16414,7 +16415,7 @@ "type": "TreeItemContext" } ], - "optional": false, + "optional": true, "required": false }, { @@ -16430,6 +16431,7 @@ "reflectToAttr": false, "docs": "Has tree item children", "docsTags": [], + "default": "false", "values": [ { "type": "boolean" @@ -16456,7 +16458,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false } ], diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index 485d8fbb64..84da58ff1a 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -2291,7 +2291,7 @@ export namespace Components { /** * Render function of tree items */ - "renderItem": ( + "renderItem"?: ( index: number, data: T, dataList: Array, @@ -2307,7 +2307,7 @@ export namespace Components { /** * Context */ - "context": TreeItemContext; + "context"?: TreeItemContext; /** * Has tree item children */ @@ -2315,7 +2315,7 @@ export namespace Components { /** * Text */ - "text": string; + "text"?: string; } /** * @since 2.0.0 @@ -6550,7 +6550,7 @@ declare namespace LocalJSX { /** * Initial root element will not be rendered */ - "root"?: string; + "root": string; } interface IxTreeItem { /** diff --git a/packages/core/src/components/tree-item/tree-item.scss b/packages/core/src/components/tree-item/tree-item.scss index f917ad4427..2cc962134e 100644 --- a/packages/core/src/components/tree-item/tree-item.scss +++ b/packages/core/src/components/tree-item/tree-item.scss @@ -23,11 +23,16 @@ cursor: pointer; .tree-node-container { + @include ellipsis; display: flex; align-items: center; height: $x-large-space; flex-grow: 1; align-items: center; + + .tree-node-text { + @include ellipsis; + } } .icon-toggle-container { @@ -36,6 +41,7 @@ justify-content: center; width: 2rem; height: 2rem; + min-width: 2rem; ix-icon { transition: transform var(--theme-default-time) ease-in-out; diff --git a/packages/core/src/components/tree-item/tree-item.tsx b/packages/core/src/components/tree-item/tree-item.tsx index d52838884e..883ebb20e4 100644 --- a/packages/core/src/components/tree-item/tree-item.tsx +++ b/packages/core/src/components/tree-item/tree-item.tsx @@ -19,33 +19,33 @@ export class TreeItem { /** * Text */ - @Prop() text: string; + @Prop() text?: string; /** * Has tree item children */ - @Prop() hasChildren: boolean; + @Prop() hasChildren = false; /** * Context */ - @Prop() context: TreeItemContext; + @Prop() context?: TreeItemContext; /** * Expand/Collapsed toggled */ - @Event() toggle: EventEmitter; + @Event() toggle!: EventEmitter; /** * Clicked */ - @Event() itemClick: EventEmitter; + @Event() itemClick!: EventEmitter; render() { return (
- {this.text} +
{this.text}
diff --git a/packages/core/src/components/tree/tree.tsx b/packages/core/src/components/tree/tree.tsx index 9875913c71..887c3b3c8b 100644 --- a/packages/core/src/components/tree/tree.tsx +++ b/packages/core/src/components/tree/tree.tsx @@ -39,17 +39,17 @@ export class Tree { /** * Initial root element will not be rendered */ - @Prop() root: string; + @Prop() root!: string; /** * Tree model */ - @Prop() model: TreeModel; + @Prop() model: TreeModel = {}; /** * Render function of tree items */ - @Prop() renderItem: ( + @Prop() renderItem?: ( index: number, data: T, dataList: Array, @@ -65,31 +65,31 @@ export class Tree { /** * Context changed */ - @Event() contextChange: EventEmitter; + @Event() contextChange!: EventEmitter; /** * Node toggled event * @since 1.5.0 */ - @Event() nodeToggled: EventEmitter<{ id: string; isExpaned: boolean }>; + @Event() nodeToggled!: EventEmitter<{ id: string; isExpaned: boolean }>; /** * Node clicked event * @since 1.5.0 */ - @Event() nodeClicked: EventEmitter; + @Event() nodeClicked!: EventEmitter; /** * Emits removed nodes */ - @Event() nodeRemoved: EventEmitter; + @Event() nodeRemoved!: EventEmitter; private hyperlist: Hyperlist; private toggleListener = new Map(); private itemClickListener = new Map(); private updates = new Map(); - private observer: MutationObserver; + private observer!: MutationObserver; private hasFirstRender = false; private updatePadding(element: HTMLElement, item: TreeItemVisual) { @@ -138,7 +138,10 @@ export class Tree { if (this.updates.has(item.id)) { const doUpdate = this.updates.get(item.id); - doUpdate(item, { ...this.context }); + + if (doUpdate) { + doUpdate(item, { ...this.context }); + } } this.updatePadding(renderedTreeItem, item); @@ -240,7 +243,7 @@ export class Tree { this.initList(); this.observer = new MutationObserver((records) => { - let removed = []; + let removed: unknown[] = []; records.forEach((record) => { removed = [...removed, ...Array.from(record.removedNodes)]; diff --git a/packages/core/src/tests/tree/overflow/index.html b/packages/core/src/tests/tree/overflow/index.html new file mode 100644 index 0000000000..37f902a207 --- /dev/null +++ b/packages/core/src/tests/tree/overflow/index.html @@ -0,0 +1,86 @@ + + + + + + + Stencil Component Starter + + +
+ +
+ + + + + diff --git a/packages/core/src/tests/tree/tree.e2e.ts b/packages/core/src/tests/tree/tree.e2e.ts index 21e0acbe16..f4d8128e9f 100644 --- a/packages/core/src/tests/tree/tree.e2e.ts +++ b/packages/core/src/tests/tree/tree.e2e.ts @@ -70,4 +70,23 @@ regressionTest.describe('tree', () => { expect(await page.screenshot({ fullPage: true })).toMatchSnapshot(); }); + + regressionTest('item overflow', async ({ page }) => { + await page.goto('tree/overflow'); + + page.setViewportSize({ width: 100, height: 100 }); + + const treeViewportHandle = await page.waitForSelector('ix-tree'); + + await page.evaluate((tree) => { + const model = tree.model; + + model['sample-child-1'].data.name = + 'This is a very long text that should overflow'; + + tree.model = { ...model }; + }, treeViewportHandle); + + expect(await page.screenshot({ fullPage: true })).toMatchSnapshot(); + }); }); diff --git a/packages/core/src/tests/tree/tree.e2e.ts-snapshots/tree-item-overflow-1-chromium---theme-classic-dark-linux.png b/packages/core/src/tests/tree/tree.e2e.ts-snapshots/tree-item-overflow-1-chromium---theme-classic-dark-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..5cc1b611ce338a2bba956eeb150dbffd59d10cb7 GIT binary patch literal 2411 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 UoNYQS{yhPl&cW>}&jzOa6G}^Y)c^nh literal 0 HcmV?d00001 diff --git a/packages/core/src/tests/tree/tree.e2e.ts-snapshots/tree-item-overflow-1-chromium---theme-classic-light-linux.png b/packages/core/src/tests/tree/tree.e2e.ts-snapshots/tree-item-overflow-1-chromium---theme-classic-light-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..3ce9f29e70774c2e92b32d6a039a300f878b2877 GIT binary patch literal 2576 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 adZ0d6q(5y-IN&GW1DF|GL$F3Jv3~*9xz4lz literal 0 HcmV?d00001