gallery

package
v0.49.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package gallery ships the importable component catalog that powers the /components showcase on the docs site (examples/site) and any other tool that needs to render every design-system component against an arbitrary theme — most notably the theme-configuration tool that will live inside the gofastr CLI binary (cmd/gofastr), which cannot import examples/.

The catalog is the single source of truth for which components exist and how each one renders with sensible default configuration. It is a sibling of framework/sdkdocs: both compose framework/ui + core-ui/* into a reusable, importable surface. Like sdkdocs, it is deliberately NOT part of framework/uihost — uihost must never import framework/ui (its always-on styles would leak into every host's CSS bundle), and a gallery of pre-canned demos is the opposite of a host's job.

Layering: the package imports only framework/ui, core-ui/*, and core/render. It does not import the framework root facade, framework/crud, framework/entity, or anything higher up the L1–L5 diagram in framework/ARCHITECTURE.md — so it introduces no cycle and is safely importable from cmd/gofastr, examples/site, and host apps alike.

Three of the 139 entries (sortablelist, optimisticcreate, optimisticdelete) have a live demo that is normally backed by per-visitor session state on the docs site. The gallery catalog ships self-contained seed-rendering Demo closures for them so a theme previewer or static export gets a realistic render out of the box; hosts that wire live session state (like examples/site) call the render helpers in demos.go directly from their own request-bearing SSR path, bypassing the Demo closure.

Index

Constants

This section is empty.

Variables

View Source
var Catalog = []Entry{}/* 141 elements not displayed */

Catalog — every component the showcase ships. The source of truth: hosts iterate over it to register routes, the index screen iterates to render cards, and the showcase screen iterates to look up the active entry.

Catalog stays exported (unlike the private codeSnippets / noteOnlySlugs maps) because it is a slice populated at package init and never mutated after: concurrent reads of a stable slice header are safe, and wrapping every iteration site behind a snapshot accessor would add per-call allocation for no practical safety gain. A host that reassigns Catalog after serving begins would race readers — don't.

View Source
var DemoCompany = store.New("sitedemo").String("company", "Acme Corp")

DemoCompany is a page-scoped store slice powering the /components/signal-store demo: one producer renames it, every bound consumer updates client-side. Exported so hosts that want to inspect or reset the demo's slice can.

View Source
var InitialOptimisticNotes = []OptimisticNote{
	{ID: "n1", Title: "Ship the optimistic-ui cookbook"},
	{ID: "n2", Title: "Document the mutation lifecycle"},
	{ID: "n3", Title: "Pair ConfirmAction with delete"},
}

InitialOptimisticNotes is the snapshot every session's create + delete lists seed from. The delete list only shrinks (via the delete RPC); the create list grows past it as the user clicks Add.

View Source
var SidebarShowcaseConfig = ui.SidebarConfig{
	Title:      "Docs",
	NavLabel:   "Sidebar component example",
	Variant:    ui.SidebarCollapsible,
	DrawerName: "ui-sidebar-drawer",
	Items: []ui.SidebarItem{
		{Label: "Modeling", Children: []ui.SidebarItem{
			{Label: "Entities", Href: "/docs/entities"},
			{Label: "Fields", Href: "/docs/fields"},
		}},
		{Label: "Serving", Children: []ui.SidebarItem{
			{Label: "Router", Href: "/docs/router"},
			{Label: "Middleware", Href: "/docs/middleware"},
		}},
	},
}

SidebarShowcaseConfig is the config for the /components/sidebar demo. It is shared between the inline render (the hamburger trigger in the catalog closure) and the mounted ui-sidebar-drawer widget the host mounts once at startup — so the two agree on DrawerName + content, otherwise the hamburger opens a drawer that was never mounted.

Functions

func BaseCSS added in v0.49.0

func BaseCSS(t style.Theme) string

BaseCSS renders ContributeCSS against a theme. For consumers that need a CSS string rather than a StyleSheet to build into — uihost.WithCustomCSS, for instance.

