GrTreeSections

  • core
  • data
  • API · 13 props

A tree whose top level becomes a section heading instead of a node.

import { GrTreeSections } from '@feugene/granularity/components/GrTreeSections'

Overview

When to take it

  • the roots are categories, not items — settings, access rights, directories: selecting the heading itself is pointless, while naming it is necessary;
  • two levels of content — under each heading an ordinary tree whose depth is no longer about headings;
  • the sections need weight in the structure of the page — the heading gets a real level (h2…h6) and lands in the outline of the document;
  • a counter at the heading — how many nodes are in the section, without expanding.

When to take something else

NeedTake
The top level is a node like the restGrTree
Markup of your own and roles of your own entirelyuseTree
The tree is in a selection panel rather than on the screenGrTreeSelect
Sections of which one is openGrCollapse
A table of contents of the page with a highlight by scrollGrScrollSpy

Playground controls come from the API, not from hand

Stage

Loading…

0 changed· state is in the URL

Examples 3 each with a live demo and its code

  • The sidebar of an API reference

    Resources are categories, not endpoints: choosing «Invoices» itself means nothing, but it needs a name. With heading-level the roots become real headings of the level the page needs — here 4, under the example’s own title — and the page outline lists them; under each sits an ordinary tree with its own keyboard ring — Tab moves between groups, the arrows inside one. v-model:current-key is one for all groups; the default slot adds the HTTP method.

    Finalize an invoicePOST /v1/invoices/{id}/finalizeLocks the lines of a draft and assigns the invoice number. A finalized invoice can be voided, not edited.
  • Which events send an email

    show-checkbox works as in the tree, but each group counts its own parents and never touches its neighbours, so all groups share one v-model:checked-keys without losses. The heading slot replaces the label of a group with a summary of what is on in it.

    Email notifications4 events send an email

    Billing2 of 4 on

    Invoice issued
    Payment failed
    First attempt
    Final attempt
    Renewal in 7 days

    Security2 of 2 on

    Sign-in from a new device
    API key created

    Team0 of 2 on

    Member joined
    Member removed
  • Sources in a query editor

    A dense rail: size="xs" with a narrower indent keeps three levels inside 15rem, and show-count puts the number of top-level entries next to each source without opening it. node-click hands over the row and its node, and the parent schema completes the table name in the query.

    Untitled queryselect * from billing.invoices limit 100

API generated from the package · cannot drift

Props

PropTypedefaultDescription
datarequiredT[]—The data of an ordinary tree. The roots become headings, their children become trees.
nodeKey"id" | Extract<keyof T, string> | undefined"id" as neverThe field with the key of a node. The keys are unique across all groups at once: the current node and the checks are kept in one set by them. `id` by default.
propsGrTreePropsMap | undefinedundefinedThe names of the fields in the data: `children`, `label`, `isLeaf`. `children` and `label` by default.
size"xs" | "sm" | "md" | "lg" | undefinedundefinedThe size of the rows of all groups, as in `GrTree`. Unset — from `GrConfigProvider`, otherwise `md`.
headingLevel2 | 3 | 4 | 5 | 6 | undefined3The heading level of a group to fit the structure of the page.
showCountboolean | undefinedfalseShow the number of first-level nodes in a group.
showCheckboxboolean | undefinedfalseCheckboxes at the nodes: a multiple choice on top of the groups.
checkStrictlyboolean | undefinedfalseDo not link the parents and the children: every node is checked on its own.
branchLineboolean | GrTreeBranchLine | undefinedundefinedThe guide lines of the levels: `line` is a vertical per level, `elbow` adds an elbow to the row as well. `line` by default.
indentnumber | undefined0The step of the indent of a level in pixels. `0` (the default) means the value from the theme.
defaultExpandedKeysGrTreeKey[] | undefined[]The initial set of expanded nodes in all groups. A new array replaces the expansion entirely.
currentKeyv-modelGrTreeKey | undefinedundefinedThe current node (`v-model:currentKey`) — one for all groups.
checkedKeysv-modelGrTreeKey[] | undefinedundefinedThe checked keys of all groups in one list (`v-model:checkedKeys`).

