build method

  1. @override
Widget build(
  1. BuildContext context
)
override

Composes theme-scaled navigation and chrome around the stable page slot.

Implementation

@override
Widget build(BuildContext context) {
  final theme = CarpenterTheme.of(context);
  final gap = context.units(theme.spacing.small);
  Widget heading(bool compact) => Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    mainAxisSize: MainAxisSize.min,
    children: [
      if (!compact) ...[
        CarpenterText.title(applicationLabel),
        SizedBox(height: gap),
        CarpenterControl(
          semanticLabel: '$workspaceLabel. $workspaceCaption',
          onTap: onWorkspacePressed,
          builder: (context, state) => DecoratedBox(
            decoration: BoxDecoration(
              color: state.hovered || state.focused
                  ? theme.overlay.hovered
                  : theme.surface.base,
              border: Border.all(
                color: state.focused
                    ? theme.focus.color
                    : theme.overlay.border,
                width: context.units(theme.focus.width),
              ),
              borderRadius: BorderRadius.circular(
                context.units(theme.shapes.radius(ShapeRole.rounded)),
              ),
            ),
            child: Padding(
              padding: EdgeInsets.all(gap),
              child: Row(
                children: [
                  CarpenterIcon(workspaceIcon),
                  SizedBox(width: gap),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        CarpenterText.label(workspaceLabel, maxLines: 2),
                        CarpenterText.caption(
                          workspaceCaption,
                          colorRole: ContentColorRole.secondary,
                        ),
                      ],
                    ),
                  ),
                  const CarpenterIcon(GravityIcons.chevronsExpandVertical),
                ],
              ),
            ),
          ),
        ),
      ] else
        CarpenterIconButton(
          icon: workspaceIcon,
          semanticLabel: '$workspaceLabel. $workspaceCaption',
          onPressed: onWorkspacePressed,
          prominence: ActionProminence.ghost,
        ),
      if ((compact ? navigation.compactHeader : navigation.header)
          case final Widget header) ...[
        SizedBox(height: gap),
        header,
      ],
    ],
  );
  final sidebar = CarpenterSidebarData(
    sections: navigation.sections,
    selectedId: navigation.selectedId,
    onSelected: navigation.onSelected,
    semanticLabel: navigation.semanticLabel,
    header: heading(false),
    compactHeader: heading(true),
    footer: navigation.footer,
    compactFooter: navigation.compactFooter,
  );
  final root = CarpenterRootLayout(
    sidebar: sidebar,
    sidebarExpanded: sidebarExpanded,
    onSidebarExpandedChanged: onSidebarExpandedChanged,
    sidebarVisible: sidebarVisible,
    sidebarOpen: sidebarOpen,
    onSidebarOpenChanged: onSidebarOpenChanged,
    viewportPolicy: viewportPolicy,
    headerBuilder: _header,
    body: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        ?notice,
        ?activity,
        Expanded(key: const ValueKey('workspace-body'), child: body),
        ?footer,
      ],
    ),
  );
  return CallbackShortcuts(
    bindings: {
      if (searchAction?.shortcut != null && searchAction!.isEnabled)
        searchAction!.shortcut!: searchAction!.onInvoke!,
    },
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        ?nativeTitleBar,
        Expanded(key: const ValueKey('workspace-root'), child: root),
      ],
    ),
  );
}