# Pages and navigation

A `ui.Router` keeps the history of the pages of a window, or of a part of
one, as a browser does for a tab. A page is a path, as `/notes/42`, which
`View` matches to build the page shown, a `switch` over patterns whose
`{name}` takes one part of the path and `{name...}` the rest.

The router is part of your app's state: make it once, with the page to
show first, and keep it in a field. The view, which runs for every frame,
builds the page it shows:

```go
// notesApp is the app's state.
type notesApp struct {
	router *ui.Router
	// … the notes and the files
}

func main() {
	app := &notesApp{router: ui.NewRouter("/notes")}
	mygo.App.WhenReady(func() {
		mygo.NewWindow(mygo.WindowOptions{Title: "Notes", Content: ui.View(app.view)})
	})
	if err := mygo.App.Run(); err != nil {
		log.Fatal(err)
	}
}

func (app *notesApp) view(c *ui.Context) {
	ui.Row(c).Fill().AlignItems(ui.Stretch).Children(func() {
		app.sidebar(c) // stays as the pages change, see below
		app.router.View(c, func(r *ui.Route) {
			switch {
			case r.Match("/notes"):
				r.Title("Notes")
				app.notes(c)
			case r.Match("/notes/{id}"):
				r.Title("Note")
				app.note(c, r.Param("id"))
			case r.Match("/files/{path...}"):
				app.files(c, r.Param("path"))
			default:
				ui.Text(c, "Not found")
			}
		})
	})
}
```

`app.notes`, `app.note` and `app.files` are methods of `notesApp` that
build those pages, as `view` builds the window.

## Going to pages

`Push` goes to a page, after the page shown, `Replace` shows one in its
place, and `Back`, `Forward` and `Go` move through the history; paths
relative to the page shown resolve as links in a web page do, so
`Push("?tab=info")` changes the query and `Push("edit")` goes to a sibling.
A [link](https://mygo.egoist.dev/docs/ui/link.md) to a path in a page goes there in its router, and
choosing an item of a [sidebar](https://mygo.egoist.dev/docs/ui/sidebar.md) pushes its page, as the sidebar
of the app above does:

```go
func (app *notesApp) sidebar(c *ui.Context) {
	page := app.router.Path()
	ui.Sidebar(c, &page, func() {
		ui.SidebarItem(c, "/notes", nil, "Notes")
		ui.SidebarItem(c, "/files", nil, "Files")
	}).Width(220).OnChange(func() {
		app.router.Push(page)
	})
}

// In a page:
ui.Link(c, "Open note", "/notes/42")
```

`Path`, `Query` and `Location` read the page shown; `Location` with its
query, which `NewRouter` takes to show it again when the app starts. A deep
link (`mygo.App.OnOpenURL`) pushes its page.

## Back and forward

Users go back and forward as in browsers and Finder: Cmd+\[ and Cmd+] on
macOS, Alt+Left and Alt+Right on Linux and Windows, the back and forward
buttons of a mouse and the keys of keyboards that have them, swiping
between pages on a touchpad on macOS, and the
[back and forward buttons](https://mygo.egoist.dev/docs/ui/history-buttons.md), which a toolbar holds, and
whose right click lists the pages to go back or forward to, by their
titles. The keys go to the router holding the keyboard focus, else to the
first of the window.

In a [browser](https://mygo.egoist.dev/docs/ui/browsers.md), the first router a window shows follows the
tab's history, in the URL's fragment (`#/notes/42`): going to a page adds
an entry to the browser's history, its back and forward buttons go through
the router's pages, and a URL with a fragment, opened or reloaded, shows
its page. After a reload, the router learns the pages before and after
the one shown as the browser goes to them. An app in a frame of another
page leaves the tab's history alone.

## Layouts

Anything built around `View`, as a sidebar or a toolbar, stays as pages
change. A page can also be a layout around the pages of the rest of its
path, as a page of settings with a list of its sections beside the section
shown: `r.View` on its route builds them, matching what the pattern's
`{name...}` took. The layout stays as they change, keeping its state, and
they slide or fade in its place; `Param` reads the layout's wildcards too.
A page of settings is another case of the `switch` in the view above:

```go
case r.Match("/settings/{section...}"):
	ui.Row(c).Grow(1).Children(func() {
		app.sectionList(c) // pushes "/settings/general", "/settings/fonts"
		r.View(c, func(r *ui.Route) {
			switch {
			case r.Match("/general"):
				r.Title("General")
				app.general(c)
			case r.Match("/fonts"):
				r.Title("Fonts")
				app.fonts(c)
			}
		})
	})
```

A second `Router` inside a page, in a field of its own, is a history of its
own, as the detail of a split view going deeper while the list beside it
stays.

## Pages keep their state

A page keeps the state of its elements while it is in the history, ten
pages either way: going back to one finds it scrolled where it was, with
its text and the keyboard focus where they were. A path with another query
is the same page, in another entry of the history, keeping its state, as a
page whose tabs or search are in its query.

## The focus and screen readers

Going to a page moves the keyboard focus into it, to the element that had
it there, else to the page itself, which Tab goes into; screen readers read
the page's `Title`. With the focus outside the page that changes, as in a
sidebar or a layout's list choosing the pages, it stays there, and screen
readers hear the title of the page.

## Transitions

A page deeper in the paths, as `/notes/42` after `/notes`, slides in from
the right over the page it leaves, and back up from the left; others fade
in. With less motion asked of the desktop, all fade, and
`router.Transition = ui.TransitionNone` shows them at once. The page going
away takes neither the pointer nor the keyboard as it slides.

`router.Transition = ui.TransitionMatch` fades the page going away out as
the page coming fades in, while the elements of a
[`Match`](https://mygo.egoist.dev/docs/ui/transitions.md#shared-elements) in both move from the one to the
other, as Keynote's Magic Move: a photo's thumbnail opening into its page.
Those that fly (`Fly`) go over both pages, the element of the page going
away going with the one coming, fading out, and showing no more once
there.

`router.Animation` sets how pages move, as a spring or a curve (see
[Motion](https://mygo.egoist.dev/docs/ui/motion.md)), in place of easing out over 250 ms as they slide,
150 ms as they fade, and 300 ms as they fade into each other:

```go
router.Animation = &ui.Snappy
```
