Tree View
Cross-platform extension. iOS 26 navigates hierarchies with drill-down (and split-view sidebars on iPad), not in-place collapsing tree rows — the system has no native equivalent. The closest references are shadcn/ui and forui.dev. liqkit_ui ships this rendered in iOS 26 visual language (Liquid Glass surfaces, San Francisco type, iOS color palette) so it composes cleanly with the rest of the library, but the interaction model itself is web-native rather than iOS-canonical.
LiqTreeView is the iOS 26 hierarchical list — a column of indented
rows with collapsible folders. Distinct from LiqAccordion (flat
top-level expand/collapse panels), the tree supports arbitrarily
nested children and is the right primitive for a file-explorer pane,
a document outline, or an org chart.
The widget owns its expansion state internally — pass
initialExpanded to seed which folder ids are open on first paint.
Selection is owned by the consumer: pass selectedId to highlight a
row and listen to onSelected to update it. Tapping a folder row
toggles expansion and does not fire onSelected; that callback
fires only for leaves.
Files
// ignore_for_file: file_names // hyphenated name required by snippet manifest conventionimport 'package:docs_snippets/src/demo.dart';import 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/material.dart';import 'package:liqkit_ui/liqkit_ui.dart';/// Snippet builder consumed by `apps/docs_snippets/lib/src/routes.g.dart`.Widget treeViewFilesBuilder(BuildContext context) { return SnippetFrame( child: LiqDemo<String?>( initial: null, builder: (sel, set) => LiqTreeView<String>( selectedId: sel, onSelected: (id, _) => set(id), initialExpanded: const <String>{'src', 'src/components'}, nodes: const <LiqTreeNode<String>>[ LiqTreeNode<String>( id: 'src', label: 'src', icon: Icons.folder_outlined, children: <LiqTreeNode<dynamic>>[ LiqTreeNode<String>( id: 'src/main.dart', label: 'main.dart', icon: Icons.description_outlined, ), LiqTreeNode<String>( id: 'src/components', label: 'components', icon: Icons.folder_outlined, children: <LiqTreeNode<dynamic>>[ LiqTreeNode<String>( id: 'src/components/button.dart', label: 'button.dart', icon: Icons.description_outlined, ), LiqTreeNode<String>( id: 'src/components/toggle.dart', label: 'toggle.dart', icon: Icons.description_outlined, ), ], ), ], ), LiqTreeNode<String>( id: 'pubspec.yaml', label: 'pubspec.yaml', icon: Icons.description_outlined, ), ], ), ), );}
Outline
// ignore_for_file: file_names // hyphenated name required by snippet manifest conventionimport 'package:docs_snippets/src/demo.dart';import 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/liqkit_ui.dart';/// Snippet builder consumed by `apps/docs_snippets/lib/src/routes.g.dart`.Widget treeViewOutlineBuilder(BuildContext context) { return SnippetFrame( child: LiqDemo<String?>( initial: 'ch1/intro', builder: (sel, set) => LiqTreeView<String>( selectedId: sel, onSelected: (id, _) => set(id), initialExpanded: const <String>{'ch1', 'ch2', 'ch3'}, nodes: const <LiqTreeNode<String>>[ LiqTreeNode<String>( id: 'ch1', label: '1. Introduction', children: <LiqTreeNode<dynamic>>[ LiqTreeNode<String>(id: 'ch1/intro', label: '1.1 Overview'), LiqTreeNode<String>(id: 'ch1/scope', label: '1.2 Scope'), ], ), LiqTreeNode<String>( id: 'ch2', label: '2. Foundations', children: <LiqTreeNode<dynamic>>[ LiqTreeNode<String>(id: 'ch2/colors', label: '2.1 Colors'), LiqTreeNode<String>( id: 'ch2/typography', label: '2.2 Typography', ), LiqTreeNode<String>(id: 'ch2/spacing', label: '2.3 Spacing'), ], ), LiqTreeNode<String>( id: 'ch3', label: '3. Components', children: <LiqTreeNode<dynamic>>[ LiqTreeNode<String>(id: 'ch3/buttons', label: '3.1 Buttons'), LiqTreeNode<String>(id: 'ch3/forms', label: '3.2 Forms'), ], ), ], ), ), );}