func Categories

func Categories() []string

Categories returns the distinct category names in display (catalog) order — the names of Grouped().

func CategorySlug

func CategorySlug(name string) string

CategorySlug is a fragment-safe variant of a category name. "Buttons & links" → "buttons-links". Used as both the section <id> and the rail-link href so the anchor-scroll actually lands. Without this, hrefs end up like "#Buttons & links" which the browser silently ignores.

func CodeSnippet

func CodeSnippet(slug string) string

CodeSnippet returns the example Go source for a component's showcase page, or "" when no snippet is registered. Read through this accessor rather than the private codeSnippets map so the map is never exposed as a mutable global to request handlers.

func ContributeCSS added in v0.49.0

func ContributeCSS(ss *style.StyleSheet)

ContributeCSS adds the layout classes the catalog's own Demo closures emit.

These are the gallery's contract with itself: a demo that shows three button variants wraps them in `.demo-row`, and one that stacks examples uses `.demo-stack`. The markup lives here, so the rules that make it lay out have to live here too. They were previously written out by hand in examples/site/styles_pages.go, which meant the docs site owned CSS for markup it does not emit — and the moment a second consumer appeared (the theme configurator) the rules were duplicated rather than shared.

This is layout only: flex direction and gap, every value a theme token. No colour, no border, no component styling — a demo's appearance comes from the components it renders, which is the whole point of a gallery.

func DemoFor

func DemoFor(slug string) func() render.HTML

DemoFor returns the Demo closure for slug, or nil for an unknown slug.

