Build typed, expandable navigation with selected destinations and visible nested rails.
Contract
| Selection | Use defaultValue for local selection or TRTreeNav.controlled with value and onValueChange for parent-owned selection. |
| Expansion | initiallyExpanded seeds a group; TRTreeNavController reads or changes the live expanded set. |
| Nesting | Every nested level adds a guide rail and indentation; groups containing the selected leaf use active emphasis. |
| Persistence | pageStorageId restores expanded groups within the nearest PageStorage; selection ownership is unchanged. |
| Content | description adds a muted secondary line. leading and trailing stay aligned around the complete row. A group trailing replaces its chevron; a leaf can opt into a disclosure indicator after its trailing content. |
| Scale | Omit uiSize to follow TRUiDensityScope. Every size uses 8 logical pixels above and below the content. Standard density preserves the 40-pixel one-line leaf minimum; descriptions grow the row from its content. |
Use TRTreeNav for an ordered collection or TRNavigationRow for one standalone destination. Tab follows reading order. Enter and Space activate the focused row, Up and Down move between tree rows, and the logical expand and collapse arrow keys follow text direction. Enabled rows show hover and pressed surfaces for pointer feedback. Disabled rows are skipped and ignore pointer and keyboard input.
Install
Add the package, then import its public library.
flutter pub add tinyrack_ui
import 'package:tinyrack_ui/tinyrack_ui.dart';
Playground
Usage
import 'package:material_ui/material_ui.dart';
import 'package:tinyrack_ui/tinyrack_ui.dart';
class DocsTree extends StatefulWidget {
const DocsTree({super.key});
@override
State<DocsTree> createState() => _DocsTreeState();
}
class _DocsTreeState extends State<DocsTree> {
String? currentPage = 'theming';
@override
Widget build(BuildContext context) => TRTreeNav<String>.controlled(
value: currentPage,
onValueChange: (value) => setState(() => currentPage = value),
pageStorageId: 'docs-navigation',
semanticLabel: 'Documentation',
items: const [
TRTreeNavGroup(
value: 'guides',
label: Text('GUIDES'),
description: Text('Product documentation'),
initiallyExpanded: true,
children: [
TRTreeNavLeaf(
value: 'install',
label: Text('Install'),
description: Text('Add and configure the package'),
),
TRTreeNavGroup(
value: 'advanced',
label: Text('ADVANCED'),
initiallyExpanded: true,
children: [
TRTreeNavLeaf(value: 'plugins', label: Text('Plugins')),
TRTreeNavLeaf(value: 'theming', label: Text('Theming')),
],
),
],
),
],
);
}
Examples
API
TRNavigationRow properties
label, description | Widget, Widget? · label required | Render the primary label and an optional muted secondary line. |
leading, trailing | Widget?, Widget? · null | Add content around the label. The automatic disclosure indicator follows trailing content. |
selected, enabled | bool, bool · false, true | Control selected emphasis and whether the row can be activated. |
onPressed | VoidCallback? · null | Activate the destination. A row without a callback is non-actionable and omits its indicator. |
uiSize | TRUiSize? · density default | Override the row and content scale supplied by TRUiDensityScope. |
TRTreeNav properties
items | List<TRTreeNavItem<T>> · required | Defines the ordered groups and destinations. |
value, defaultValue | T?, T? · null | Control selection or initialize uncontrolled selection. |
onValueChange | ValueChanged<T?>? · null | Reports an enabled leaf activation. |
controller | TRTreeNavController<T>? · null | Observes selection and owns the expanded group set. |
pageStorageId, semanticLabel | Object?, String? · null | Persist expansion and name the navigation region for assistive technology. |
uiSize | TRUiSize? · density default | Override the row and content scale supplied by TRUiDensityScope. |
TRTreeNavGroup properties
value, label, children | T, Widget, List<TRTreeNavItem<T>> · required | Identify the group and define its trigger and nested nodes. |
initiallyExpanded | bool · false | Adds the group to the initial expanded set. |
key | Key? · null | Identifies the rendered group row for state restoration and precise interaction. |
description | Widget? · null | Adds a muted secondary line below the group label. |
disabled, leading, trailing | bool?, Widget?, Widget? · null | Disable expansion or decorate the row; trailing replaces the chevron. |
TRTreeNavLeaf properties
value, label | T, Widget · required | Identify and render a selectable destination. |
description | Widget? · null | Adds a muted secondary line below the destination label. |
key | Key? · null | Identifies the rendered destination row even when labels repeat. |
disabled, leading, trailing | bool?, Widget?, Widget? · null | Block selection or add content before and after the label. |
showDisclosureIndicator | bool · false | Show a direction-aware indicator after trailing content for an enabled destination. |
TRTreeNavController API
value, expanded | T?, Set<T> | Read the current selection and an unmodifiable expanded set. |
select, toggle | void Function(T?), void Function(T) | Change selection or invert one group’s expansion. |
setExpanded, replaceExpanded | methods | Set one group or replace the complete expanded set. |