From 1cbe2b6d22565ae06b071d78bfb069e31e9ae4ca Mon Sep 17 00:00:00 2001 From: Atul Varma Date: Fri, 2 Apr 2021 19:00:29 -0400 Subject: [PATCH] Improve layout (#74) This improves the layout of all our pages to look more like the mandala page. Additionally, some form widgets now have better layout, and the header takes up less vertical space. At an implementation level, the component hierarchy of pages has been inverted to make this kind of layout easier. Now fully laid-out pages are contained within `` components that are at the top of the component hierarchy, and which are defined by each specific page (mandala, creature, vocabulary, etc). I had to do a few architectural things to avoid circular imports, though; most notably, this involved the creation of a new React context called a `PageContext`. It uses CSS grid, which should be pretty well-supported amongst recent browsers. --- index.html | 85 ++++++++++++++++++------- lib/browser-main.tsx | 70 ++++----------------- lib/page.tsx | 60 ++++++++++++++++++ lib/pages/creature-page.tsx | 90 ++++++++++++++------------- lib/pages/debug-page.tsx | 30 +++++---- lib/pages/index.tsx | 28 +++++++++ lib/pages/mandala-page.tsx | 113 ++++++++++++++++------------------ lib/pages/vocabulary-page.tsx | 69 +++++++++++---------- lib/pages/waves-page.tsx | 106 ++++++++++++++++--------------- lib/vocabulary-widget.tsx | 4 +- 10 files changed, 376 insertions(+), 279 deletions(-) create mode 100644 lib/page.tsx create mode 100644 lib/pages/index.tsx diff --git a/index.html b/index.html index 54ad5bc..6aa9c9d 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,44 @@ Mystic Symbolic -
+
diff --git a/lib/browser-main.tsx b/lib/browser-main.tsx index 9d80a46..5dbd366 100644 --- a/lib/browser-main.tsx +++ b/lib/browser-main.tsx @@ -1,22 +1,7 @@ import React from "react"; import ReactDOM from "react-dom"; -import { WavesPage } from "./pages/waves-page"; -import { VocabularyPage } from "./pages/vocabulary-page"; -import { CreaturePage } from "./pages/creature-page"; -import { MandalaPage } from "./pages/mandala-page"; -import { DebugPage } from "./pages/debug-page"; - -const Pages = { - vocabulary: VocabularyPage, - creature: CreaturePage, - waves: WavesPage, - mandala: MandalaPage, - debug: DebugPage, -}; - -type PageName = keyof typeof Pages; - -const pageNames = Object.keys(Pages) as PageName[]; +import { PageContext, PAGE_QUERY_ARG } from "./page"; +import { pageNames, Pages, toPageName, DEFAULT_PAGE } from "./pages"; const APP_ID = "app"; @@ -26,53 +11,20 @@ if (!appEl) { throw new Error(`Unable to find #${APP_ID}!`); } -const Navbar: React.FC<{ currPageName: string }> = (props) => ( - -); - const App: React.FC<{}> = (props) => { const page = new URLSearchParams(window.location.search); - const currPageName = toPageName(page.get("p") || "", "vocabulary"); - const PageComponent = Pages[currPageName]; + const currPage = toPageName(page.get(PAGE_QUERY_ARG) || "", DEFAULT_PAGE); + const PageComponent = Pages[currPage]; + const ctx: PageContext = { + currPage, + allPages: pageNames, + }; return ( - <> -
- -
-
- -
- - + + + ); }; ReactDOM.render(, appEl); - -function isPageName(page: string): page is PageName { - return pageNames.includes(page as any); -} - -function toPageName(page: string, defaultValue: PageName): PageName { - if (isPageName(page)) return page; - return defaultValue; -} diff --git a/lib/page.tsx b/lib/page.tsx new file mode 100644 index 0000000..e7f1b98 --- /dev/null +++ b/lib/page.tsx @@ -0,0 +1,60 @@ +import React, { useContext } from "react"; +import type { PageName } from "./pages"; + +export type PageContext = { + currPage: PageName; + allPages: PageName[]; +}; + +export const PageContext = React.createContext({ + currPage: "vocabulary", + allPages: [], +}); + +export const PAGE_QUERY_ARG = "p"; + +const PageLink: React.FC<{ page: PageName }> = ({ page }) => ( + {page} +); + +const Navbar: React.FC<{}> = (props) => { + const pc = useContext(PageContext); + + return ( + + ); +}; + +export type PageProps = { + title: string; + children?: any; +}; + +export const Page: React.FC = ({ title, children }) => { + return ( +
+
+

{title}

+ +
+ {children} + +
+ ); +}; diff --git a/lib/pages/creature-page.tsx b/lib/pages/creature-page.tsx index 9f5af8b..fd93594 100644 --- a/lib/pages/creature-page.tsx +++ b/lib/pages/creature-page.tsx @@ -25,6 +25,7 @@ import { CompositionContextWidget, createSvgCompositionContext, } from "../svg-composition-context"; +import { Page } from "../page"; /** Symbols that can be the "root" (i.e., main body) of a creature. */ const ROOT_SYMBOLS = SvgVocabulary.items.filter( @@ -190,49 +191,54 @@ export const CreaturePage: React.FC<{}> = () => { }); return ( - <> -

Creature!

- -
-
- { - setComplexity(value); - newRandomSeed(); - }} - /> + +
+ +
+ { + setComplexity(value); + newRandomSeed(); + }} + /> +
+
+ +
+
+ {" "} + +
-
- +
+ + + + + + + + +
-
- {" "} - {" "} - -
- - - - - - - - - - + ); }; diff --git a/lib/pages/debug-page.tsx b/lib/pages/debug-page.tsx index 4453088..8fb8301 100644 --- a/lib/pages/debug-page.tsx +++ b/lib/pages/debug-page.tsx @@ -3,6 +3,7 @@ import { AutoSizingSvg } from "../auto-sizing-svg"; import { CreatureContext, CreatureContextType } from "../creature-symbol"; import { createCreatureSymbolFactory } from "../creature-symbol-factory"; import { HoverDebugHelper } from "../hover-debug-helper"; +import { Page } from "../page"; import { createSvgSymbolContext } from "../svg-symbol"; import { svgScale, SvgTransform } from "../svg-transform"; import { SvgVocabulary } from "../svg-vocabulary"; @@ -60,18 +61,21 @@ export const DebugPage: React.FC<{}> = () => { }; return ( - <> -

Debug!

- - - - - - {EYE_CREATURE} - - - - - + +
+ +
+
+ + + + + {EYE_CREATURE} + + + + +
+
); }; diff --git a/lib/pages/index.tsx b/lib/pages/index.tsx new file mode 100644 index 0000000..37c87d0 --- /dev/null +++ b/lib/pages/index.tsx @@ -0,0 +1,28 @@ +import { WavesPage } from "./waves-page"; +import { VocabularyPage } from "./vocabulary-page"; +import { CreaturePage } from "./creature-page"; +import { MandalaPage } from "./mandala-page"; +import { DebugPage } from "./debug-page"; + +export const Pages = { + vocabulary: VocabularyPage, + creature: CreaturePage, + waves: WavesPage, + mandala: MandalaPage, + debug: DebugPage, +}; + +export type PageName = keyof typeof Pages; + +export const pageNames = Object.keys(Pages) as PageName[]; + +export const DEFAULT_PAGE: PageName = "vocabulary"; + +export function isPageName(page: string): page is PageName { + return pageNames.includes(page as any); +} + +export function toPageName(page: string, defaultValue: PageName): PageName { + if (isPageName(page)) return page; + return defaultValue; +} diff --git a/lib/pages/mandala-page.tsx b/lib/pages/mandala-page.tsx index fdbc512..ea75e4c 100644 --- a/lib/pages/mandala-page.tsx +++ b/lib/pages/mandala-page.tsx @@ -29,6 +29,7 @@ import { CompositionContextWidget, createSvgCompositionContext, } from "../svg-composition-context"; +import { Page } from "../page"; type ExtendedMandalaCircleParams = MandalaCircleParams & { scaling: number; @@ -281,71 +282,65 @@ export const MandalaPage: React.FC<{}> = () => { } return ( - <> -

Mandala!

-
-
- +
+ +
+ First circle + +
+
+ +
+ {useTwoCircles && (
- First circle + Second circle + {" "} +
-
- -
- {useTwoCircles && ( -
- Second circle - - {" "} - -
- )} -
- {" "} - -
-
-
- - - {circles} - - + )} +
+ {" "} +
- +
+ + + {circles} + + +
+ ); }; diff --git a/lib/pages/vocabulary-page.tsx b/lib/pages/vocabulary-page.tsx index e625d85..67941ae 100644 --- a/lib/pages/vocabulary-page.tsx +++ b/lib/pages/vocabulary-page.tsx @@ -9,6 +9,7 @@ import { SvgVocabulary } from "../svg-vocabulary"; import { SvgSymbolContext } from "../svg-symbol"; import { SymbolContextWidget } from "../symbol-context-widget"; import { HoverDebugHelper } from "../hover-debug-helper"; +import { Page } from "../page"; type SvgSymbolProps = { data: SvgSymbolData; @@ -49,43 +50,47 @@ export const VocabularyPage: React.FC<{}> = () => { ); return ( - <> -

Mystic Symbolic Vocabulary

-
- - setFilter(e.target.value)} - /> + +
+
+ + setFilter(e.target.value)} + placeholder="🔎" + /> +
+
- - - {items.map((symbolData) => ( -
+
+ + {items.map((symbolData) => (
- {symbolData.name} +
+ {symbolData.name} +
+
+ +
-
- -
-
- ))} - - + ))} + +
+
); }; diff --git a/lib/pages/waves-page.tsx b/lib/pages/waves-page.tsx index 234be23..f7c2303 100644 --- a/lib/pages/waves-page.tsx +++ b/lib/pages/waves-page.tsx @@ -1,6 +1,7 @@ import React, { useState } from "react"; import { ColorWidget } from "../color-widget"; import { NumericSlider } from "../numeric-slider"; +import { Page } from "../page"; const WAVE_STROKE = "#79beda"; const WAVE_FILL = "#2b7c9e"; @@ -104,61 +105,64 @@ const Waves: React.FC<{}> = () => { return ( <> - - {waves} - -

- {" "} - -

- - - - - +
+ + {waves} + +
+
+
+ {" "} + +
+ + + + + +
); }; export const WavesPage: React.FC<{}> = () => ( - <> -

Waves!

+ - + ); diff --git a/lib/vocabulary-widget.tsx b/lib/vocabulary-widget.tsx index 8a26de3..c3dac7c 100644 --- a/lib/vocabulary-widget.tsx +++ b/lib/vocabulary-widget.tsx @@ -20,7 +20,7 @@ export function VocabularyWidget({ id = id || slugify(label); return ( - <> +
- +
); }