Slots

SlotTypeDescription
heading{ data: T; label: string; count: number; }The heading of a group as a whole — instead of the label of the root node.
default{ node: GrTreeNode<T>; data: T; }A row inside a group, as in `GrTree`.

Events

EventSignatureDescription
update:currentKey(e: "update:currentKey", key: GrTreeKey | undefined): voidThe current node has changed by a click or `Enter` in any of the groups (`v-model:currentKey`).
update:checkedKeys(e: "update:checkedKeys", keys: GrTreeKey[]): voidThe checks have changed (`v-model:checkedKeys`): the checks of a group are merged with the checks of the other groups from `checkedKeys`; parents checked in a cascade are included too.
nodeClick(e: "nodeClick", data: any, node: GrTreeNode<any>): voidA node has been selected by a click or `Enter` and has become the current one — the row data and the node, as in `GrTree`.

Types

Every exported type of the subpath, grouped by the file it lives in. Names, generics and bodies come from the package’s declaration files and cannot drift.

Import
import type { GrTreeSectionsProps, GrTreeSectionsEmits, GrTreeSectionsInstance } from '@feugene/granularity/components/GrTreeSections'

Filedist/types/components/GrTreeSections/GrTreeSections.vue.d.ts

GrTreeSectionsPropsinterface
interface GrTreeSectionsProps<TData extends object = any> {
    data: TData[];
    nodeKey?: GrTreeDataProps<TData>['nodeKey'];
    props?: GrTreePropsMap;
    size?: GrComponentSize;
    headingLevel?: 2 | 3 | 4 | 5 | 6;
    showCount?: boolean;
    showCheckbox?: boolean;
    checkStrictly?: boolean;
    branchLine?: boolean | GrTreeBranchLine;
    indent?: number;
    defaultExpandedKeys?: GrTreeKey[];
    currentKey?: GrTreeKey;
    checkedKeys?: GrTreeKey[];
}
GrTreeSectionsEmitsinterface
interface GrTreeSectionsEmits {
    (e: 'update:currentKey', key: GrTreeKey | undefined): void;
    (e: 'update:checkedKeys', keys: GrTreeKey[]): void;
    (e: 'nodeClick', data: any, node: GrTreeNode<any>): void;
}

Filedist/types/components/GrTreeSections/config.d.ts

grTreeSectionsConfigconst
const grTreeSectionsConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrTreeSections">;

Filedist/types/components/GrTreeSections/safelist.d.ts

grTreeSectionsSafelistconst
const grTreeSectionsSafelist: string[];

Filedist/types/components/GrTreeSections/index.d.ts

GrTreeSectionsInstancetype
type GrTreeSectionsInstance = ComponentExposed<typeof GrTreeSectionsComponent>;

Usage from the library prose

Inside there are several trees, not one with headings

That is not a detail of the implementation but a requirement of the pattern: role="tree" obliges its children to be treeitem, and a heading between the rows either breaks the role or remains a row and lies to a screen reader about what it is. Headings between separate trees are legal, and each group declares itself — the name of the tree is taken from the caption of the heading.

Hence a consequence worth knowing in advance: each group has a keyboard ring of its own, and Tab moves between them while the arrows walk inside one. That is right in substance — the groups are independent — but differs from a single tree, where the arrows pass through the whole list.

One selection, the ticks add up

The selected node is one across all groups: the keys are unique, so the other groups simply will not find a foreign key among their own.

The ticks are collected as a union over the groups. They can be reduced to one list without losses precisely because the groups have no common parent: the inheritance inside each is computed on its own and does not affect the neighbours.

The limits
  • the headings do not collapse. A heading is a heading, not a toggle; a collapsible section is needed — that is GrCollapse with a tree inside;
  • deeper than three levels the device stops helping. The first level is taken by the heading, the second lies flat, and beyond that goes the ordinary staircase of indentation — and there are more headings than content.