Hosts whose live demos need per-request session state (e.g. examples/site renders sortablelist/optimisticcreate/optimisticdelete from the visitor's own demoState) switch on the slug in their own SSR path and call the Render* helpers directly.

func DemoSectionMenuConfig

func DemoSectionMenuConfig() interactive.SectionMenuConfig

DemoSectionMenuConfig powers the /components/section-menu showcase — a small self-contained menu whose drawer the host mounts like any real menu's.

func IsNoteOnly

func IsNoteOnly(slug string) bool

IsNoteOnly reports whether the slug's showcase renders an explanatory note instead of a live demo — those components need per-page backend wiring (an RPC, a mounted widget, image sources) that a self-contained demo cannot provide.

func OptimisticDeleteModals

func OptimisticDeleteModals() []*widget.Builder

OptimisticDeleteModals returns one *widget.Builder per initial delete row (the ConfirmAction modal matching that row's Delete trigger), PLUS the opt-delete-fail-n1 modal for the "will fail" affordance. Hosts mount these once at startup, keyed off InitialOptimisticNotes — the set EVERY session seeds from and only ever shrinks below. So every rendered trigger, in any session, has its modal mounted — no orphan opt-delete-nN triggers.

func OptimisticFailDeleteTrigger

func OptimisticFailDeleteTrigger() render.HTML

OptimisticFailDeleteTrigger is the inline trigger for the "Delete (will fail)" affordance rendered below the list. It opens the dedicated opt-delete-fail-n1 modal (mounted by OptimisticDeleteModals) whose RPC always returns 422 — the runtime then leaves the opt-delete-list region untouched, exercising the optimistic-UI "failed delete leaves the row/list unchanged" invariant. Rendered as a free-standing button (no list row) so the store never carries a phantom "fail row".

func PkgForSlug

func PkgForSlug(slug string) string

PkgForSlug returns the Go source package for a component, used to link the showcase header at its API docs on pkg.go.dev. Most live in framework/ui; a few are core-ui patterns or the image pipeline.

func RenderKanbanBoard

func RenderKanbanBoard(cols []KanbanColumn, version int) render.HTML

RenderKanbanBoard renders N linked sortable columns. Each column shares Group "kanban-demo" and has a unique Container id. Version + ConflictRPC wire the 409 conflict-recovery path. The caller owns any locking around the input data — this function is lock-free.

func RenderOptimisticCreateDemoFor

func RenderOptimisticCreateDemoFor(notes []OptimisticNote) render.HTML

RenderOptimisticCreateDemoFor renders the full optimistic-create demo (code block + Add button + the supplied list) for a given notes slice. The list region is bound to a signal in mode=html; on 2xx the runtime swaps its innerHTML with the response — the fresh authoritative list (with the new row's real server-assigned id). Hosts pass the visitor's current createNotes; the gallery's seed catalog closure passes InitialOptimisticNotes.

func RenderOptimisticCreateList

func RenderOptimisticCreateList(notes []OptimisticNote) render.HTML

RenderOptimisticCreateList renders the create list as a <ul> of rows. Used at SSR and as the create-RPC response body: the runtime swaps the list region's innerHTML with this HTML on 2xx.

func RenderOptimisticDeleteDemoFor

func RenderOptimisticDeleteDemoFor(notes []OptimisticNote) render.HTML

RenderOptimisticDeleteDemoFor renders the full optimistic-delete demo (code block + the supplied list + the will-fail trigger) for a given notes slice. Hosts pass the visitor's current deleteNotes; the gallery's seed catalog closure passes InitialOptimisticNotes.

func RenderOptimisticDeleteList

func RenderOptimisticDeleteList(notes []OptimisticNote) render.HTML

RenderOptimisticDeleteList renders the delete list as a <ul> with a Delete trigger per row. Each trigger is the ConfirmAction trigger for its row's modal (mounted by OptimisticDeleteModals).

Types

type Entry

type Entry struct {
	Slug     string
	Name     string
	Category string
	Desc     string
	// Demo returns a self-contained render.HTML showing the component live,
	// configured with sensible defaults so the page works without setup.
	// Closures that need backend wiring (DataTable's RPC island,
	// ConfirmAction's modal) render a smaller stand-alone variant or a
	// static note — see NoteOnlySlugs for the set that renders an
	// explanatory note instead of a live instance.
	Demo func() render.HTML
}

Entry describes one component in the catalog. It is the shape every /components/<slug> page iterates over: main.go registers a route per entry, the index screen renders a card per entry, and the showcase screen looks up the active entry by slug.

func ByCategory

func ByCategory(category string) []Entry

ByCategory returns every entry whose Category matches, in catalog order. Returns nil if the category is unknown.

func Lookup

func Lookup(slug string) (Entry, bool)

Lookup returns the entry for slug and ok=true, or the zero Entry and ok=false if the slug is unknown.

func MustLookup

func MustLookup(slug string) Entry

MustLookup returns the entry for slug, panicking if it is unknown. Use only for slugs that are guaranteed by construction (e.g. the slug came from ranging over Catalog itself).

type Group

type Group struct {
	Name    string
	Entries []Entry
}

Group is a category-grouped slice of entries — the shape the index page and the navigation sidebar iterate over. Groups are returned in catalog (display) order.

func Grouped

func Grouped() []Group

Grouped returns the catalog grouped by category in display (catalog) order. The same category ordering is used by the index page's sections and the navigation sidebar, so the two cannot drift.

type KanbanCard

type KanbanCard struct{ Key, Title string }

KanbanCard is one draggable card on the kanban demo board.

type KanbanColumn

type KanbanColumn struct {
	ID, Title string
	Cards     []KanbanCard
}

KanbanColumn is one linked sortable column. A board is a []KanbanColumn.

func InitialKanbanColumns

func InitialKanbanColumns() []KanbanColumn

InitialKanbanColumns is the seed board every visitor's session starts from — and the board the gallery's seed Demo closure renders.

type OptimisticNote

type OptimisticNote struct {
	ID, Title string
}

OptimisticNote is one row in the optimistic-create / optimistic-delete demo lists. Each visitor's demoState carries two independent note lists — one per recipe — seeded from InitialOptimisticNotes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL