Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
131f558
662 - content tree init
prashanthr6383 Jan 13, 2026
7432795
662 - update layout
prashanthr6383 Jan 13, 2026
eefb20b
662 - content tree add node using slots
prashanthr6383 Jan 14, 2026
ca9d12b
662 - add search functionality
prashanthr6383 Jan 19, 2026
62be67c
662 - add menu item toggle feature
prashanthr6383 Jan 20, 2026
1ba646e
662 - remove
prashanthr6383 Jan 21, 2026
5d2c24e
662 - poc atomic approach
prashanthr6383 Jan 23, 2026
a6d206e
Merge branch 'main' into 662---content-tree---base
prashanthr6383 Feb 14, 2026
125cb24
662 - replace menu item with content tree item
prashanthr6383 Feb 16, 2026
72e1362
662 - add selection state to item and css fixes
prashanthr6383 Feb 16, 2026
c770eb0
662 - add row actions, 1.0 & 2.0 features
prashanthr6383 Feb 17, 2026
bf962bb
662 - Add multi-select feature
prashanthr6383 Feb 18, 2026
b5e66b6
662 - ui fixes
prashanthr6383 Feb 19, 2026
2cb744e
662 - add multi select event and ui fixes
prashanthr6383 Feb 20, 2026
42161a5
662 - fix bugs
prashanthr6383 Feb 20, 2026
8174bb7
662 - add tests
prashanthr6383 Feb 23, 2026
2bf2b91
662 - build fixes
prashanthr6383 Feb 23, 2026
ee19ec0
662 - build fixes
prashanthr6383 Feb 23, 2026
f420401
662 - add tests
prashanthr6383 Feb 24, 2026
b416fd1
Merge branch 'main' into 662---content-tree---base
prashanthr6383 Feb 24, 2026
fa4b5c0
662 - build fixes
prashanthr6383 Feb 24, 2026
f86ee07
662 - build fixes
prashanthr6383 Feb 24, 2026
c1f674a
662 - fix PR comments
prashanthr6383 Feb 24, 2026
acab2fc
662 - address pr comments
prashanthr6383 Feb 24, 2026
170d3cf
662 - address pr comments
prashanthr6383 Feb 25, 2026
46e0a35
662 - address pr comments
prashanthr6383 Feb 25, 2026
2e2603e
662 - address pr comments
prashanthr6383 Feb 26, 2026
122e414
662 - fix selection state logic
prashanthr6383 Feb 27, 2026
5c183d4
662 - multi seletect fix
prashanthr6383 Mar 2, 2026
a64f816
662 - fix pr comments
prashanthr6383 Mar 2, 2026
f823a60
662 - address pr comments
prashanthr6383 Mar 2, 2026
a2a4201
662 - update storybook
prashanthr6383 Mar 3, 2026
4cbd0c6
662 - update storybook
prashanthr6383 Mar 3, 2026
e4fd9b4
Merge branch 'main' into 662---content-tree---base
prashanthr6383 Mar 3, 2026
f817936
662 - dark mode fixes
prashanthr6383 Mar 3, 2026
f5290ee
662 - css fixes
prashanthr6383 Mar 11, 2026
2cb7610
Merge branch 'main' into 662---content-tree---base
prashanthr6383 Mar 11, 2026
70deeb8
662 - fix build issues
prashanthr6383 Mar 11, 2026
5724fc1
Merge branch '662---content-tree---base' of https://github.com/trimbl…
prashanthr6383 Mar 11, 2026
5250a41
662- build fixes
prashanthr6383 Mar 11, 2026
84f6cdd
662 - css fixes
prashanthr6383 Mar 12, 2026
cf23b19
css fixes
prashanthr6383 Mar 16, 2026
223cc21
662 - ui fixes
prashanthr6383 Mar 16, 2026
6aa9e0f
662 - code fixes
prashanthr6383 Mar 16, 2026
96c3c58
Merge branch 'main' into 662---content-tree---base
prashanthr6383 Mar 20, 2026
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
636 changes: 588 additions & 48 deletions src/components.d.ts

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/components/modus-wc-button/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The component supports a `<slot>` for injecting content within the button, simil
| `disabled` | `disabled` | If true, the button will be disabled. | `boolean \| undefined` | `false` |
| `fullWidth` | `full-width` | If true, the button will take the full width of its container. | `boolean \| undefined` | `false` |
| `pressed` | `pressed` | If true, the button will be in a pressed state (for toggle buttons). | `boolean \| undefined` | `false` |
| `shape` | `shape` | The shape of the button. | `"circle" \| "rectangle" \| "square"` | `'rectangle'` |
| `shape` | `shape` | The shape of the button. | `"circle" \| "ellipse" \| "rectangle" \| "square"` | `'rectangle'` |
| `size` | `size` | The size of the button. | `"lg" \| "md" \| "sm" \| "xs"` | `'md'` |
| `type` | `type` | The type of the button. | `"button" \| "reset" \| "submit"` | `'button'` |
| `variant` | `variant` | The variant of the button. | `"borderless" \| "filled" \| "outlined"` | `'filled'` |
Expand All @@ -37,6 +37,7 @@ The component supports a `<slot>` for injecting content within the button, simil

