rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1package gallery
2
3// Every gallery page is the sidebar shell Fiesta ships: the gallery
4// documents the shell by being one. pageTemplate is Rastrillo's page
5// template over Fiesta's seams: say in place of P and T, the scheme
6// menu lifted from the scheme-menu example in place of the three
7// buttons, the page's Icon and Asset methods, every link the gallery
8// owns marked data-gallery-nav, and the scheme store attribute on
9// <html> so fiesta.js remembers the choice.
10//
11// The head loads tokens.css, the theme, shell.css and gallery.css, then
12// gallery.js blocking, so a stored scheme is on the root and the
13// frame-hiding rule is armed before the first paint; fiesta.js and
14// anchor.js deferred, as the scheme-menu example loads them; shell.js
15// deferred and render-blocking, as the layouts load it, so the slide's
16// direction is set at the first render.
17//
18// The Overview's phone heading leaves the shell's brand span empty and
19// puts the gallery's name in the title span after it. The shell hides
20// a brand span with no element in it, as a blank brand, and shows the
21// title instead; a brand link would add a tab stop that goes to the
22// page it is on. The ds-prefs menu is written once per page, in the
23// index's header row or in a content page's back strip, and both it
24// and the bar draw their controls from one value, so the two cannot
25// differ.
26//
27// The live region at the foot carries the Copy button's three words
28// and the join as data attributes, so the script writes no words of
29// its own.
30const pageTemplate = `{{define "ds-controls"}}<nav rst-seg-tabs aria-label="{{say "gallery.theme.label"}}">{{range .Themes}}<a data-gallery-nav href="{{.Href}}"{{if .Current}} aria-current="page"{{end}}>{{.Label}}</a>{{end}}</nav>
31{{.Scheme}}
32<details rst-dropdown rst-locale name="rst-menus">
33<summary>{{say "gallery.language"}}<span rst-caret aria-hidden="true">{{icon "chevron-down"}}</span><span class="rst-sr-only">{{say "gallery.language.current" "language" .LocaleName}}</span></summary>
34<div rst-dropdown-menu>{{range .Locales}}<a data-gallery-nav href="{{.Href}}" lang="{{.Code}}" dir="{{.Dir}}"{{if .Current}} aria-current="true"{{end}}>{{.Name}}</a>{{end}}</div>
35</details>{{end}}
36{{define "ds-prefs"}}<details rst-dropdown class="ds-prefs" id="ds-prefs" name="ds-prefs"><summary aria-label="{{say "gallery.prefs"}}">` + cogIcon + `</summary><div rst-dropdown-menu>{{template "ds-controls" .}}</div></details>{{end}}
37{{define "ds-page"}}<!doctype html>
38<html lang="{{.Lang}}" dir="{{.Dir}}" {{.HTMLAttrs}}>
39<head>
40<meta charset="utf-8">
41<meta name="viewport" content="width=device-width">
42<title>{{.Title}}</title>
43<link rel="stylesheet" href="{{.Asset "css/tokens.css"}}">
44<link rel="stylesheet" href="{{.Asset (print "css/themes/" .Theme ".css")}}">
45<link rel="stylesheet" href="{{.Asset "css/shell.css"}}">
46<link rel="stylesheet" href="{{.Asset "gallery.css"}}">
47<script src="{{.Asset "gallery.js"}}"></script>
48{{range .Scripts}}<script defer src="{{$.Asset (print "js/" .)}}"></script>
49{{end}}<script defer blocking="render" src="{{.Asset "js/shell.js"}}"></script>
50</head>
51<body>
52<div rst-shell-sidebar="{{if .Rows}}index{{else}}page{{end}}">
53<a rst-skip href="#main">{{say "gallery.skip"}}</a>
54{{with .Up}}<div rst-shell-back><a data-gallery-nav href="{{.}}" rel="up" aria-label="{{say "gallery.up" "name" (say "gallery.up.label")}}">{{say "gallery.up.label"}}</a>{{template "ds-prefs" $.Bar}}</div>
55{{end}}<aside class="ds-rail" rst-shell-rail>
56{{if .Rows}}<h1 rst-shell-title><span></span><span>{{say "gallery.brand"}}</span></h1>
57{{template "ds-prefs" .Bar}}
58<p class="ds-index-lead">{{say "gallery.overview.intro"}}</p>
59{{end}} <search class="ds-search">
60 <label class="rst-sr-only" for="ds-filter">{{say "gallery.filter"}}</label>
61 {{icon "search"}}<input id="ds-filter" type="search" placeholder="{{say "gallery.filter"}}" autocomplete="off" aria-controls="ds-nav" data-ds-filter>
62 </search>
63 <p class="ds-nav__empty" data-ds-filter-empty role="status" hidden>{{say "gallery.filter.empty"}}</p>
64{{if .Rows}} <nav class="ds-index" rst-shell-nav aria-label="{{say "gallery.up.label"}}">{{range .Rows}}<a id="{{.ID}}" data-gallery-nav href="{{.Href}}">{{.Title}}</a>{{end}}<p rst-shell-group>{{.Demos.Title}}</p>{{range .Demos.Items}}<a data-gallery-nav href="{{.Href}}" target="_blank" rel="noopener">{{.Label}}<span class="rst-sr-only"> ({{say "gallery.newtab"}})</span></a>{{end}}</nav>
65{{end}} <nav class="ds-nav" rst-shell-nav id="ds-nav" aria-label="{{say "gallery.nav.sections"}}">
66{{range .Nav}}{{if .Items}} <details{{if .Current}} open aria-current="page"{{end}}><summary><span rst-caret aria-hidden="true">{{icon "chevron-down"}}</span>{{.Title}}</summary>{{range .Items}}<a data-gallery-nav href="{{.Href}}"{{if .Current}} aria-current="page"{{end}}{{if .Aria}} aria-label="{{.Aria}}"{{end}}{{if .Code}} class="rst-mono"{{end}}{{if .Blank}} target="_blank" rel="noopener"{{end}}{{if .Terms}} data-ds-terms="{{.Terms}}"{{end}}>{{.Label}}{{if .Blank}}<span class="rst-sr-only"> ({{say "gallery.newtab"}})</span>{{end}}</a>{{end}}</details>
67{{else}} <a class="ds-nav__page" data-gallery-nav href="{{.Href}}"{{if .Current}} aria-current="page"{{end}}>{{.Title}}</a>
68{{end}}{{end}} </nav>
69</aside>
70<header class="ds-top">
71<a class="ds-top__brand" data-gallery-nav href="{{.Home}}">{{say "gallery.brand"}}</a>
72<div class="ds-top__controls">{{template "ds-controls" .Bar}}</div>
73</header>
74<main rst-shell-main id="main">
75<div rst-page>
76<header rst-page-header><div rst-page-header-titles><h1{{with .TitleID}} id="{{.}}"{{end}}{{if .Mono}} class="rst-mono"{{end}}>{{.Name}}</h1></div></header>
77{{.Body}}
78<nav class="ds-updown" aria-label="{{say "gallery.steps.label"}}">{{with .Prev}}<a class="ds-updown__prev" data-gallery-nav href="{{.Href}}">{{.Label}}</a>{{end}}{{with .Next}}<a class="ds-updown__next" data-gallery-nav href="{{.Href}}">{{.Label}}</a>{{end}}</nav>
79<p class="rst-sr-only" role="status" data-ds-copy-status data-copy="{{say "gallery.copy"}}" data-copied="{{say "gallery.copied"}}" data-failed="{{say "gallery.copy.failed"}}" data-join=", "></p>
80</div>
81</main>
82</div>
83</body>
84</html>
85{{end}}`
86
87// cogIcon is the display settings button's glyph, Lucide's settings
88// (ISC, as the icon set), drawn the way the set draws its own. Fiesta's
89// icons/ has no settings glyph and is frozen, and this one button is
90// the gallery's furniture, not something an app is offered, so it is
91// drawn here rather than given a slug. aria-hidden: the button's name
92// is its aria-label.
93const cogIcon = `<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">` +
94 `<path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"/><circle cx="12" cy="12" r="3"/></svg>`
95
96func init() { registerTemplate(pageTemplate) }
97