App shell
Sidebar with constrained content
Workspace
Settings
Page content
open System
open FSharp.ViewEngine
open Acme.Components.Primitives
open Acme.Components.Application
open type Html
open type Svg
open type Datastar
type ShellLayoutDestination = Dashboard | Projects | Preferences
let shellLayoutLabel = function
| Dashboard -> "Dashboard"
| Projects -> "Projects"
| Preferences -> "Settings"
let shellLayoutUrl = function
| Dashboard -> "/components/app-shell"
| Projects -> "/components/app-shell?section=projects"
| Preferences -> "/components/app-shell?section=settings"
let shellLayoutExample id width bottomNavigation current =
let layoutLabel = if bottomNavigation then "Full-width workspace" else "Constrained workspace"
let navigation =
SideNav.create (id + "-navigation") (layoutLabel + " navigation") (SideNavHeader.create "Workspace") [
SideNavSection.ungrouped [
SideNavItem.create Dashboard "Dashboard"
SideNavItem.create Projects "Projects"
SideNavItem.create Preferences "Settings" ] ]
|> SideNav.withCurrent current
|> SideNav.withFooter (a { _href (shellLayoutUrl Preferences); _class "block px-3 py-2 text-sm font-semibold"; "Andy Meier" })
let content =
Page.create (PageHeader.create (shellLayoutLabel current)) (
div {
_class "grid min-h-80 place-items-center rounded-lg border border-dashed border-[var(--fve-border)] bg-[var(--fve-surface-subtle)] p-6 text-center text-sm text-[var(--fve-muted-text)]"
"Page content"
})
|> Page.withWidth width
|> Page.withTopBar (
PageTopBar.create ()
|> PageTopBar.withContent (div {
_class "flex min-h-[var(--fve-shell-bar-min-height)] items-center px-4 sm:px-6 lg:px-8"
Breadcrumbs.create (id + "-breadcrumbs") (layoutLabel + " breadcrumb") [
if current <> Dashboard then BreadcrumbItem.create Dashboard "Dashboard"
BreadcrumbItem.create current (shellLayoutLabel current) ]
|> Breadcrumbs.render shellLayoutUrl
}))
|> Page.render shellLayoutUrl
let shell =
AppShell.create id navigation content
|> AppShell.withBoundary AppShellBoundary.Container
|> AppShell.asPreview (layoutLabel + " layout preview")
let shell =
if bottomNavigation then
shell |> AppShell.withMobileBottomNavigation (id + "-bottom") "Workspace quick navigation" [
BottomNavigationItem.create Dashboard "Dashboard"
BottomNavigationItem.create Projects "Projects"
BottomNavigationItem.create Preferences "Settings" ]
else shell
div {
_class "h-[36rem]"
shell |> AppShell.render shellLayoutUrl
}
shellLayoutExample "layout-sidebar" PageWidth.Reading false DashboardFull-width content with mobile bottom navigation
Workspace
Settings
Page content
open System
open FSharp.ViewEngine
open Acme.Components.Primitives
open Acme.Components.Application
open type Html
open type Svg
open type Datastar
type ShellLayoutDestination = Dashboard | Projects | Preferences
let shellLayoutLabel = function
| Dashboard -> "Dashboard"
| Projects -> "Projects"
| Preferences -> "Settings"
let shellLayoutUrl = function
| Dashboard -> "/components/app-shell"
| Projects -> "/components/app-shell?section=projects"
| Preferences -> "/components/app-shell?section=settings"
let shellLayoutExample id width bottomNavigation current =
let layoutLabel = if bottomNavigation then "Full-width workspace" else "Constrained workspace"
let navigation =
SideNav.create (id + "-navigation") (layoutLabel + " navigation") (SideNavHeader.create "Workspace") [
SideNavSection.ungrouped [
SideNavItem.create Dashboard "Dashboard"
SideNavItem.create Projects "Projects"
SideNavItem.create Preferences "Settings" ] ]
|> SideNav.withCurrent current
|> SideNav.withFooter (a { _href (shellLayoutUrl Preferences); _class "block px-3 py-2 text-sm font-semibold"; "Andy Meier" })
let content =
Page.create (PageHeader.create (shellLayoutLabel current)) (
div {
_class "grid min-h-80 place-items-center rounded-lg border border-dashed border-[var(--fve-border)] bg-[var(--fve-surface-subtle)] p-6 text-center text-sm text-[var(--fve-muted-text)]"
"Page content"
})
|> Page.withWidth width
|> Page.withTopBar (
PageTopBar.create ()
|> PageTopBar.withContent (div {
_class "flex min-h-[var(--fve-shell-bar-min-height)] items-center px-4 sm:px-6 lg:px-8"
Breadcrumbs.create (id + "-breadcrumbs") (layoutLabel + " breadcrumb") [
if current <> Dashboard then BreadcrumbItem.create Dashboard "Dashboard"
BreadcrumbItem.create current (shellLayoutLabel current) ]
|> Breadcrumbs.render shellLayoutUrl
}))
|> Page.render shellLayoutUrl
let shell =
AppShell.create id navigation content
|> AppShell.withBoundary AppShellBoundary.Container
|> AppShell.asPreview (layoutLabel + " layout preview")
let shell =
if bottomNavigation then
shell |> AppShell.withMobileBottomNavigation (id + "-bottom") "Workspace quick navigation" [
BottomNavigationItem.create Dashboard "Dashboard"
BottomNavigationItem.create Projects "Projects"
BottomNavigationItem.create Preferences "Settings" ]
else shell
div {
_class "h-[36rem]"
shell |> AppShell.render shellLayoutUrl
}
shellLayoutExample "layout-bottom" PageWidth.Full true DashboardFor populated pages and a connected workflow, explore Account management. These shell examples intentionally show only the layout.