diff --git a/COMPONENT_INDEX.md b/COMPONENT_INDEX.md index ed8d98b0..87b462c0 100644 --- a/COMPONENT_INDEX.md +++ b/COMPONENT_INDEX.md @@ -1,6 +1,6 @@ # Component Index -> 169 components exported from carbon-components-svelte@0.38.2. +> 170 components exported from carbon-components-svelte@0.38.2. ## Components @@ -171,6 +171,7 @@ - [`TooltipDefinition`](#tooltipdefinition) - [`TooltipFooter`](#tooltipfooter) - [`TooltipIcon`](#tooltipicon) +- [`TreeView`](#treeview) - [`Truncate`](#truncate) - [`UnorderedList`](#unorderedlist) @@ -4649,6 +4650,48 @@ None. | mouseleave | forwarded | -- | | focus | forwarded | -- | +## `TreeView` + +### Types + +```ts +export type TreeNodeId = string | number; + +export interface TreeNode { + id: TreeNodeId; + text: string; + icon?: typeof import("carbon-icons-svelte").CarbonIcon; + disabled?: boolean; + expanded?: boolean; +} +``` + +### Props + +| Prop name | Kind | Reactive | Type | Default value | Description | +| :---------- | :--------------- | :------- | :------------------------------------------------------- | ---------------------- | --------------------------------------------------------------- | +| selectedIds | let | Yes | TreeNodeId[] | [] | Set the node ids to be selected | +| activeId | let | Yes | TreeNodeId | "" | Set the current active node id
Only one node can be active | +| children | let | No | Array | [] | Provide an array of children nodes to render | +| size | let | No | "default" | "compact" | "default" | Specify the TreeView size | +| labelText | let | No | string | "" | Specify the label text | +| hideLabel | let | No | boolean | false | Set to `true` to visually hide the label text | + +### Slots + +| Slot name | Default | Props | Fallback | +| :-------- | :------ | :---- | :----------------------- | +| labelText | No | -- | {labelText} | + +### Events + +| Event name | Type | Detail | +| :--------- | :--------- | :------------------------------------------------------------ | +| select | dispatched | TreeNode & { expanded: boolean; leaf: boolean; } | +| toggle | dispatched | TreeNode & { expanded: boolean; leaf: boolean; } | +| focus | dispatched | TreeNode & { expanded: boolean; leaf: boolean; } | +| keydown | forwarded | -- | + ## `Truncate` ### Props diff --git a/css/all.scss b/css/all.scss index 6679fa7a..ecbbd37f 100644 --- a/css/all.scss +++ b/css/all.scss @@ -76,5 +76,8 @@ $css--plex: true; @import "carbon-components/scss/globals/scss/_css--body"; @import "carbon-components/scss/globals/grid/grid"; +// Import experimental TreeView styles not included in global styles +@import "carbon-components/src/components/treeview/treeview"; + // Import all component styles @import "carbon-components/scss/globals/scss/styles"; diff --git a/css/g10.scss b/css/g10.scss index e97cdb84..e77b2144 100644 --- a/css/g10.scss +++ b/css/g10.scss @@ -27,6 +27,9 @@ $carbon--theme: $carbon--theme--g10; @import "carbon-components/scss/globals/scss/_css--body"; @import "carbon-components/scss/globals/grid/grid"; +// Import experimental TreeView styles not included in global styles +@import "carbon-components/src/components/treeview/treeview"; + // Import all component styles @import "carbon-components/scss/globals/scss/styles"; diff --git a/css/g100.scss b/css/g100.scss index 6828061d..b30327a8 100644 --- a/css/g100.scss +++ b/css/g100.scss @@ -27,5 +27,8 @@ $carbon--theme: $carbon--theme--g100; @import "carbon-components/scss/globals/scss/_css--body"; @import "carbon-components/scss/globals/grid/grid"; +// Import experimental TreeView styles not included in global styles +@import "carbon-components/src/components/treeview/treeview"; + // Import all component styles @import "carbon-components/scss/globals/scss/styles"; \ No newline at end of file diff --git a/css/g80.scss b/css/g80.scss index 9f5475c9..c0df672a 100644 --- a/css/g80.scss +++ b/css/g80.scss @@ -27,6 +27,9 @@ $carbon--theme: $carbon--theme--g80; @import "carbon-components/scss/globals/scss/_css--body"; @import "carbon-components/scss/globals/grid/grid"; +// Import experimental TreeView styles not included in global styles +@import "carbon-components/src/components/treeview/treeview"; + // Import all component styles @import "carbon-components/scss/globals/scss/styles"; diff --git a/css/g90.scss b/css/g90.scss index abf54fa0..d219f985 100644 --- a/css/g90.scss +++ b/css/g90.scss @@ -27,5 +27,8 @@ $carbon--theme: $carbon--theme--g90; @import "carbon-components/scss/globals/scss/_css--body"; @import "carbon-components/scss/globals/grid/grid"; +// Import experimental TreeView styles not included in global styles +@import "carbon-components/src/components/treeview/treeview"; + // Import all component styles @import "carbon-components/scss/globals/scss/styles"; \ No newline at end of file diff --git a/css/white.scss b/css/white.scss index 9b4bd827..409b423f 100644 --- a/css/white.scss +++ b/css/white.scss @@ -27,5 +27,8 @@ $carbon--theme: $carbon--theme--white; @import "carbon-components/scss/globals/scss/_css--body"; @import "carbon-components/scss/globals/grid/grid"; +// Import experimental TreeView styles not included in global styles +@import "carbon-components/src/components/treeview/treeview"; + // Import all component styles @import "carbon-components/scss/globals/scss/styles"; \ No newline at end of file diff --git a/docs/src/App.svelte b/docs/src/App.svelte index 50709afa..95e62f70 100644 --- a/docs/src/App.svelte +++ b/docs/src/App.svelte @@ -84,6 +84,8 @@ @import "carbon-components/scss/globals/scss/_css--body"; @import "carbon-components/scss/globals/grid/grid"; + @import "carbon-components/src/components/treeview/treeview"; + // Import all component styles @import "carbon-components/scss/globals/scss/styles"; diff --git a/docs/src/COMPONENT_API.json b/docs/src/COMPONENT_API.json index 675d727a..fe0fa3d1 100644 --- a/docs/src/COMPONENT_API.json +++ b/docs/src/COMPONENT_API.json @@ -1,5 +1,5 @@ { - "total": 169, + "total": 170, "components": [ { "moduleName": "Accordion", @@ -11834,6 +11834,111 @@ "typedefs": [], "rest_props": { "type": "Element", "name": "button" } }, + { + "moduleName": "TreeView", + "filePath": "src/TreeView/TreeView.svelte", + "props": [ + { + "name": "children", + "kind": "let", + "description": "Provide an array of children nodes to render", + "type": "Array", + "value": "[]", + "isFunction": false, + "constant": false, + "reactive": false + }, + { + "name": "activeId", + "kind": "let", + "description": "Set the current active node id\nOnly one node can be active", + "type": "TreeNodeId", + "value": "\"\"", + "isFunction": false, + "constant": false, + "reactive": true + }, + { + "name": "selectedIds", + "kind": "let", + "description": "Set the node ids to be selected", + "type": "TreeNodeId[]", + "value": "[]", + "isFunction": false, + "constant": false, + "reactive": true + }, + { + "name": "size", + "kind": "let", + "description": "Specify the TreeView size", + "type": "\"default\" | \"compact\"", + "value": "\"default\"", + "isFunction": false, + "constant": false, + "reactive": false + }, + { + "name": "labelText", + "kind": "let", + "description": "Specify the label text", + "type": "string", + "value": "\"\"", + "isFunction": false, + "constant": false, + "reactive": false + }, + { + "name": "hideLabel", + "kind": "let", + "description": "Set to `true` to visually hide the label text", + "type": "boolean", + "value": "false", + "isFunction": false, + "constant": false, + "reactive": false + } + ], + "slots": [ + { + "name": "labelText", + "default": false, + "fallback": "{labelText}", + "slot_props": "{}" + } + ], + "events": [ + { + "type": "dispatched", + "name": "select", + "detail": "TreeNode & { expanded: boolean; leaf: boolean; }" + }, + { + "type": "dispatched", + "name": "toggle", + "detail": "TreeNode & { expanded: boolean; leaf: boolean; }" + }, + { + "type": "dispatched", + "name": "focus", + "detail": "TreeNode & { expanded: boolean; leaf: boolean; }" + }, + { "type": "forwarded", "name": "keydown", "element": "ul" } + ], + "typedefs": [ + { + "type": "string | number", + "name": "TreeNodeId", + "ts": "type TreeNodeId = string | number" + }, + { + "type": "{ id: TreeNodeId; text: string; icon?: typeof import(\"carbon-icons-svelte\").CarbonIcon; disabled?: boolean; expanded?: boolean; }", + "name": "TreeNode", + "ts": "interface TreeNode { id: TreeNodeId; text: string; icon?: typeof import(\"carbon-icons-svelte\").CarbonIcon; disabled?: boolean; expanded?: boolean; }" + } + ], + "rest_props": { "type": "Element", "name": "ul" } + }, { "moduleName": "Truncate", "filePath": "src/Truncate/Truncate.svelte", diff --git a/docs/src/pages/_layout.svelte b/docs/src/pages/_layout.svelte index 1fa85bb0..7f97d8e2 100644 --- a/docs/src/pages/_layout.svelte +++ b/docs/src/pages/_layout.svelte @@ -20,7 +20,7 @@ import Footer from "../components/Footer.svelte"; const deprecated = ["ToggleSmall", "Icon"]; - const new_components = ["ProgressBar", "RecursiveList"]; + const new_components = ["ProgressBar", "RecursiveList", "TreeView"]; let isOpen = false; let isSideNavOpen = true; @@ -264,6 +264,6 @@ } .bx--side-nav__submenu[aria-expanded="true"] + .bx--side-nav__menu { - max-height: 124rem; + max-height: 132rem; } diff --git a/docs/src/pages/components/TreeView.svx b/docs/src/pages/components/TreeView.svx new file mode 100644 index 00000000..7e1a4232 --- /dev/null +++ b/docs/src/pages/components/TreeView.svx @@ -0,0 +1,48 @@ + + +### Default + +The `children` prop accepts an array of child nodes. Each node should contain `id` and `text` properties. + +Optional properties include `disabled`, `expanded`, `icon`, and `children`. + +A parent node contains `children` while a leaf node does not. + + +
Every node must have a unique id.
+
+ + + +### Initial active node + +The active node can be set through `activeId`. + + + +### Compact size + +Set `size` to `"compact"` to use the compact variant. + + + +### With icons + +To render a node with an icon, define an `icon` property with a Carbon Svelte icon as its value. + + + +### Initial expanded nodes + +Set `expanded` to `true` on nodes that should be expanded by default. + + + +### Initial multiple selected nodes + +Initial multiple selected nodes can be set using `selectedIds`. + + \ No newline at end of file diff --git a/docs/src/pages/framed/TreeView/TreeView.svelte b/docs/src/pages/framed/TreeView/TreeView.svelte new file mode 100644 index 00000000..4489cb9c --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeView.svelte @@ -0,0 +1,65 @@ + + + + +
Active node id: {activeId}
+
Selected ids: {JSON.stringify(selectedIds)}
+ + diff --git a/docs/src/pages/framed/TreeView/TreeViewActive.svelte b/docs/src/pages/framed/TreeView/TreeViewActive.svelte new file mode 100644 index 00000000..fafeb48c --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewActive.svelte @@ -0,0 +1,65 @@ + + + + +
Active node id: {activeId}
+
Selected ids: {JSON.stringify(selectedIds)}
+ + diff --git a/docs/src/pages/framed/TreeView/TreeViewCompact.svelte b/docs/src/pages/framed/TreeView/TreeViewCompact.svelte new file mode 100644 index 00000000..0a9bf2b9 --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewCompact.svelte @@ -0,0 +1,66 @@ + + + + +
Active node id: {activeId}
+
Selected ids: {JSON.stringify(selectedIds)}
+ + diff --git a/docs/src/pages/framed/TreeView/TreeViewExpanded.svelte b/docs/src/pages/framed/TreeView/TreeViewExpanded.svelte new file mode 100644 index 00000000..819babd2 --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewExpanded.svelte @@ -0,0 +1,67 @@ + + + + +
Active node id: {activeId}
+
Selected ids: {JSON.stringify(selectedIds)}
+ + diff --git a/docs/src/pages/framed/TreeView/TreeViewIcons.svelte b/docs/src/pages/framed/TreeView/TreeViewIcons.svelte new file mode 100644 index 00000000..04de81c3 --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewIcons.svelte @@ -0,0 +1,98 @@ + + + + +
Active node id: {activeId}
+
Selected ids: {JSON.stringify(selectedIds)}
+ + diff --git a/docs/src/pages/framed/TreeView/TreeViewMultiselect.svelte b/docs/src/pages/framed/TreeView/TreeViewMultiselect.svelte new file mode 100644 index 00000000..6ea62569 --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewMultiselect.svelte @@ -0,0 +1,65 @@ + + + + +
Active node id: {activeId}
+
Selected ids: {JSON.stringify(selectedIds)}
+ + diff --git a/src/TreeView/TreeView.svelte b/src/TreeView/TreeView.svelte new file mode 100644 index 00000000..10e71aee --- /dev/null +++ b/src/TreeView/TreeView.svelte @@ -0,0 +1,120 @@ + + +{#if !hideLabel} + + +{/if} + +
    + +
diff --git a/src/TreeView/TreeViewNode.svelte b/src/TreeView/TreeViewNode.svelte new file mode 100644 index 00000000..038d2e52 --- /dev/null +++ b/src/TreeView/TreeViewNode.svelte @@ -0,0 +1,125 @@ + + + + +
  • +
    + + {text} +
    +
  • diff --git a/src/TreeView/TreeViewNodeList.svelte b/src/TreeView/TreeViewNodeList.svelte new file mode 100644 index 00000000..2f6d3ab2 --- /dev/null +++ b/src/TreeView/TreeViewNodeList.svelte @@ -0,0 +1,160 @@ + + +{#if root} + {#each children as child (child.id)} + {#if Array.isArray(child.children)} + + {:else} + + {/if} + {/each} +{:else} +
  • +
    + + + + + + {text} + +
    + {#if expanded} +
      + {#each children as child (child.id)} + {#if Array.isArray(child.children)} + + {:else} + + {/if} + {/each} +
    + {/if} +
  • +{/if} diff --git a/src/TreeView/index.js b/src/TreeView/index.js new file mode 100644 index 00000000..59f96be0 --- /dev/null +++ b/src/TreeView/index.js @@ -0,0 +1 @@ +export { default as TreeView } from "./TreeView.svelte"; diff --git a/src/index.js b/src/index.js index 14924283..5dc44324 100644 --- a/src/index.js +++ b/src/index.js @@ -126,6 +126,7 @@ export { ToggleSmall, ToggleSmallSkeleton } from "./ToggleSmall"; export { Tooltip, TooltipFooter } from "./Tooltip"; export { TooltipDefinition } from "./TooltipDefinition"; export { TooltipIcon } from "./TooltipIcon"; +export { TreeView } from "./TreeView"; export { Truncate } from "./Truncate"; export { Header, diff --git a/tests/TreeView.test.svelte b/tests/TreeView.test.svelte new file mode 100644 index 00000000..85bf8909 --- /dev/null +++ b/tests/TreeView.test.svelte @@ -0,0 +1,59 @@ + + + diff --git a/types/TreeView/TreeView.d.ts b/types/TreeView/TreeView.d.ts new file mode 100644 index 00000000..786fed62 --- /dev/null +++ b/types/TreeView/TreeView.d.ts @@ -0,0 +1,63 @@ +/// +import { SvelteComponentTyped } from "svelte"; + +export type TreeNodeId = string | number; + +export interface TreeNode { + id: TreeNodeId; + text: string; + icon?: typeof import("carbon-icons-svelte").CarbonIcon; + disabled?: boolean; + expanded?: boolean; +} + +export interface TreeViewProps + extends svelte.JSX.HTMLAttributes { + /** + * Provide an array of children nodes to render + * @default [] + */ + children?: Array; + + /** + * Set the current active node id + * Only one node can be active + * @default "" + */ + activeId?: TreeNodeId; + + /** + * Set the node ids to be selected + * @default [] + */ + selectedIds?: TreeNodeId[]; + + /** + * Specify the TreeView size + * @default "default" + */ + size?: "default" | "compact"; + + /** + * Specify the label text + * @default "" + */ + labelText?: string; + + /** + * Set to `true` to visually hide the label text + * @default false + */ + hideLabel?: boolean; +} + +export default class TreeView extends SvelteComponentTyped< + TreeViewProps, + { + select: CustomEvent; + toggle: CustomEvent; + focus: CustomEvent; + keydown: WindowEventMap["keydown"]; + }, + { labelText: {} } +> {} diff --git a/types/index.d.ts b/types/index.d.ts index 9123950f..02714fef 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -144,6 +144,7 @@ export { default as Tooltip } from "./Tooltip/Tooltip"; export { default as TooltipFooter } from "./Tooltip/TooltipFooter"; export { default as TooltipDefinition } from "./TooltipDefinition/TooltipDefinition"; export { default as TooltipIcon } from "./TooltipIcon/TooltipIcon"; +export { default as TreeView } from "./TreeView/TreeView"; export { default as Truncate } from "./Truncate/Truncate"; export { default as Header } from "./UIShell/GlobalHeader/Header"; export { default as HeaderAction } from "./UIShell/GlobalHeader/HeaderAction";