summaryrefslogtreecommitdiff
path: root/examples/docs/src/components/Header
diff options
context:
space:
mode:
authorGravatar Fred K. Schott <fkschott@gmail.com> 2021-08-26 15:04:19 -0700
committerGravatar Fred K. Schott <fkschott@gmail.com> 2021-08-26 15:04:44 -0700
commitfdd701dd88529ee0d4911283e35be86b000ed1fc (patch)
tree61d450d04633eece1c12b350b9ef3512dc2fa7b7 /examples/docs/src/components/Header
parent84c18d3030c98b2770144a8a27d1cca7bbfedc1d (diff)
parent2e8db7ad2384b756894eac6be72bcf720f7f28fa (diff)
downloadastro-fdd701dd88529ee0d4911283e35be86b000ed1fc.tar.gz
astro-fdd701dd88529ee0d4911283e35be86b000ed1fc.tar.zst
astro-fdd701dd88529ee0d4911283e35be86b000ed1fc.zip
Merge branch 'okikio/main' (#1111)
Diffstat (limited to 'examples/docs/src/components/Header')
-rw-r--r--examples/docs/src/components/Header/AstroLogo.astro18
-rw-r--r--examples/docs/src/components/Header/Header.astro132
-rw-r--r--examples/docs/src/components/Header/LanguageSelect.css47
-rw-r--r--examples/docs/src/components/Header/LanguageSelect.tsx38
-rw-r--r--examples/docs/src/components/Header/Search.css76
-rw-r--r--examples/docs/src/components/Header/Search.tsx77
-rw-r--r--examples/docs/src/components/Header/SidebarToggle.tsx27
-rw-r--r--examples/docs/src/components/Header/SkipToContent.astro21
8 files changed, 436 insertions, 0 deletions
diff --git a/examples/docs/src/components/Header/AstroLogo.astro b/examples/docs/src/components/Header/AstroLogo.astro
new file mode 100644
index 000000000..124865f1b
--- /dev/null
+++ b/examples/docs/src/components/Header/AstroLogo.astro
@@ -0,0 +1,18 @@
+---
+const {size} = Astro.props;
+---
+<svg class="logo" width={size} height={size} viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <style>
+ #flame {
+ fill: var(--theme-text-accent);
+ }
+ #a {
+ fill: var(--theme-text-accent);
+ }
+ </style>
+ <title>Logo</title>
+ <path id="a" fill-rule="evenodd" clip-rule="evenodd"
+ d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z" />
+ <path id="flame" fill-rule="evenodd" clip-rule="evenodd"
+ d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z" />
+</svg> \ No newline at end of file
diff --git a/examples/docs/src/components/Header/Header.astro b/examples/docs/src/components/Header/Header.astro
new file mode 100644
index 000000000..a50957240
--- /dev/null
+++ b/examples/docs/src/components/Header/Header.astro
@@ -0,0 +1,132 @@
+---
+import { getLanguageFromURL, KNOWN_LANGUAGE_CODES } from '../../languages.ts';
+import * as CONFIG from '../../config.ts';
+import AstroLogo from './AstroLogo.astro';
+import SkipToContent from './SkipToContent.astro';
+import SidebarToggle from './SidebarToggle.tsx';
+import LanguageSelect from './LanguageSelect.jsx';
+import Search from "./Search.jsx";
+
+const {currentPage} = Astro.props;
+const lang = currentPage && getLanguageFromURL(currentPage);
+---
+<style>
+ header {
+ z-index: 11;
+ height: var(--theme-navbar-height);
+ width: 100%;
+ background-color: var(--theme-navbar-bg);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+ position: sticky;
+ top: 0;
+ }
+
+
+ .logo {
+ display: flex;
+ overflow: hidden;
+ width: 30px;
+ font-size: 2rem;
+ flex-shrink: 0;
+ font-weight: 600;
+ line-height: 1;
+ color: hsla(var(--color-base-white), 100%, 1);
+ gap: 0.25em;
+ z-index: -1;
+ }
+
+ .logo a {
+ padding: 0.5em 0.25em;
+ margin: -0.5em -0.25em;
+ text-decoration: none;
+ font-weight: bold;
+ }
+
+ .logo a {
+ transition: color 100ms ease-out;
+ color: var(--theme-text);
+ }
+
+ .logo a:hover,
+ .logo a:focus {
+ color: var(--theme-text-accent);
+ }
+
+ .logo h1 {
+ font: inherit;
+ color: inherit;
+ margin: 0;
+ }
+
+ .nav-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 1em;
+ width: 100%;
+ max-width: 82em;
+ padding: 0 1rem;
+ }
+
+ @media (min-width: 50em) {
+ header {
+ position: static;
+ padding: 2rem 0rem;
+ }
+ .logo {
+ width: auto;
+ margin: 0;
+ z-index: 0;
+ }
+ .menu-toggle {
+ display: none;
+ }
+ .logo {
+ width: auto;
+ }
+ }
+
+ /** Style Algolia */
+ :root {
+ --docsearch-primary-color: var(--theme-accent);
+ --docsearch-logo-color: var(--theme-text);
+ }
+
+ .search-item {
+ display: none;
+ position: relative;
+ z-index: 10;
+ flex-grow: 1;
+ padding-right: 0.7rem;
+ display: flex;
+ max-width: 200px;
+ }
+ :global(.search-item > *) {
+ flex-grow: 1;
+ }
+ @media (min-width: 50em) {
+ .search-item {
+ max-width: 400px;
+ }
+ }
+</style>
+<header>
+ <SkipToContent />
+ <nav class="nav-wrapper" title="Top Navigation">
+ <div class="menu-toggle">
+ <SidebarToggle client:idle/>
+ </div>
+ <div class="logo flex">
+ <AstroLogo size={40} />
+ <a href="/">
+ <h1>Documentation</h1>
+ </a>
+ </div>
+ <div style="flex-grow: 1;"></div>
+ {KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle />}
+ {CONFIG.ALGOLIA && <div class="search-item"><Search client:idle /></div>}
+ </nav>
+</header> \ No newline at end of file
diff --git a/examples/docs/src/components/Header/LanguageSelect.css b/examples/docs/src/components/Header/LanguageSelect.css
new file mode 100644
index 000000000..4e878714b
--- /dev/null
+++ b/examples/docs/src/components/Header/LanguageSelect.css
@@ -0,0 +1,47 @@
+.language-select {
+ flex-grow: 1;
+ width: 48px;
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0.33em 0.5em;
+ overflow: visible;
+ font-weight: 500;
+ font-size: 1rem;
+ font-family: inherit;
+ line-height: inherit;
+ background-color: var(--theme-bg);
+ border-color: var(--theme-text-lighter);
+ color: var(--theme-text-light);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0.25rem;
+ outline: 0;
+ cursor: pointer;
+ transition-timing-function: ease-out;
+ transition-duration: 0.2s;
+ transition-property: border-color, color;
+ -webkit-font-smoothing: antialiased;
+ padding-left: 30px;
+ padding-right: 1rem;
+}
+.language-select-wrapper .language-select:hover,
+.language-select-wrapper .language-select:focus {
+ color: var(--theme-text);
+ border-color: var(--theme-text-light);
+}
+.language-select-wrapper {
+ color: var(--theme-text-light);
+ position: relative;
+}
+.language-select-wrapper > svg {
+ position: absolute;
+ top: 7px;
+ left: 10px;
+ pointer-events: none;
+}
+
+@media (min-width: 50em) {
+ .language-select {
+ width: 100%;
+ }
+}
diff --git a/examples/docs/src/components/Header/LanguageSelect.tsx b/examples/docs/src/components/Header/LanguageSelect.tsx
new file mode 100644
index 000000000..8b9807fe8
--- /dev/null
+++ b/examples/docs/src/components/Header/LanguageSelect.tsx
@@ -0,0 +1,38 @@
+import type { FunctionalComponent } from 'preact';
+import { h } from 'preact';
+import './LanguageSelect.css';
+import { KNOWN_LANGUAGES, langPathRegex } from '../../languages';
+
+const LanguageSelect: FunctionalComponent<{ lang: string }> = ({ lang }) => {
+ return (
+ <div class="language-select-wrapper">
+ <svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88.6 77.3" height="1.2em" width="1.2em">
+ <path fill="currentColor" d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z" />
+ <path
+ fill="currentColor"
+ d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
+ />
+ </svg>
+ <select
+ class="language-select"
+ value={lang}
+ onChange={(e) => {
+ const newLang = e.target.value;
+ let actualDest = window.location.pathname.replace(langPathRegex, '/');
+ if (actualDest == '/') actualDest = `/introduction`;
+ window.location.pathname = '/' + newLang + actualDest;
+ }}
+ >
+ {Object.keys(KNOWN_LANGUAGES).map((key) => {
+ return (
+ <option value={KNOWN_LANGUAGES[key]}>
+ <span>{key}</span>
+ </option>
+ );
+ })}
+ </select>
+ </div>
+ );
+};
+
+export default LanguageSelect;
diff --git a/examples/docs/src/components/Header/Search.css b/examples/docs/src/components/Header/Search.css
new file mode 100644
index 000000000..2056c2c8f
--- /dev/null
+++ b/examples/docs/src/components/Header/Search.css
@@ -0,0 +1,76 @@
+/** Style Algolia */
+:root {
+ --docsearch-primary-color: var(--theme-accent);
+ --docsearch-logo-color: var(--theme-text);
+}
+.search-input {
+ flex-grow: 1;
+ box-sizing: border-box;
+ width: 100%;
+ margin: 0;
+ padding: 0.33em 0.5em;
+ overflow: visible;
+ font-weight: 500;
+ font-size: 1rem;
+ font-family: inherit;
+ line-height: inherit;
+ background-color: var(--theme-divider);
+ border-color: var(--theme-divider);
+ color: var(--theme-text-light);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0.25rem;
+ outline: 0;
+ cursor: pointer;
+ transition-timing-function: ease-out;
+ transition-duration: 0.2s;
+ transition-property: border-color, color;
+ -webkit-font-smoothing: antialiased;
+}
+.search-input:hover,
+.search-input:focus {
+ color: var(--theme-text);
+ border-color: var(--theme-text-light);
+}
+.search-input:hover::placeholder,
+.search-input:focus::placeholder {
+ color: var(--theme-text-light);
+}
+.search-input::placeholder {
+ color: var(--theme-text-light);
+}
+.search-hint {
+ position: absolute;
+ top: 7px;
+ right: 19px;
+ padding: 3px 5px;
+ display: none;
+ display: none;
+ align-items: center;
+ justify-content: center;
+ letter-spacing: 0.125em;
+ font-size: 13px;
+ font-family: var(--font-mono);
+ pointer-events: none;
+ border-color: var(--theme-text-lighter);
+ color: var(--theme-text-light);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0.25rem;
+ line-height: 14px;
+}
+
+@media (min-width: 50em) {
+ .search-hint {
+ display: flex;
+ }
+}
+
+/* ------------------------------------------------------------ *\
+ DocSearch (Algolia)
+\* ------------------------------------------------------------ */
+
+.DocSearch-Modal .DocSearch-Hit a {
+ box-shadow: none;
+ border: 1px solid var(--theme-accent);
+}
diff --git a/examples/docs/src/components/Header/Search.tsx b/examples/docs/src/components/Header/Search.tsx
new file mode 100644
index 000000000..19ee513f1
--- /dev/null
+++ b/examples/docs/src/components/Header/Search.tsx
@@ -0,0 +1,77 @@
+/* jsxImportSource: react */
+import { useState, useCallback, useRef } from 'react';
+import { createPortal } from 'react-dom';
+import { DocSearchModal, useDocSearchKeyboardEvents } from '@docsearch/react';
+import * as CONFIG from '../../config.js';
+import '@docsearch/css/dist/style.css';
+import './Search.css';
+
+export default function Search() {
+ const [isOpen, setIsOpen] = useState(false);
+ const searchButtonRef = useRef();
+ const [initialQuery, setInitialQuery] = useState(null);
+
+ const onOpen = useCallback(() => {
+ setIsOpen(true);
+ }, [setIsOpen]);
+
+ const onClose = useCallback(() => {
+ setIsOpen(false);
+ }, [setIsOpen]);
+
+ const onInput = useCallback(
+ (e) => {
+ setIsOpen(true);
+ setInitialQuery(e.key);
+ },
+ [setIsOpen, setInitialQuery]
+ );
+
+ useDocSearchKeyboardEvents({
+ isOpen,
+ onOpen,
+ onClose,
+ onInput,
+ searchButtonRef,
+ });
+
+ return (
+ <>
+ <button type="button" ref={searchButtonRef} onClick={onOpen} className="search-input">
+ <svg width="24" height="24" fill="none">
+ <path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
+ </svg>
+ <span>Search</span>
+ <span className="search-hint">
+ <span className="sr-only">Press </span>
+ <kbd>/</kbd>
+ <span className="sr-only"> to search</span>
+ </span>
+ </button>
+ {isOpen &&
+ createPortal(
+ <DocSearchModal
+ initialQuery={initialQuery}
+ initialScrollY={window.scrollY}
+ onClose={onClose}
+ indexName={(CONFIG as any).ALGOLIA.indexName}
+ apiKey={(CONFIG as any).ALGOLIA.apiKey}
+ transformItems={(items) => {
+ return items.map((item) => {
+ // We transform the absolute URL into a relative URL to
+ // work better on localhost, preview URLS.
+ const a = document.createElement('a');
+ a.href = item.url;
+ const hash = a.hash === '#overview' ? '' : a.hash;
+ return {
+ ...item,
+ url: `${a.pathname}${hash}`,
+ };
+ });
+ }}
+ />,
+ document.body
+ )}
+ </>
+ );
+}
diff --git a/examples/docs/src/components/Header/SidebarToggle.tsx b/examples/docs/src/components/Header/SidebarToggle.tsx
new file mode 100644
index 000000000..97fece6b2
--- /dev/null
+++ b/examples/docs/src/components/Header/SidebarToggle.tsx
@@ -0,0 +1,27 @@
+import type { FunctionalComponent } from 'preact';
+import { h, Fragment } from 'preact';
+import { useState, useEffect } from 'preact/hooks';
+
+const MenuToggle: FunctionalComponent = () => {
+ const [sidebarShown, setSidebarShown] = useState(false);
+
+ useEffect(() => {
+ const body = document.getElementsByTagName('body')[0];
+ if (sidebarShown) {
+ body.classList.add('mobile-sidebar-toggle');
+ } else {
+ body.classList.remove('mobile-sidebar-toggle');
+ }
+ }, [sidebarShown]);
+
+ return (
+ <button type="button" aria-pressed={sidebarShown ? 'true' : 'false'} id="menu-toggle" onClick={() => setSidebarShown(!sidebarShown)}>
+ <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
+ </svg>
+ <span className="sr-only">Toggle sidebar</span>
+ </button>
+ );
+};
+
+export default MenuToggle;
diff --git a/examples/docs/src/components/Header/SkipToContent.astro b/examples/docs/src/components/Header/SkipToContent.astro
new file mode 100644
index 000000000..6df3a72ed
--- /dev/null
+++ b/examples/docs/src/components/Header/SkipToContent.astro
@@ -0,0 +1,21 @@
+<style>
+.skiplink,
+.skiplink:focus,
+.skiplink:focus-visible {
+ position: absolute;
+ padding: 0.25em;
+ font-size: larger;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 9;
+ display: block;
+ text-align: center;
+ background-color: var(--theme-text-accent);
+ color: var(--theme-bg);
+ border-radius: 0.25em;
+ outline: var(--theme-bg) solid 1px;
+ outline-offset: 0;
+}
+</style>
+<a href="#article" class="sr-only skiplink"><span>Skip to Content</span></a>