Sidebar
A vertical panel for the app or docs navigation.
<sidebar.Sidebar id="demo-sidebar" class="h-72">
<sidebar.SidebarHeader><span class="px-2 text-sm font-semibold">Gx</span></sidebar.SidebarHeader>
<sidebar.SidebarContent>
<sidebar.SidebarGroup>
<sidebar.SidebarGroupLabel>Menu</sidebar.SidebarGroupLabel>
<sidebar.SidebarGroupContent>
<sidebar.SidebarMenu>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/")} active><span>Home</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/docs")}><span>Docs</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
</sidebar.SidebarMenu>
</sidebar.SidebarGroupContent>
</sidebar.SidebarGroup>
</sidebar.SidebarContent>
<sidebar.SidebarFooter><span class="px-2 text-xs text-sidebar-foreground/70">v0.1.0</span></sidebar.SidebarFooter>
</sidebar.Sidebar>Installation
Run the command in the app module.
gx add sidebarThe command also installs button, icons and input.
The command writes these files.
| File | Path in the app |
|---|---|
Sidebar.gx |
ui/sidebar/Sidebar.gx |
SidebarHeader.gx |
ui/sidebar/SidebarHeader.gx |
SidebarContent.gx |
ui/sidebar/SidebarContent.gx |
SidebarFooter.gx |
ui/sidebar/SidebarFooter.gx |
SidebarInset.gx |
ui/sidebar/SidebarInset.gx |
SidebarSeparator.gx |
ui/sidebar/SidebarSeparator.gx |
SidebarInput.gx |
ui/sidebar/SidebarInput.gx |
SidebarTrigger.gx |
ui/sidebar/SidebarTrigger.gx |
SidebarGroup.gx |
ui/sidebar/SidebarGroup.gx |
SidebarGroupLabel.gx |
ui/sidebar/SidebarGroupLabel.gx |
SidebarGroupAction.gx |
ui/sidebar/SidebarGroupAction.gx |
SidebarGroupContent.gx |
ui/sidebar/SidebarGroupContent.gx |
SidebarMenu.gx |
ui/sidebar/SidebarMenu.gx |
SidebarMenuItem.gx |
ui/sidebar/SidebarMenuItem.gx |
SidebarMenuButton.gx |
ui/sidebar/SidebarMenuButton.gx |
SidebarMenuAction.gx |
ui/sidebar/SidebarMenuAction.gx |
SidebarMenuBadge.gx |
ui/sidebar/SidebarMenuBadge.gx |
SidebarMenuSkeleton.gx |
ui/sidebar/SidebarMenuSkeleton.gx |
SidebarMenuSub.gx |
ui/sidebar/SidebarMenuSub.gx |
SidebarMenuSubItem.gx |
ui/sidebar/SidebarMenuSubItem.gx |
SidebarMenuSubButton.gx |
ui/sidebar/SidebarMenuSubButton.gx |
Sidebar.fixtures.go |
ui/sidebar/Sidebar.fixtures.go |
SidebarHeader.fixtures.go |
ui/sidebar/SidebarHeader.fixtures.go |
SidebarContent.fixtures.go |
ui/sidebar/SidebarContent.fixtures.go |
SidebarFooter.fixtures.go |
ui/sidebar/SidebarFooter.fixtures.go |
SidebarInset.fixtures.go |
ui/sidebar/SidebarInset.fixtures.go |
SidebarSeparator.fixtures.go |
ui/sidebar/SidebarSeparator.fixtures.go |
SidebarInput.fixtures.go |
ui/sidebar/SidebarInput.fixtures.go |
SidebarTrigger.fixtures.go |
ui/sidebar/SidebarTrigger.fixtures.go |
SidebarGroup.fixtures.go |
ui/sidebar/SidebarGroup.fixtures.go |
SidebarGroupLabel.fixtures.go |
ui/sidebar/SidebarGroupLabel.fixtures.go |
SidebarGroupAction.fixtures.go |
ui/sidebar/SidebarGroupAction.fixtures.go |
SidebarGroupContent.fixtures.go |
ui/sidebar/SidebarGroupContent.fixtures.go |
SidebarMenu.fixtures.go |
ui/sidebar/SidebarMenu.fixtures.go |
SidebarMenuItem.fixtures.go |
ui/sidebar/SidebarMenuItem.fixtures.go |
SidebarMenuButton.fixtures.go |
ui/sidebar/SidebarMenuButton.fixtures.go |
SidebarMenuAction.fixtures.go |
ui/sidebar/SidebarMenuAction.fixtures.go |
SidebarMenuBadge.fixtures.go |
ui/sidebar/SidebarMenuBadge.fixtures.go |
SidebarMenuSkeleton.fixtures.go |
ui/sidebar/SidebarMenuSkeleton.fixtures.go |
SidebarMenuSub.fixtures.go |
ui/sidebar/SidebarMenuSub.fixtures.go |
SidebarMenuSubItem.fixtures.go |
ui/sidebar/SidebarMenuSubItem.fixtures.go |
SidebarMenuSubButton.fixtures.go |
ui/sidebar/SidebarMenuSubButton.fixtures.go |
styles.go |
ui/sidebar/styles.go |
Install button, icons and input first.
Copy each file to its path in the app. Change each import of a registry package to the path of that package in the app.
package sidebar
props {
// Id is the id of the root element.
// SidebarTrigger shows and hides the sidebar with the id gx-sidebar.
Id string
// Side sets the edge of the page that holds the sidebar: Left or Right.
Side Side = Left
// Class adds classes to the root element.
Class string = ""
// Children is the content of the sidebar: the header, content and footer.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<aside id={p.Id} data-gx-sidebar data-slot="sidebar" data-side={p.side()} class={gx.Cx("flex w-64 shrink-0 flex-col bg-sidebar text-sidebar-foreground data-[side=left]:border-r data-[side=right]:border-l", p.Class)} {...p.Attrs}>{p.Children}</aside>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the header.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-header" data-sidebar="header" class={gx.Cx("flex flex-col gap-2 p-2", p.Class)} {...p.Attrs}>{p.Children}</div>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the scrolling content of the sidebar: the groups.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-content" data-sidebar="content" class={gx.Cx("flex min-h-0 flex-1 flex-col gap-2 overflow-auto", p.Class)} {...p.Attrs}>{p.Children}</div>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the footer.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-footer" data-sidebar="footer" class={gx.Cx("flex flex-col gap-2 p-2", p.Class)} {...p.Attrs}>{p.Children}</div>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the main content of the page.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<main data-slot="sidebar-inset" class={gx.Cx("relative flex w-full flex-1 flex-col bg-background", p.Class)} {...p.Attrs}>{p.Children}</main>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-separator" data-sidebar="separator" role="none" data-orientation="horizontal" class={gx.Cx("h-px w-full shrink-0 bg-border", "mx-2 w-auto bg-sidebar-border", p.Class)} {...p.Attrs}></div>package sidebar
import "github.com/alternayte/gx/registry/input"
props {
// Type is the type attribute of the input. An empty value is text.
Type string = "text"
// Name is the form field name.
Name string = ""
// Value is the value of the input.
Value string = ""
// Placeholder is the text that shows while the input is empty.
Placeholder string = ""
// Class adds classes to the root element.
Class string = ""
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<input type={p.inputType()} name={p.Name} value={p.Value} placeholder={p.Placeholder} data-slot="sidebar-input" data-sidebar="input" class={gx.Cx(input.Class, "h-8 w-full bg-background shadow-none", p.Class)} {...p.Attrs} />package sidebar
import "github.com/alternayte/gx/registry/button"
import "github.com/alternayte/gx/registry/icons"
props {
// Controls is the id that aria-controls names. An empty value is gx-sidebar, the id the shell
// runtime shows and hides.
Controls string = "gx-sidebar"
// Class adds classes to the root element.
Class string = ""
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<button.Button variant={button.Ghost} size={button.Icon} class={gx.Cx("size-7", p.Class)} attrs={p.attrs()}>
<icons.PanelLeft />
<span class="sr-only">Toggle Sidebar</span>
</button.Button>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the group: the label, action and group content.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-group" data-sidebar="group" class={gx.Cx("relative flex w-full min-w-0 flex-col p-2", p.Class)} {...p.Attrs}>{p.Children}</div>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the label text of the group.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-group-label" data-sidebar="group-label" class={gx.Cx("flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear motion-reduce:transition-none focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", p.Class)} {...p.Attrs}>{p.Children}</div>package sidebar
props {
// Label is the accessible name of the button.
Label string
// Class adds classes to the root element.
Class string = ""
// Children is the icon of the button.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<button type="button" aria-label={p.Label} data-slot="sidebar-group-action" data-sidebar="group-action" class={gx.Cx("absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform motion-reduce:transition-none hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0 after:absolute after:-inset-2 md:after:hidden", p.Class)} {...p.Attrs}>{p.Children}</button>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the group, usually a SidebarMenu.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-group-content" data-sidebar="group-content" class={gx.Cx("w-full text-sm", p.Class)} {...p.Attrs}>{p.Children}</div>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the menu items.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<ul data-slot="sidebar-menu" data-sidebar="menu" class={gx.Cx("flex w-full min-w-0 flex-col gap-1", p.Class)} {...p.Attrs}>{p.Children}</ul>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the item: the menu button, action, badge and sub menu.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<li data-slot="sidebar-menu-item" data-sidebar="menu-item" class={gx.Cx("group/menu-item relative", p.Class)} {...p.Attrs}>{p.Children}</li>package sidebar
props {
// Href is the URL of the link. An empty value renders a button in place of a link.
Href gx.URL = ""
// Active marks the button of the current page.
// A link gets aria-current and a button gets data-active.
Active bool = false
// Variant sets the surface: Default or Outline.
Variant Variant = Default
// Size sets the height and the text size: Md, Sm or Lg.
Size Size = Md
// Class adds classes to the root element.
Class string = ""
// Children is the content of the button: an icon and a span with the text.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
if p.Href != "" {
<a href={p.Href} data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size={p.size()} class={p.class()} {...p.attrs()}>{p.Children}</a>
} else {
<button type="button" data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size={p.size()} class={p.class()} {...p.buttonAttrs()}>{p.Children}</button>
}package sidebar
props {
// Label is the accessible name of the button.
Label string
// ShowOnHover hides the action on a wide screen until its item has the pointer or the focus.
ShowOnHover bool = false
// Class adds classes to the root element.
Class string = ""
// Children is the icon of the button.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<button type="button" aria-label={p.Label} data-slot="sidebar-menu-action" data-sidebar="menu-action" class={gx.Cx("absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform motion-reduce:transition-none peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0 after:absolute after:-inset-2 md:after:hidden peer-data-[size=sm]/menu-button:top-1 peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5", hoverClass[p.ShowOnHover], p.Class)} {...p.Attrs}>{p.Children}</button>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the badge text.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-menu-badge" data-sidebar="menu-badge" class={gx.Cx("pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none peer-hover/menu-button:text-sidebar-accent-foreground peer-aria-[current=page]/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground peer-data-[size=sm]/menu-button:top-1 peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5", p.Class)} {...p.Attrs}>{p.Children}</div>package sidebar
props {
// ShowIcon adds an icon placeholder before the text bar.
ShowIcon bool = false
// Width is the maximum width of the text bar as a CSS length. An empty value is 70%.
Width string = "70%"
// Class adds classes to the root element.
Class string = ""
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="sidebar-menu-skeleton" data-sidebar="menu-skeleton" class={gx.Cx("flex h-8 items-center gap-2 rounded-md px-2", p.Class)} {...p.Attrs}>
if p.ShowIcon {
<div data-slot="skeleton" data-sidebar="menu-skeleton-icon" class="size-4 animate-pulse rounded-md bg-accent"></div>
}
<div data-slot="skeleton" data-sidebar="menu-skeleton-text" style={gx.Style("--skeleton-width: " + p.width())} class="h-4 max-w-(--skeleton-width) flex-1 animate-pulse rounded-md bg-accent"></div>
</div>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the sub menu items.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<ul data-slot="sidebar-menu-sub" data-sidebar="menu-sub" class={gx.Cx("mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5", p.Class)} {...p.Attrs}>{p.Children}</ul>package sidebar
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the sub item: a SidebarMenuSubButton.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<li data-slot="sidebar-menu-sub-item" data-sidebar="menu-sub-item" class={gx.Cx("group/menu-sub-item relative", p.Class)} {...p.Attrs}>{p.Children}</li>package sidebar
props {
// Href is the URL of the link.
Href gx.URL
// Active marks the link of the current page. It sets aria-current and the active style.
Active bool = false
// Size sets the text size: Md or Sm.
Size Size = Md
// Class adds classes to the root element.
Class string = ""
// Children is the content of the link: an icon and a span with the text.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<a href={p.Href} data-slot="sidebar-menu-sub-button" data-sidebar="menu-sub-button" data-size={p.size()} class={gx.Cx("flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground aria-[current=page]:bg-sidebar-accent aria-[current=page]:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground", subSizeClass[Size(p.size())], subActiveClass[p.Active], p.Class)} {...p.attrs()}>{p.Children}</a>package sidebar
import (
"github.com/alternayte/gx"
"github.com/alternayte/gx/registry/icons"
)
// more is the icon of the action fixtures.
func more() gx.Node {
return icons.Ellipsis(icons.EllipsisProps{})
}
// demoMenu is the menu of the sidebar fixtures.
func demoMenu() gx.Node {
return SidebarMenu(SidebarMenuProps{Children: gx.Frag(
SidebarMenuItem(SidebarMenuItemProps{Children: SidebarMenuButton(SidebarMenuButtonProps{Href: gx.URL("/"), Active: true, Children: gx.El("span", nil, gx.Text("Home"))})}),
SidebarMenuItem(SidebarMenuItemProps{Children: SidebarMenuButton(SidebarMenuButtonProps{Href: gx.URL("/docs"), Children: gx.El("span", nil, gx.Text("Docs"))})}),
)})
}
var SidebarFixtures = gx.Fixtures[SidebarProps]{
"Full": {Id: "demo-sidebar", Class: "h-72", Children: gx.Frag(
SidebarHeader(SidebarHeaderProps{Children: gx.El("span", gx.Attrs{{Key: "class", Value: "px-2 text-sm font-semibold"}}, gx.Text("Gx"))}),
SidebarContent(SidebarContentProps{Children: SidebarGroup(SidebarGroupProps{Children: gx.Frag(
SidebarGroupLabel(SidebarGroupLabelProps{Children: gx.Text("Menu")}),
SidebarGroupContent(SidebarGroupContentProps{Children: demoMenu()}),
)})}),
SidebarFooter(SidebarFooterProps{Children: gx.El("span", gx.Attrs{{Key: "class", Value: "px-2 text-xs text-sidebar-foreground/70"}}, gx.Text("v0.1.0"))}),
)},
"Right": {Id: "demo-sidebar-right", Side: Right, Class: "h-40", Children: SidebarContent(SidebarContentProps{
Children: SidebarGroup(SidebarGroupProps{Children: demoMenu()}),
})},
"Hidden": {Id: "demo-sidebar-hidden", Attrs: gx.Attrs{gx.Bool("hidden", true)}},
}package sidebar
import "github.com/alternayte/gx"
var SidebarHeaderFixtures = gx.Fixtures[SidebarHeaderProps]{"Empty": {}}package sidebar
import "github.com/alternayte/gx"
var SidebarContentFixtures = gx.Fixtures[SidebarContentProps]{"Empty": {}}package sidebar
import "github.com/alternayte/gx"
var SidebarFooterFixtures = gx.Fixtures[SidebarFooterProps]{"Empty": {}}package sidebar
import "github.com/alternayte/gx"
var SidebarInsetFixtures = gx.Fixtures[SidebarInsetProps]{"Page": {Class: "p-4", Children: gx.Text("Page content.")}}package sidebar
import "github.com/alternayte/gx"
var SidebarSeparatorFixtures = gx.Fixtures[SidebarSeparatorProps]{"Default": {}}package sidebar
import "github.com/alternayte/gx"
var SidebarInputFixtures = gx.Fixtures[SidebarInputProps]{"Search": {Placeholder: "Search the docs", Attrs: gx.Attrs{{Key: "aria-label", Value: "Search"}}}}package sidebar
import "github.com/alternayte/gx"
var SidebarTriggerFixtures = gx.Fixtures[SidebarTriggerProps]{"Default": {Controls: "demo-sidebar"}}package sidebar
import "github.com/alternayte/gx"
var SidebarGroupFixtures = gx.Fixtures[SidebarGroupProps]{
"Labelled": {Class: "w-64 bg-sidebar text-sidebar-foreground", Children: gx.Frag(
SidebarGroupLabel(SidebarGroupLabelProps{Children: gx.Text("Projects")}),
SidebarGroupAction(SidebarGroupActionProps{Label: "Project options", Children: more()}),
SidebarGroupContent(SidebarGroupContentProps{Children: demoMenu()}),
)},
}package sidebar
import "github.com/alternayte/gx"
var SidebarGroupLabelFixtures = gx.Fixtures[SidebarGroupLabelProps]{"Label": {Children: gx.Text("Projects")}}package sidebar
import "github.com/alternayte/gx"
var SidebarGroupActionFixtures = gx.Fixtures[SidebarGroupActionProps]{"Add": {Label: "Project options", Children: more()}}
// SidebarGroupActionWrap renders the action in a group, which positions
// it.
func SidebarGroupActionWrap(n gx.Node) gx.Node {
return SidebarGroup(SidebarGroupProps{Class: "w-64", Children: gx.Frag(
SidebarGroupLabel(SidebarGroupLabelProps{Children: gx.Text("Projects")}),
n,
)})
}package sidebar
import "github.com/alternayte/gx"
var SidebarGroupContentFixtures = gx.Fixtures[SidebarGroupContentProps]{"Empty": {}}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuFixtures = gx.Fixtures[SidebarMenuProps]{
"Nested": {Class: "w-64", Children: gx.Frag(
SidebarMenuItem(SidebarMenuItemProps{Children: gx.Frag(
SidebarMenuButton(SidebarMenuButtonProps{Href: gx.URL("/docs"), Children: gx.El("span", nil, gx.Text("Docs"))}),
SidebarMenuBadge(SidebarMenuBadgeProps{Children: gx.Text("12")}),
SidebarMenuSub(SidebarMenuSubProps{Children: gx.Frag(
SidebarMenuSubItem(SidebarMenuSubItemProps{Children: SidebarMenuSubButton(SidebarMenuSubButtonProps{Href: gx.URL("/docs/start"), Active: true, Children: gx.El("span", nil, gx.Text("Get started"))})}),
SidebarMenuSubItem(SidebarMenuSubItemProps{Children: SidebarMenuSubButton(SidebarMenuSubButtonProps{Href: gx.URL("/docs/forms"), Children: gx.El("span", nil, gx.Text("Forms"))})}),
)}),
)}),
SidebarMenuItem(SidebarMenuItemProps{Children: gx.Frag(
SidebarMenuButton(SidebarMenuButtonProps{Href: gx.URL("/projects"), Children: gx.El("span", nil, gx.Text("Projects"))}),
SidebarMenuAction(SidebarMenuActionProps{Label: "Project options", Children: more()}),
)}),
)},
"Loading": {Class: "w-64", Children: gx.Frag(
SidebarMenuItem(SidebarMenuItemProps{Children: SidebarMenuSkeleton(SidebarMenuSkeletonProps{ShowIcon: true, Width: "80%"})}),
SidebarMenuItem(SidebarMenuItemProps{Children: SidebarMenuSkeleton(SidebarMenuSkeletonProps{ShowIcon: true, Width: "55%"})}),
SidebarMenuItem(SidebarMenuItemProps{Children: SidebarMenuSkeleton(SidebarMenuSkeletonProps{ShowIcon: true, Width: "70%"})}),
)},
}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuItemFixtures = gx.Fixtures[SidebarMenuItemProps]{"Empty": {}}
// SidebarMenuItemWrap renders the part in a menu, where it belongs.
func SidebarMenuItemWrap(n gx.Node) gx.Node {
return SidebarMenu(SidebarMenuProps{Class: "w-64", Children: n})
}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuButtonFixtures = gx.Fixtures[SidebarMenuButtonProps]{
"Link": {Href: gx.URL("/docs"), Children: gx.El("span", nil, gx.Text("Docs"))},
"Active": {Href: gx.URL("/"), Active: true, Children: gx.El("span", nil, gx.Text("Home"))},
"Button": {Children: gx.El("span", nil, gx.Text("Sign out"))},
"Outline": {Variant: Outline, Href: gx.URL("/docs"), Children: gx.El("span", nil, gx.Text("Docs"))},
"Small": {Size: Sm, Href: gx.URL("/docs"), Children: gx.El("span", nil, gx.Text("Docs"))},
"Large": {Size: Lg, Href: gx.URL("/docs"), Children: gx.El("span", nil, gx.Text("Docs"))},
}
// SidebarMenuButtonWrap renders the part in a menu, where it belongs.
func SidebarMenuButtonWrap(n gx.Node) gx.Node {
return SidebarMenu(SidebarMenuProps{Class: "w-64", Children: SidebarMenuItem(SidebarMenuItemProps{Children: n})})
}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuActionFixtures = gx.Fixtures[SidebarMenuActionProps]{
"Add": {Label: "Project options", Children: more()},
"Hover": {Label: "Project options", ShowOnHover: true, Children: more()},
}
// SidebarMenuActionWrap renders the part in a menu, where it belongs.
func SidebarMenuActionWrap(n gx.Node) gx.Node {
return SidebarMenu(SidebarMenuProps{Class: "w-64", Children: SidebarMenuItem(SidebarMenuItemProps{Children: gx.Frag(SidebarMenuButton(SidebarMenuButtonProps{Href: gx.URL("/projects"), Children: gx.El("span", nil, gx.Text("Projects"))}), n)})})
}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuBadgeFixtures = gx.Fixtures[SidebarMenuBadgeProps]{"Count": {Children: gx.Text("12")}}
// SidebarMenuBadgeWrap renders the part in a menu, where it belongs.
func SidebarMenuBadgeWrap(n gx.Node) gx.Node {
return SidebarMenu(SidebarMenuProps{Class: "w-64", Children: SidebarMenuItem(SidebarMenuItemProps{Children: gx.Frag(SidebarMenuButton(SidebarMenuButtonProps{Href: gx.URL("/projects"), Children: gx.El("span", nil, gx.Text("Projects"))}), n)})})
}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuSkeletonFixtures = gx.Fixtures[SidebarMenuSkeletonProps]{
"Text": {},
"Icon": {ShowIcon: true, Width: "55%"},
}
// SidebarMenuSkeletonWrap renders the part in a menu, where it belongs.
func SidebarMenuSkeletonWrap(n gx.Node) gx.Node {
return SidebarMenu(SidebarMenuProps{Class: "w-64", Children: SidebarMenuItem(SidebarMenuItemProps{Children: n})})
}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuSubFixtures = gx.Fixtures[SidebarMenuSubProps]{
"Two": {Children: gx.Frag(
SidebarMenuSubItem(SidebarMenuSubItemProps{Children: SidebarMenuSubButton(SidebarMenuSubButtonProps{Href: gx.URL("/docs/start"), Active: true, Children: gx.El("span", nil, gx.Text("Get started"))})}),
SidebarMenuSubItem(SidebarMenuSubItemProps{Children: SidebarMenuSubButton(SidebarMenuSubButtonProps{Href: gx.URL("/docs/forms"), Size: Sm, Children: gx.El("span", nil, gx.Text("Forms"))})}),
)},
}
// SidebarMenuSubWrap renders the part in a menu, where it belongs.
func SidebarMenuSubWrap(n gx.Node) gx.Node {
return SidebarMenu(SidebarMenuProps{Class: "w-64", Children: SidebarMenuItem(SidebarMenuItemProps{Children: n})})
}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuSubItemFixtures = gx.Fixtures[SidebarMenuSubItemProps]{"Empty": {}}
// SidebarMenuSubItemWrap renders the part in a sub menu, where it belongs.
func SidebarMenuSubItemWrap(n gx.Node) gx.Node {
return gx.El("div", gx.Attrs{{Key: "class", Value: "w-64"}}, SidebarMenuSub(SidebarMenuSubProps{Children: n}))
}package sidebar
import "github.com/alternayte/gx"
var SidebarMenuSubButtonFixtures = gx.Fixtures[SidebarMenuSubButtonProps]{
"Link": {Href: gx.URL("/docs/forms"), Children: gx.El("span", nil, gx.Text("Forms"))},
"Active": {Href: gx.URL("/docs/start"), Active: true, Children: gx.El("span", nil, gx.Text("Get started"))},
"Small": {Href: gx.URL("/docs/forms"), Size: Sm, Children: gx.El("span", nil, gx.Text("Forms"))},
}
// SidebarMenuSubButtonWrap renders the part in a sub menu, where it belongs.
func SidebarMenuSubButtonWrap(n gx.Node) gx.Node {
return gx.El("div", gx.Attrs{{Key: "class", Value: "w-64"}}, SidebarMenuSub(SidebarMenuSubProps{Children: SidebarMenuSubItem(SidebarMenuSubItemProps{Children: n})}))
}package sidebar
import "github.com/alternayte/gx"
// Side is the edge of the page that holds the sidebar.
type Side string
// The sides of sidebar.Sidebar.
const (
Left Side = "left"
Right Side = "right"
)
// side returns the data-side value; a zero value is Left. The border of
// the sidebar follows this attribute.
func (p SidebarProps) side() string {
if p.Side == "" {
return string(Left)
}
return string(p.Side)
}
// Variant is the surface of a menu button.
type Variant string
// The variants of sidebar.SidebarMenuButton.
const (
Default Variant = "default"
Outline Variant = "outline"
)
var variantClass = gx.Enum[Variant]{
Default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
Outline: "bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--sidebar-accent)]",
}
// Size is the height and the text size of a menu button.
type Size string
// The sizes of sidebar.SidebarMenuButton. A sub button has Md and Sm.
const (
Md Size = "default"
Sm Size = "sm"
Lg Size = "lg"
)
var sizeClass = gx.Enum[Size]{
Md: "h-8 text-sm",
Sm: "h-7 text-xs",
Lg: "h-12 text-sm",
}
// subSizeClass is the text size of a sub button. Its height is fixed.
var subSizeClass = gx.Enum[Size]{
Md: "text-sm",
Sm: "text-xs",
Lg: "text-sm",
}
// hoverClass hides a menu action on a wide screen until its item has the
// pointer or the focus.
var hoverClass = map[bool]string{
true: "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-aria-[current=page]/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground data-[state=open]:opacity-100 md:opacity-0",
false: "",
}
// size returns the data-size value; a zero value is Md. The action and the
// badge of the item read this attribute.
func (p SidebarMenuButtonProps) size() string {
if p.Size == "" {
return string(Md)
}
return string(p.Size)
}
// class returns the classes of one menu button.
func (p SidebarMenuButtonProps) class() string {
const base = "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] motion-reduce:transition-none group-has-data-[sidebar=menu-action]/menu-item:pr-8 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 aria-[current=page]:bg-sidebar-accent aria-[current=page]:font-medium aria-[current=page]:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0"
variant := p.Variant
if variant == "" {
variant = Default
}
return gx.Cx(base, variantClass[variant], sizeClass[Size(p.size())], activeClass[p.Active], p.Class)
}
// activeClass is the look of a menu button with Active set. A link also
// takes this look from aria-current and data-active, which the framework
// keeps current for a typed href.
var activeClass = map[bool]string{
true: "bg-sidebar-accent font-medium text-sidebar-accent-foreground",
false: "",
}
// subActiveClass is the look of a sub button with Active set.
var subActiveClass = map[bool]string{
true: "bg-sidebar-accent text-sidebar-accent-foreground",
false: "",
}
// attrs marks the link of the current page, then adds the caller's
// attributes.
func (p SidebarMenuButtonProps) attrs() gx.Attrs {
if !p.Active {
return p.Attrs
}
return append(gx.Attrs{{Key: "aria-current", Value: "page"}}, p.Attrs...)
}
// buttonAttrs marks an active button, then adds the caller's attributes.
// The action and the badge of the item read data-active.
func (p SidebarMenuButtonProps) buttonAttrs() gx.Attrs {
if !p.Active {
return p.Attrs
}
return append(gx.Attrs{{Key: "data-active", Value: "true"}}, p.Attrs...)
}
// size returns the data-size value; a zero value is Md.
func (p SidebarMenuSubButtonProps) size() string {
if p.Size == "" {
return string(Md)
}
return string(p.Size)
}
// attrs marks the link of the current page, then adds the caller's
// attributes.
func (p SidebarMenuSubButtonProps) attrs() gx.Attrs {
if !p.Active {
return p.Attrs
}
return append(gx.Attrs{{Key: "aria-current", Value: "page"}}, p.Attrs...)
}
// width returns the width of the text bar; a zero value is 70%.
func (p SidebarMenuSkeletonProps) width() string {
if p.Width == "" {
return "70%"
}
return p.Width
}
// inputType returns the type of the input; a zero value is text.
func (p SidebarInputProps) inputType() string {
if p.Type == "" {
return "text"
}
return p.Type
}
// controls returns the id of the sidebar; a zero value is gx-sidebar, the
// id the shell runtime shows and hides.
func (p SidebarTriggerProps) controls() string {
if p.Controls == "" {
return "gx-sidebar"
}
return p.Controls
}
// attrs returns the attributes of the trigger: the shell runtime reads
// data-gx-menu and keeps aria-expanded current.
func (p SidebarTriggerProps) attrs() gx.Attrs {
return append(gx.Attrs{
{Key: "data-sidebar", Value: "trigger"},
gx.Bool("data-gx-menu", true),
{Key: "aria-controls", Value: p.controls()},
{Key: "aria-expanded", Value: "false"},
}, p.Attrs...)
}The theme must define these tokens: --border, --background, --accent, --sidebar, --sidebar-foreground, --sidebar-accent, --sidebar-accent-foreground, --sidebar-border, --sidebar-ring.
Usage
<sidebar.Sidebar id="gx-sidebar">
<sidebar.SidebarHeader>
<sidebar.SidebarInput name="q" placeholder="Search" />
</sidebar.SidebarHeader>
<sidebar.SidebarContent>
<sidebar.SidebarGroup>
<sidebar.SidebarGroupLabel>Menu</sidebar.SidebarGroupLabel>
<sidebar.SidebarGroupContent>
<sidebar.SidebarMenu>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={homeRoute} active={true}><span>Home</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={docsRoute}><span>Docs</span></sidebar.SidebarMenuButton>
<sidebar.SidebarMenuBadge>12</sidebar.SidebarMenuBadge>
<sidebar.SidebarMenuSub>
<sidebar.SidebarMenuSubItem>
<sidebar.SidebarMenuSubButton href={formsRoute}><span>Forms</span></sidebar.SidebarMenuSubButton>
</sidebar.SidebarMenuSubItem>
</sidebar.SidebarMenuSub>
</sidebar.SidebarMenuItem>
</sidebar.SidebarMenu>
</sidebar.SidebarGroupContent>
</sidebar.SidebarGroup>
</sidebar.SidebarContent>
<sidebar.SidebarFooter>v0.1.0</sidebar.SidebarFooter>
</sidebar.Sidebar>
<sidebar.SidebarInset>
<sidebar.SidebarTrigger class="lg:hidden" />
</sidebar.SidebarInset>SidebarMenuButton is a link when it has Href, and a button when it has none. Its variants are Default and Outline. Its sizes are Md, Sm and Lg.
SidebarMenuAction and SidebarMenuBadge sit at the right of the button of their item. SidebarGroupAction sits at the right of the group label.
SidebarMenuSkeleton is the placeholder of one menu row.
SidebarTrigger shows and hides the sidebar with the id gx-sidebar on a narrow screen. The sidebar is always visible on a wide screen.
Set side={sidebar.Right} for a sidebar at the right edge.
The sidebar is static. It has no collapsed icon mode, no rail, no floating or inset variant and no mobile sheet.
Examples
Sidebar: Full
<sidebar.Sidebar id="demo-sidebar" class="h-72">
<sidebar.SidebarHeader><span class="px-2 text-sm font-semibold">Gx</span></sidebar.SidebarHeader>
<sidebar.SidebarContent>
<sidebar.SidebarGroup>
<sidebar.SidebarGroupLabel>Menu</sidebar.SidebarGroupLabel>
<sidebar.SidebarGroupContent>
<sidebar.SidebarMenu>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/")} active><span>Home</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/docs")}><span>Docs</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
</sidebar.SidebarMenu>
</sidebar.SidebarGroupContent>
</sidebar.SidebarGroup>
</sidebar.SidebarContent>
<sidebar.SidebarFooter><span class="px-2 text-xs text-sidebar-foreground/70">v0.1.0</span></sidebar.SidebarFooter>
</sidebar.Sidebar>Sidebar: Right
<sidebar.Sidebar id="demo-sidebar-right" side={sidebar.Right} class="h-40">
<sidebar.SidebarContent>
<sidebar.SidebarGroup>
<sidebar.SidebarMenu>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/")} active><span>Home</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/docs")}><span>Docs</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
</sidebar.SidebarMenu>
</sidebar.SidebarGroup>
</sidebar.SidebarContent>
</sidebar.Sidebar>Sidebar: Hidden
<sidebar.Sidebar id="demo-sidebar-hidden" attrs={gx.Attrs{gx.Bool("hidden", true)}} children={gx.Frag()} />SidebarContent: Empty
<sidebar.SidebarContent children={gx.Frag()} />SidebarFooter: Empty
<sidebar.SidebarFooter children={gx.Frag()} />SidebarGroup: Labelled
<sidebar.SidebarGroup class="w-64 bg-sidebar text-sidebar-foreground">
<sidebar.SidebarGroupLabel>Projects</sidebar.SidebarGroupLabel>
<sidebar.SidebarGroupAction label="Project options"><icons.Ellipsis /></sidebar.SidebarGroupAction>
<sidebar.SidebarGroupContent>
<sidebar.SidebarMenu>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/")} active><span>Home</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/docs")}><span>Docs</span></sidebar.SidebarMenuButton>
</sidebar.SidebarMenuItem>
</sidebar.SidebarMenu>
</sidebar.SidebarGroupContent>
</sidebar.SidebarGroup>SidebarGroupAction: Add
<sidebar.SidebarGroupAction label="Project options"><icons.Ellipsis /></sidebar.SidebarGroupAction>SidebarGroupContent: Empty
<sidebar.SidebarGroupContent children={gx.Frag()} />SidebarGroupLabel: Label
<sidebar.SidebarGroupLabel>Projects</sidebar.SidebarGroupLabel>SidebarHeader: Empty
<sidebar.SidebarHeader children={gx.Frag()} />SidebarInput: Search
<sidebar.SidebarInput placeholder="Search the docs" attrs={gx.Attrs{{Key: "aria-label", Value: "Search"}}} />SidebarInset: Page
<sidebar.SidebarInset class="p-4">Page content.</sidebar.SidebarInset>SidebarMenu: Nested
<sidebar.SidebarMenu class="w-64">
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/docs")}><span>Docs</span></sidebar.SidebarMenuButton>
<sidebar.SidebarMenuBadge>12</sidebar.SidebarMenuBadge>
<sidebar.SidebarMenuSub>
<sidebar.SidebarMenuSubItem>
<sidebar.SidebarMenuSubButton href={gx.URL("/docs/start")} active>
<span>Get started</span>
</sidebar.SidebarMenuSubButton>
</sidebar.SidebarMenuSubItem>
<sidebar.SidebarMenuSubItem>
<sidebar.SidebarMenuSubButton href={gx.URL("/docs/forms")}><span>Forms</span></sidebar.SidebarMenuSubButton>
</sidebar.SidebarMenuSubItem>
</sidebar.SidebarMenuSub>
</sidebar.SidebarMenuItem>
<sidebar.SidebarMenuItem>
<sidebar.SidebarMenuButton href={gx.URL("/projects")}><span>Projects</span></sidebar.SidebarMenuButton>
<sidebar.SidebarMenuAction label="Project options"><icons.Ellipsis /></sidebar.SidebarMenuAction>
</sidebar.SidebarMenuItem>
</sidebar.SidebarMenu>SidebarMenu: Loading
<sidebar.SidebarMenu class="w-64">
<sidebar.SidebarMenuItem><sidebar.SidebarMenuSkeleton showIcon width="80%" /></sidebar.SidebarMenuItem>
<sidebar.SidebarMenuItem><sidebar.SidebarMenuSkeleton showIcon width="55%" /></sidebar.SidebarMenuItem>
<sidebar.SidebarMenuItem><sidebar.SidebarMenuSkeleton showIcon width="70%" /></sidebar.SidebarMenuItem>
</sidebar.SidebarMenu>SidebarMenuAction: Add
<sidebar.SidebarMenuAction label="Project options"><icons.Ellipsis /></sidebar.SidebarMenuAction>SidebarMenuAction: Hover
<sidebar.SidebarMenuAction label="Project options" showOnHover><icons.Ellipsis /></sidebar.SidebarMenuAction>SidebarMenuBadge: Count
<sidebar.SidebarMenuBadge>12</sidebar.SidebarMenuBadge>SidebarMenuButton: Link
<sidebar.SidebarMenuButton href={gx.URL("/docs")}><span>Docs</span></sidebar.SidebarMenuButton>SidebarMenuButton: Active
<sidebar.SidebarMenuButton href={gx.URL("/")} active><span>Home</span></sidebar.SidebarMenuButton>SidebarMenuButton: Button
<sidebar.SidebarMenuButton><span>Sign out</span></sidebar.SidebarMenuButton>SidebarMenuButton: Outline
<sidebar.SidebarMenuButton variant={sidebar.Outline} href={gx.URL("/docs")}>
<span>Docs</span>
</sidebar.SidebarMenuButton>SidebarMenuButton: Small
<sidebar.SidebarMenuButton size={sidebar.Sm} href={gx.URL("/docs")}><span>Docs</span></sidebar.SidebarMenuButton>SidebarMenuButton: Large
<sidebar.SidebarMenuButton size={sidebar.Lg} href={gx.URL("/docs")}><span>Docs</span></sidebar.SidebarMenuButton>SidebarMenuItem: Empty
<sidebar.SidebarMenuItem children={gx.Frag()} />SidebarMenuSkeleton: Text
<sidebar.SidebarMenuSkeleton />SidebarMenuSkeleton: Icon
<sidebar.SidebarMenuSkeleton showIcon width="55%" />SidebarMenuSub: Two
<sidebar.SidebarMenuSub>
<sidebar.SidebarMenuSubItem>
<sidebar.SidebarMenuSubButton href={gx.URL("/docs/start")} active>
<span>Get started</span>
</sidebar.SidebarMenuSubButton>
</sidebar.SidebarMenuSubItem>
<sidebar.SidebarMenuSubItem>
<sidebar.SidebarMenuSubButton href={gx.URL("/docs/forms")} size={sidebar.Sm}>
<span>Forms</span>
</sidebar.SidebarMenuSubButton>
</sidebar.SidebarMenuSubItem>
</sidebar.SidebarMenuSub>SidebarMenuSubButton: Link
<sidebar.SidebarMenuSubButton href={gx.URL("/docs/forms")}><span>Forms</span></sidebar.SidebarMenuSubButton>SidebarMenuSubButton: Active
<sidebar.SidebarMenuSubButton href={gx.URL("/docs/start")} active>
<span>Get started</span>
</sidebar.SidebarMenuSubButton>SidebarMenuSubButton: Small
<sidebar.SidebarMenuSubButton href={gx.URL("/docs/forms")} size={sidebar.Sm}>
<span>Forms</span>
</sidebar.SidebarMenuSubButton>SidebarMenuSubItem: Empty
<sidebar.SidebarMenuSubItem children={gx.Frag()} />SidebarSeparator: Default
<sidebar.SidebarSeparator />SidebarTrigger: Default
<sidebar.SidebarTrigger controls="demo-sidebar" />API reference
A tag sets a prop by its name with a lower-case first letter: Class is class.
sidebar.Sidebar
| Prop | Type | Default | Description |
|---|---|---|---|
Id |
string |
Required | Id is the id of the root element. SidebarTrigger shows and hides the sidebar with the id gx-sidebar. |
Side |
Side |
Left |
Side sets the edge of the page that holds the sidebar: Left or Right. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the sidebar: the header, content and footer. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarContent
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the scrolling content of the sidebar: the groups. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarFooter
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the footer. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarGroup
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the group: the label, action and group content. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarGroupAction
| Prop | Type | Default | Description |
|---|---|---|---|
Label |
string |
Required | Label is the accessible name of the button. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the icon of the button. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarGroupContent
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the group, usually a SidebarMenu. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarGroupLabel
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the label text of the group. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarHeader
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the header. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarInput
| Prop | Type | Default | Description |
|---|---|---|---|
Type |
string |
"text" |
Type is the type attribute of the input. An empty value is text. |
Name |
string |
"" |
Name is the form field name. |
Value |
string |
"" |
Value is the value of the input. |
Placeholder |
string |
"" |
Placeholder is the text that shows while the input is empty. |
Class |
string |
"" |
Class adds classes to the root element. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarInset
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the main content of the page. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenu
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the menu items. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenuAction
| Prop | Type | Default | Description |
|---|---|---|---|
Label |
string |
Required | Label is the accessible name of the button. |
ShowOnHover |
bool |
false |
ShowOnHover hides the action on a wide screen until its item has the pointer or the focus. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the icon of the button. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenuBadge
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the badge text. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenuButton
| Prop | Type | Default | Description |
|---|---|---|---|
Href |
gx.URL |
"" |
Href is the URL of the link. An empty value renders a button in place of a link. |
Active |
bool |
false |
Active marks the button of the current page. A link gets aria-current and a button gets data-active. |
Variant |
Variant |
Default |
Variant sets the surface: Default or Outline. |
Size |
Size |
Md |
Size sets the height and the text size: Md, Sm or Lg. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the button: an icon and a span with the text. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the item: the menu button, action, badge and sub menu. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenuSkeleton
| Prop | Type | Default | Description |
|---|---|---|---|
ShowIcon |
bool |
false |
ShowIcon adds an icon placeholder before the text bar. |
Width |
string |
"70%" |
Width is the maximum width of the text bar as a CSS length. An empty value is 70%. |
Class |
string |
"" |
Class adds classes to the root element. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenuSub
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the sub menu items. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenuSubButton
| Prop | Type | Default | Description |
|---|---|---|---|
Href |
gx.URL |
Required | Href is the URL of the link. |
Active |
bool |
false |
Active marks the link of the current page. It sets aria-current and the active style. |
Size |
Size |
Md |
Size sets the text size: Md or Sm. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the link: an icon and a span with the text. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarMenuSubItem
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the sub item: a SidebarMenuSubButton. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
sidebar.SidebarTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
Controls |
string |
"gx-sidebar" |
Controls is the id that aria-controls names. An empty value is gx-sidebar, the id the shell runtime shows and hides. |
Class |
string |
"" |
Class adds classes to the root element. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
Do and do not
Do
- Give the sidebar the id
gx-sidebarwhen it pairs withSidebarTrigger. - Put the text of a menu button in a
<span>. A long text is then cut with an ellipsis. - Give
SidebarMenuActionandSidebarGroupActionaLabel.
Don't
- Do not put a second sidebar on one page.
- Do not hide the sidebar on a wide screen.
Keyboard
| Key | Action |
|---|---|
| Tab | Moves between the links and the buttons. |
| Enter | Follows the focused link, or activates the focused button. |
| Space | Activates the focused button. |