- [modus-wc-alert](../modus-wc-alert)
- [modus-wc-autocomplete](../modus-wc-autocomplete)
- [modus-wc-content-tree](../modus-wc-content-tree)
- [modus-wc-date](../modus-wc-date)
- [modus-wc-dropdown-menu](../modus-wc-dropdown-menu)
- [modus-wc-modal](../modus-wc-modal)
Expand All @@ -47,6 +48,7 @@ The component supports a `<slot>` for injecting content within the button, simil
graph TD;
modus-wc-alert --> modus-wc-button
modus-wc-autocomplete --> modus-wc-button
modus-wc-content-tree --> modus-wc-button
modus-wc-date --> modus-wc-button
modus-wc-dropdown-menu --> modus-wc-button
modus-wc-modal --> modus-wc-button
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`modus-wc-content-tree should render with custom props 1`] = `
<modus-wc-content-tree custom-class="test-class" expand-all="true" multi-select="true" selected-values="[&quot;item1&quot;, &quot;item2&quot;]">
<!---->
<div class="modus-wc-content-tree-wrapper test-class">
<div class="modus-wc-content-tree-header">
<div class="modus-wc-content-tree-search">
<modus-wc-text-input customclass="modus-wc-content-tree-search-input" include-clear="" include-search="" placeholder="Search..." value=""></modus-wc-text-input>
</div>
<div class="modus-wc-content-tree-actions">
<modus-wc-button aria-label="Expand all" shape="circle" size="sm" variant="borderless">
<modus-wc-icon customclass="modus-wc-content-tree-action-icon" decorative="" name="unfold_more" size="sm" variant="solid"></modus-wc-icon>
</modus-wc-button>
</div>
</div>
<div class="modus-wc-content-tree-content" role="tree">
<div class="modus-wc-content-tree-empty">
<modus-wc-icon customclass="modus-wc-content-tree-empty-icon" name="folder_open" variant="solid"></modus-wc-icon>
<modus-wc-typography customclass="modus-wc-content-tree-empty-text" hierarchy="p" label="Empty Content Tree" size="lg" weight="normal"></modus-wc-typography>
</div>
</div>
</div>
</modus-wc-content-tree>
`;
Comment thread
prashanthr6383 marked this conversation as resolved.
Outdated

exports[`modus-wc-content-tree should render with default props 1`] = `
<modus-wc-content-tree>
<!---->
<div class="modus-wc-content-tree-wrapper">
<div class="modus-wc-content-tree-header">
<div class="modus-wc-content-tree-search">
<modus-wc-text-input customclass="modus-wc-content-tree-search-input" include-clear="" include-search="" placeholder="Search..." value=""></modus-wc-text-input>
</div>
<div class="modus-wc-content-tree-actions">
<modus-wc-button aria-label="Expand all" shape="circle" size="sm" variant="borderless">
<modus-wc-icon customclass="modus-wc-content-tree-action-icon" decorative="" name="unfold_more" size="sm" variant="solid"></modus-wc-icon>
</modus-wc-button>
</div>
</div>
<div class="modus-wc-content-tree-content" role="tree">
<div class="modus-wc-content-tree-empty">
<modus-wc-icon customclass="modus-wc-content-tree-empty-icon" name="folder_open" variant="solid"></modus-wc-icon>
<modus-wc-typography customclass="modus-wc-content-tree-empty-text" hierarchy="p" label="Empty Content Tree" size="lg" weight="normal"></modus-wc-typography>
</div>
</div>
</div>
</modus-wc-content-tree>
`;
74 changes: 74 additions & 0 deletions src/components/modus-wc-content-tree/modus-wc-content-tree.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* This component uses menu items for the tree structure.
* Only add styles here that should not be applied by Tailwind, Daisy, or the theme.
*/

