diff --git a/packages/calcite-components/src/components/tree-item/tree-item.scss b/packages/calcite-components/src/components/tree-item/tree-item.scss
index 35cfb8714c1..5da9c962735 100644
--- a/packages/calcite-components/src/components/tree-item/tree-item.scss
+++ b/packages/calcite-components/src/components/tree-item/tree-item.scss
@@ -1,80 +1,53 @@
+:host([scale="s"]) {
+ --calcite-internal-tree-item-spacing-unit: 0.25rem;
+ --calcite-internal-tree-item-padding-block: 0.25rem;
+ --calcite-internal-tree-item-children-container-padding: 1.25rem;
+ --calcite-internal-tree-item-line-left-position: 0.75rem;
+ @apply text-n2h;
+}
+
+:host([scale="m"]) {
+ --calcite-internal-tree-item-spacing-unit: 0.5rem;
+ --calcite-internal-tree-item-padding-block: 0.5rem;
+ --calcite-internal-tree-item-children-container-padding: 1.5rem;
+ --calcite-internal-tree-item-line-left-position: 1rem;
+ @apply text-n1h;
+}
+
+:host([scale="l"]) {
+ --calcite-internal-tree-item-spacing-unit: 0.75rem;
+ --calcite-internal-tree-item-padding-block: 0.625rem;
+ --calcite-internal-tree-item-children-container-padding: 2.25rem;
+ --calcite-internal-tree-item-line-left-position: 1.5rem;
+ @apply text-0h;
+}
+
:host {
@apply text-color-3
block
max-w-full
cursor-pointer;
+
+ .children-container ::slotted(*) {
+ padding-inline-start: var(--calcite-internal-tree-item-children-container-padding);
+ }
}
.node-actions-container {
@apply flex;
-}
-
-@include calcite-hydrated-hidden();
-@include disabled();
-
-:host([scale="s"]) {
- @apply text-n2h;
- .node-actions-container {
- @apply min-h-[1.5rem];
- .node-container {
- .checkbox,
- .checkmark,
- .bullet-point {
- margin-inline: theme("margin.1");
- }
- .icon-start {
- margin-inline: theme("margin.3");
- }
- .chevron {
- padding: theme("padding.1");
- }
- }
+ .node-container,
+ .checkbox-container {
+ gap: var(--calcite-internal-tree-item-spacing-unit);
}
-}
-
-:host([scale="m"]) {
- @apply text-n1h;
-
- .node-actions-container {
- @apply min-h-[2rem];
- .node-container {
- .checkbox,
- .checkmark,
- .bullet-point {
- margin-inline: theme("margin.2");
- }
- .icon-start {
- margin-inline: theme("margin.3");
- }
- .chevron {
- padding: theme("padding.2");
- }
- }
+ .node-container {
+ padding-inline: var(--calcite-internal-tree-item-spacing-unit);
+ padding-block: var(--calcite-internal-tree-item-padding-block);
}
}
-:host([scale="l"]) {
- @apply text-0h;
-
- .node-actions-container {
- @apply min-h-[2.75rem];
- .node-container {
- .checkbox,
- .checkmark,
- .bullet-point {
- margin-inline: theme("margin.3");
- }
- .icon-start {
- margin-inline: theme("margin.3");
- }
- .chevron {
- padding-inline: var(--calcite-spacing-md);
- padding-block: var(--calcite-spacing-sm-plus);
- }
- }
- }
-}
+@include calcite-hydrated-hidden();
+@include disabled();
:host([lines]) {
.children-container::after {
@@ -86,6 +59,7 @@
z-default;
// ensure lines don't overlap focus outline
block-size: 96%;
+ left: var(--calcite-internal-tree-item-line-left-position);
content: "";
background-color: var(--calcite-color-border-2);
}
@@ -154,7 +128,6 @@
.children-container {
@apply relative h-0 overflow-hidden opacity-0 origin-top;
- margin-inline-start: theme("margin.5");
transform: scaleY(0);
transition:
var(--calcite-animation-timing) $easing-function,
@@ -198,37 +171,6 @@
}
}
-:host([selection-mode="none"]:not([has-children])) {
- &:host([scale="s"]) .node-container {
- padding-inline-start: theme("padding.2");
- }
- &:host([scale="m"]) .node-container {
- padding-inline-start: theme("padding.4");
- }
- &:host([scale="l"]) .node-container {
- padding-inline-start: theme("padding.6");
- }
-}
-
-// ancestors selection-mode, dropdown without children
-:host(:not([has-children])) {
- &:host([scale="s"]) .node-container[data-selection-mode="ancestors"] .checkbox {
- padding-inline-start: theme("padding.5");
- }
- &:host([scale="m"]) .node-container[data-selection-mode="ancestors"] .checkbox {
- padding-inline-start: theme("padding.6");
- }
- &:host([scale="l"]) .node-container[data-selection-mode="ancestors"] .checkbox {
- padding-inline-start: 1.75rem;
- }
-}
-// ancestors selection-mode, dropdown with children
-:host([has-children]) .node-container[data-selection-mode="ancestors"] {
- .checkbox {
- margin-inline-start: 0;
- }
-}
-
// dropdown with children
:host([has-children]) .node-container {
.bullet-point,
diff --git a/packages/calcite-components/src/components/tree-item/tree-item.tsx b/packages/calcite-components/src/components/tree-item/tree-item.tsx
index 941990ed8da..0daa035b74e 100644
--- a/packages/calcite-components/src/components/tree-item/tree-item.tsx
+++ b/packages/calcite-components/src/components/tree-item/tree-item.tsx
@@ -354,18 +354,19 @@ export class TreeItem extends LitElement implements InteractiveComponent {
const showBlank = this.selectionMode === "none" && !this.hasChildren;
const checkboxIsIndeterminate = this.hasChildren && this.indeterminate;
- const chevron = this.hasChildren ? (
-
- ) : null;
+ const chevron =
+ this.hasChildren || this.selectionMode === "ancestors" ? (
+
+ ) : null;
const defaultSlotNode: JsxNode = ;
const checkbox =
@@ -382,7 +383,6 @@ export class TreeItem extends LitElement implements InteractiveComponent {
}
scale={getIconScale(this.scale)}
/>
-
) : null;
const selectedIcon = showBulletPoint
@@ -462,8 +462,13 @@ export class TreeItem extends LitElement implements InteractiveComponent {
>
{chevron}
{itemIndicator}
+ {checkbox ? checkbox : null}
{this.iconStart ? iconStartEl : null}
- {checkbox ? checkbox : defaultSlotNode}
+ {checkbox ? (
+
+ ) : (
+ defaultSlotNode
+ )}
{slotNode}
diff --git a/packages/calcite-components/src/components/tree/tree.stories.ts b/packages/calcite-components/src/components/tree/tree.stories.ts
index cf58db9312a..149bd33b16f 100644
--- a/packages/calcite-components/src/components/tree/tree.stories.ts
+++ b/packages/calcite-components/src/components/tree/tree.stories.ts
@@ -1,29 +1,55 @@
-import { boolean, modesDarkDefault } from "../../../.storybook/utils";
+import { modesDarkDefault } from "../../../.storybook/utils";
import { html } from "../../../support/formatting";
-import { ATTRIBUTES } from "../../../.storybook/resources";
+import type { Scale } from "../interfaces";
import { Tree } from "./tree";
-const { selectionMode, scale } = ATTRIBUTES;
-
-type TreeStoryArgs = Pick
;
+/**
+ * This decorator takes HTML for items and will create a composite story for all scales for each specified selection mode.
+ *
+ * @param itemsStory - the HTML story template for items
+ * @param context - the context object
+ * @param context.args - the args object
+ * @param context.args.selectionMode - the selection mode(s) to use for the tree
+ * @param context.args.lines
+ * @returns the composite story for all scales for specified selection mode
+ */
+function allScaleTreeBuilder(
+ itemsStory: () => string,
+ context: { args: { selectionMode: Tree["selectionMode"]; lines: boolean } },
+): string {
+ const items = itemsStory();
+ const { selectionMode, lines } = context.args;
+ const scales: Scale[] = ["s", "m", "l"];
+
+ return html`
+
+
+
+ ${scales.map(
+ (scale) => html`
+
+
${selectionMode} selection mode + ${scale} scale
+
+ ${items}
+
+
+ `,
+ )}
+
+ `;
+}
export default {
title: "Components/Tree",
- args: {
- lines: false,
- selectionMode: selectionMode.values[0],
- scale: scale.defaultValue,
- },
- argTypes: {
- selectionMode: {
- options: selectionMode.values,
- control: { type: "select" },
- },
- scale: {
- options: scale.values,
- control: { type: "select" },
- },
- },
parameters: {
chromatic: {
delay: 1000,
@@ -31,17 +57,17 @@ export default {
},
};
-const treeItems = html`
+const treeItems = (expanded = true) => html`
Child 1
-
+
Child 2
Grandchild 1
-
+
Grandchild 2
@@ -54,7 +80,7 @@ const treeItems = html`
-
+
Child 3
@@ -67,21 +93,8 @@ const treeItems = html`
`;
-const slottedLargeDropdown = html`
-
-
-
- Group elements
-
-
- Row
- Column
-
-
-`;
-
-const slottedDefaultDropdown = html`
-
+const slottedDefaultDropdown = (scale: string) => html`
+
Group elements
@@ -93,129 +106,66 @@ const slottedDefaultDropdown = html`
`;
-const slottedSmallDropdown = html`
-
-
-
- Group elements
-
-
- Row
- Column
-
-
-`;
-
-const iconStartLargeActionsEnd = html`
+const iconStartLargeActionsEnd = (scale: string) => html`
- Child 1
- ${slottedLargeDropdown} ${slottedLargeDropdown}
+ Child 1
+ ${slottedDefaultDropdown(scale)} ${slottedDefaultDropdown(scale)}
- Child 2
+ Child 2
- Grandchild 1
+ Grandchild 1
- Great-Grandchild 1
- ${slottedLargeDropdown}${slottedLargeDropdown}
+ Great - Grandchild 1
+ ${slottedDefaultDropdown(scale)}${slottedDefaultDropdown(scale)}
- Child 3
- ${slottedLargeDropdown}
+ Child 3
+ ${slottedDefaultDropdown(scale)}
- Grandchild 1
+ Grandchild 1
- Grandchild 2
- ${slottedLargeDropdown}
+ Grandchild 2
+ ${slottedDefaultDropdown(scale)}
`;
-const slottedDefaultActionsEnd = html`
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
-
- Great-Grandchild 1
- ${slottedDefaultDropdown}${slottedDefaultDropdown}
-
-
-
-
-
-`;
+export const singleSelectionMode = (): string => html` ${treeItems()} `;
-const slottedSmallActionsEnd = html`
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
-
- Great-Grandchild 1
- ${slottedSmallDropdown}${slottedSmallDropdown}
-
-
-
-
-
-`;
+singleSelectionMode.decorators = [allScaleTreeBuilder];
-export const simple = (args: TreeStoryArgs): string => html`
-
- ${treeItems}
-
-`;
+export const selectionModeNone = (): string => html`${treeItems()}`;
+selectionModeNone.decorators = [allScaleTreeBuilder];
+selectionModeNone.args = { selectionMode: "none" };
-export const selectionModeNone = (): string => html` ${treeItems} `;
+export const multipleSelectionModeWithLines_TestOnly = (): string => html` ${treeItems()} `;
-export const withLines_TestOnly = (): string => html`
-
- Child 1
-
- Child 2
-
- Grandchild 1
- Grandchild 2
-
- Grandchild 3
-
- Great-Grandchild 1
- Great-Grandchild 2
- Great-Grandchild 3
-
-
-
-
-
-`;
+multipleSelectionModeWithLines_TestOnly.decorators = [allScaleTreeBuilder];
+multipleSelectionModeWithLines_TestOnly.args = { lines: true, selectionMode: "multiple" };
-export const iconStartAndActionsEnd = (): string => html`
-
- ${iconStartLargeActionsEnd}
- ${slottedDefaultActionsEnd}
- ${slottedSmallActionsEnd}
-
-`;
+export const ancestorsSelectionModeWithLines_TestOnly = (): string => html` ${treeItems()} `;
+
+ancestorsSelectionModeWithLines_TestOnly.decorators = [allScaleTreeBuilder];
+ancestorsSelectionModeWithLines_TestOnly.args = { lines: true, selectionMode: "ancestors" };
+
+export const singlePersistSelectionModeWithLines_TestOnly = (): string => html` ${treeItems()} `;
+
+singlePersistSelectionModeWithLines_TestOnly.decorators = [allScaleTreeBuilder];
+singlePersistSelectionModeWithLines_TestOnly.args = { lines: true, selectionMode: "single-persist" };
+
+export const iconStartAndActionsEnd = (scale: string): string => html` ${iconStartLargeActionsEnd(scale)} `;
+
+iconStartAndActionsEnd.decorators = [allScaleTreeBuilder];
export const treeItemTextContentWraps_TestOnly = (): string => html`
@@ -257,10 +207,9 @@ export const treeItemContentIsNotClipped_TestOnly = (): string => html`
`;
-export const darkModeRTL_TestOnly = (): string => html`
- ${treeItems}
-`;
+export const darkModeRTL_TestOnly = (): string => html` ${treeItems()} `;
darkModeRTL_TestOnly.parameters = { themes: modesDarkDefault };
+darkModeRTL_TestOnly.decorators = [allScaleTreeBuilder];
export const OverflowingSubtree = (): string =>
html`
@@ -298,173 +247,3 @@ export const OverflowingSubtree = (): string =>
}, 1000);
});
`;
-
-export const allSelectionModesExpanded_TestOnly = (): string => html`
-
ancestors
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
- Grandchild 2
-
-
- Grandchild 3
-
- Great-Grandchild 1
- Great-Grandchild 2
- Great-Grandchild 3
-
-
-
-
-
-
- children
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
- Grandchild 2
-
-
- Grandchild 3
-
- Great-Grandchild 1
- Great-Grandchild 2
- Great-Grandchild 3
-
-
-
-
-
-
- multichildren
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
- Grandchild 2
-
-
- Grandchild 3
-
- Great-Grandchild 1
- Great-Grandchild 2
- Great-Grandchild 3
-
-
-
-
-
-
- multiple
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
- Grandchild 2
-
-
- Grandchild 3
-
- Great-Grandchild 1
- Great-Grandchild 2
- Great-Grandchild 3
-
-
-
-
-
-
- none
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
- Grandchild 2
-
-
- Grandchild 3
-
- Great-Grandchild 1
- Great-Grandchild 2
- Great-Grandchild 3
-
-
-
-
-
-
- single
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
- Grandchild 2
-
-
- Grandchild 3
-
- Great-Grandchild 1
- Great-Grandchild 2
- Great-Grandchild 3
-
-
-
-
-
-
- single-persist
-
- Child 1
-
-
- Child 2
-
-
- Grandchild 1
-
- Grandchild 2
-
-
- Grandchild 3
-
- Great-Grandchild 1
- Great-Grandchild 2
- Great-Grandchild 3
-
-
-
-
-
-`;