///|
fn sidebar_icon_only(scope : SidebarSurfaceScope) -> Bool {
!scope.mobile &&
scope.collapsible == SidebarIcon &&
scope.owner.state.collapsed
}
///|
pub fn SidebarSurfaceScope::is_icon_only(self : SidebarSurfaceScope) -> Bool {
sidebar_icon_only(self)
}
///|
pub fn SidebarSurfaceScope::variant(
self : SidebarSurfaceScope,
) -> SidebarVariant {
self.variant
}
///|
pub fn sidebar_surface(
scope : SidebarScope,
render~ : (SidebarSurfaceScope) -> @minimoon.Node,
side? : SidebarSide = SidebarLeft,
variant? : SidebarVariant = SidebarDefault,
collapsible? : SidebarCollapsible = SidebarOffcanvas,
mobile? : Bool = false,
hidden? : Bool = false,
aria_label? : String = "Sidebar",
id? : String,
class? : String = "",
style? : String = "",
) -> @minimoon.Node {
if hidden || (mobile && (!scope.state.mobile_open || !scope.visible)) {
return @minimoon.nothing()
}
let surface = SidebarSurfaceScope::{
owner: scope,
side,
variant,
collapsible,
mobile,
}
let collapsed = !mobile &&
collapsible != SidebarFixed &&
scope.state.collapsed
let width = if collapsed {
if collapsible == SidebarIcon {
48.0
} else {
0.0
}
} else {
scope.state.width
}
let edge = if side == SidebarLeft { "left" } else { "right" }
let variant_style = match variant {
SidebarDefault => "border:1px solid var(--mmui-border);"
SidebarFloating =>
"margin:8px;border:1px solid var(--mmui-border);border-radius:var(--mmui-radius);box-shadow:0 4px 16px rgba(0,0,0,.12);"
SidebarInset => "margin:8px;border-radius:var(--mmui-radius);"
}
let node = ui_container(
"sidebar-surface",
id=id.unwrap_or(scope.id + (if mobile { "-mobile" } else { "-surface" })),
class~,
style="box-sizing:border-box;display:flex;flex-direction:column;flex-shrink:0;min-height:0;position:relative;overflow:hidden;background:var(--mmui-muted);color:var(--mmui-foreground);width:" +
width.to_string() +
"px;" +
variant_style +
(if mobile {
"position:fixed;top:0;bottom:0;" +
edge +
":0;max-width:calc(100vw - 32px);"
} else if side == SidebarRight {
"order:2;"
} else {
"order:0;"
}) +
style,
semantics=@minimoon.semantics(
role=if mobile { @minimoon.DialogRole } else { @minimoon.NavigationRole },
label=aria_label,
modal=mobile,
hidden=collapsed && collapsible == SidebarOffcanvas,
),
if collapsed && collapsible == SidebarOffcanvas {
[]
} else {
[render(surface)]
},
)
if mobile {
@minimoon.layer(id=scope.id + "-mobile-layer", [
@minimoon.tap_view(
on_tap=sidebar_close_mobile(scope),
event_key=scope.id + "/mobile-dismiss",
class="mmui-overlay",
style="position:fixed;left:0;right:0;top:0;bottom:0;",
@minimoon.nothing(),
),
node,
])
} else {
node
}
}
///|
pub fn[C : @minimoon.IsChildren] sidebar_trigger(
scope : SidebarScope,
children : C,
mobile? : Bool = false,
disabled? : Bool = false,
id? : String,
class? : String = "",
on_tap? : @minimoon.Cmd,
) -> @minimoon.Node {
@minimoon.button_children(
id=id.unwrap_or(
scope.id + (if mobile { "-mobile-trigger" } else { "-trigger" }),
),
class="mmui-sidebar-trigger " + class,
disabled~,
event_key=scope.id + (if mobile { "/mobile-toggle" } else { "/toggle" }),
semantics=@minimoon.semantics(
expanded=if mobile {
scope.state.mobile_open
} else {
!scope.state.collapsed
},
controls=scope.id + (if mobile { "-mobile" } else { "-surface" }),
),
on_tap=if disabled {
@minimoon.none
} else {
@minimoon.batch([
(scope.send)(if mobile { ToggleMobile } else { ToggleCollapsed }),
on_tap.unwrap_or(@minimoon.none),
])
},
children,
)
}
///|
pub fn sidebar_rail(
scope : SidebarSurfaceScope,
min_width? : Double = 160.0,
max_width? : Double = 512.0,
class? : String = "",
) -> @minimoon.Node {
if scope.mobile || scope.collapsible == SidebarFixed {
return @minimoon.nothing()
}
guard min_width > 0.0 &&
min_width <= max_width &&
max_width - max_width == 0.0 else {
abort("sidebar rail needs finite ordered positive width bounds")
}
let send = scope.owner.send
@minimoon.touch_view(
id=scope.owner.id + "-rail",
class="mmui-sidebar-rail " + class,
style="position:absolute;top:0;bottom:0;" +
(if scope.side == SidebarLeft { "right" } else { "left" }) +
":0;width:24px;",
catch_move=true,
event_key=scope.owner.id + "/rail",
on_tap=send(RailTap),
on_touch_start=send.map(detail => {
RailStart(scope.side, min_width, max_width, detail)
}),
on_touch_move=send.map(detail => RailMove(detail)),
on_touch_end=send.map(detail => RailEnd(detail)),
on_touch_cancel=send.map(detail => RailCancel(detail)),
semantics=@minimoon.semantics(
role=@minimoon.SeparatorRole,
orientation="vertical",
label="Resize or toggle sidebar",
expanded=!scope.owner.state.collapsed,
),
@minimoon.div(
style="position:absolute;left:50%;width:2px;top:0;bottom:0;background:var(--mmui-border);",
@minimoon.nothing(),
),
)
}