modus-wc-content-tree {
background-color: var(--modus-wc-color-base-page);
border: 1px solid var(--modus-wc-color-base-100);
display: block;
min-width: 320px;
width: 100%;

.modus-wc-content-tree-actions {
align-items: center;
display: flex;
gap: var(--modus-wc-spacing-xs, 0.5rem);
justify-content: flex-end;
margin-top: var(--modus-wc-spacing-md, 1rem);
padding-bottom: var(--modus-wc-spacing-sm, 0.75rem);

.modus-wc-content-tree-action-icon {
color: var(--modus-wc-color-black);
cursor: pointer;
}
}

.modus-wc-content-tree-add-node {
margin-bottom: var(--modus-wc-spacing-md, 1rem);
}
Comment thread
ElishaSamPeterPrabhu marked this conversation as resolved.
Outdated

.modus-wc-content-tree-content {
align-items: center;
Comment thread
ElishaSamPeterPrabhu marked this conversation as resolved.
Outdated
display: block;
Comment thread
ElishaSamPeterPrabhu marked this conversation as resolved.
Outdated
min-height: 500px;
}

li.modus-wc-tree-item-selected:not(.modus-wc-tree-dropdown-show li) {
border-inline-start: 2px solid var(--modus-wc-color-primary);
}

.modus-wc-content-tree-header {
padding: var(--modus-wc-spacing-md, 1rem);
}

.modus-wc-content-tree-empty {
align-items: center;
display: flex;
flex-direction: column;
gap: var(--modus-wc-spacing-md, 1rem);
justify-content: center;
min-height: 500px;
padding: 1rem;

.modus-wc-content-tree-empty-icon {
color: var(--modus-wc-color-text-secondary, #6b7280);
}

.modus-wc-content-tree-empty-text {
color: var(--modus-wc-color-text-secondary, #6b7280);
Comment thread
ElishaSamPeterPrabhu marked this conversation as resolved.
Outdated
font-size: var(--modus-wc-font-size-md, 1rem);
text-align: center;
}
}
}

[data-theme='modus-classic-dark'],
[data-theme='modus-modern-dark'],
[data-theme='connect-dark'] modus-wc-content-tree {
Comment thread
prashanthr6383 marked this conversation as resolved.
Outdated
.modus-wc-content-tree-actions {
.modus-wc-content-tree-action-icon {
color: var(--modus-wc-color-gray-light);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { newSpecPage } from '@stencil/core/testing';
import { ModusWcContentTree } from './modus-wc-content-tree';

describe('modus-wc-content-tree', () => {
it('should render with default props', async () => {
const page = await newSpecPage({
components: [ModusWcContentTree],
html: '<modus-wc-content-tree></modus-wc-content-tree>',
});
expect(page.root).toMatchSnapshot();
});

it('should render with custom props', async () => {
const page = await newSpecPage({
components: [ModusWcContentTree],
html: `<modus-wc-content-tree
custom-class="test-class"
expand-all="true"
multi-select="true"
selected-values='["item1", "item2"]'>
</modus-wc-content-tree>`,
});
expect(page.root).toMatchSnapshot();
});
Comment thread
prashanthr6383 marked this conversation as resolved.
Outdated

it('should filter nodes based on search input', async () => {
const page = await newSpecPage({
components: [ModusWcContentTree],
html: `<modus-wc-content-tree include-search="true">
<modus-wc-tree-item value="item1">Item 1</modus-wc-tree-item>
<modus-wc-tree-item value="item2">Item 2</modus-wc-tree-item>
<modus-wc-tree-item value="item3">Item 3</modus-wc-tree-item>
</modus-wc-content-tree>`,
});

const searchInput = page.root!.querySelector('input[type="search"]');
expect(searchInput as HTMLInputElement).toBeDefined();
if (searchInput) {
(searchInput as HTMLInputElement).value = 'Item 2';
searchInput.dispatchEvent(new Event('input'));
await page.waitForChanges();
const visibleItems = page.root!.querySelectorAll(
'modus-wc-tree-item:not([hidden])'
);
expect(visibleItems.length).toBe(1);
expect(visibleItems[0].getAttribute('value')).toBe('item2');
}
});

it('clears filter on Escape key', async () => {
const page = await newSpecPage({
components: [ModusWcContentTree],
html: `
<modus-wc-content-tree>
<modus-wc-tree-item label="Alpha"></modus-wc-tree-item>
<modus-wc-tree-item label="Beta"></modus-wc-tree-item>
</modus-wc-content-tree>
`,
});

const input = page.root!.querySelector('modus-wc-text-input')!;

input.dispatchEvent(
new CustomEvent('inputChange', {
bubbles: true,
composed: true,
})
);

await page.waitForChanges();

// Now press Escape
input.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }));
await page.waitForChanges();

// Assert all items visible
const items = page.root!.querySelectorAll('modus-wc-tree-item');
items.forEach((item) => {
expect((item as HTMLElement).style.display).toBe('');
});
});
});
Loading
Loading