on master help sign in
various: toggle search onclick, autofocus
c87ee75Matilde Park
components/Header.js+8−2
@@ -47,7 +47,7 @@ function MenuTray(props) {
47}
47}
48
48
49// This is the header for the index page
49// This is the header for the index page
50−export default function Header() {
50+export default function Header(props) {
51 const [isOpen, toggleTray] = useState(false);
51 const [isOpen, toggleTray] = useState(false);
52 return (
52 return (
53 <header className="layout-wide flex justify-between items-center pt-8">
53 <header className="layout-wide flex justify-between items-center pt-8">
@@ -73,7 +73,13 @@ export default function Header() {
73 Events
73 Events
74 </ActiveLink>
74 </ActiveLink>
75 <button className="mr-5 text-green type-ui">Download Port</button>
75 <button className="mr-5 text-green type-ui">Download Port</button>
76+ <button
77+ onClick={(e) => {
78+ e.stopPropagation();
79+ props.toggleSearch();
80+ }}
76− <button className="button-sm bg-wall text-gray">
81+ className="button-sm bg-wall text-gray"
82+ >
77 Search Urbit.org<div className="ml-4 text-lightGray">⌘K</div>
83 Search Urbit.org<div className="ml-4 text-lightGray">⌘K</div>
78 </button>
84 </button>
79 </nav>
85 </nav>
components/Search.js+5−10
@@ -8,12 +8,11 @@ const glossarySearch = (query) => {
8 });
8 });
9};
9};
10
10
11−export default function Search() {
11+export default function Search(props) {
12 const searchRef = useRef(null);
12 const searchRef = useRef(null);
13 const [query, SetQuery] = useState("");
13 const [query, SetQuery] = useState("");
14 const [active, setActive] = useState(false);
14 const [active, setActive] = useState(false);
15 const [results, setResults] = useState([]);
15 const [results, setResults] = useState([]);
16− const [hidden, toggle] = useState(true);
17 const searchEndpoint = (query) => `/api/search?q=${query}`;
16 const searchEndpoint = (query) => `/api/search?q=${query}`;
18
17
19 const onChange = useCallback((event) => {
18 const onChange = useCallback((event) => {
@@ -39,6 +38,7 @@ export default function Search() {
39 if (searchRef.current && !searchRef.current.contains(event.target)) {
38 if (searchRef.current && !searchRef.current.contains(event.target)) {
40 setActive(false);
39 setActive(false);
41 window.removeEventListener("click", onClick);
40 window.removeEventListener("click", onClick);
41+ props.toggleSearch();
42 }
42 }
43 }, []);
43 }, []);
44
44
@@ -52,15 +52,9 @@ export default function Search() {
52 }, []);
52 }, []);
53
53
54 return (
54 return (
55− <div
56− className={
57− "fixed w-screen h-screen bg-black bg-opacity-30 z-50 flex flex-col " +
55+ <div className="fixed w-screen h-screen bg-black bg-opacity-30 z-50 flex flex-col">
58− (hidden ? "hidden" : "")
59− }
60− ref={searchRef}
61− >
62 <div className="p-12 w-100 flex flex-col min-h-0">
56 <div className="p-12 w-100 flex flex-col min-h-0">
63− <div className="relative flex flex-col">
57+ <div className="relative flex flex-col" ref={searchRef}>
64 <input
58 <input
65 className="bg-white type-ui text-green rounded-xl border-transparent p-2 outline-none relative"
59 className="bg-white type-ui text-green rounded-xl border-transparent p-2 outline-none relative"
66 onChange={onChange}
60 onChange={onChange}
@@ -68,6 +62,7 @@ export default function Search() {
68 placeholder="Search..."
62 placeholder="Search..."
69 type="text"
63 type="text"
70 value={query}
64 value={query}
65+ autoFocus={true}
71 />
66 />
72 {query.length > 0 && (
67 {query.length > 0 && (
73 <span
68 <span
pages/404.js+4−2
@@ -1,3 +1,4 @@
1+import { useState } from "react";
1import Container from "../components/Container";
2import Container from "../components/Container";
2import SingleColumn from "../components/SingleColumn";
3import SingleColumn from "../components/SingleColumn";
3import Header from "../components/Header";
4import Header from "../components/Header";
@@ -5,11 +6,12 @@ import Footer from "../components/Footer";
5import Search from "../components/Search";
6import Search from "../components/Search";
6
7
7export default function NotFound() {
8export default function NotFound() {
9+ const [showSearch, toggleSearch] = useState(false);
8 return (
10 return (
9 <Container>
11 <Container>
10− <Search />
12+ {showSearch && <Search toggleSearch={() => toggleSearch(!showSearch)} />}
11 <SingleColumn>
13 <SingleColumn>
12− <Header />
14+ <Header toggleSearch={() => toggleSearch(true)} />
13 <section className="layout-wide pt-48">
15 <section className="layout-wide pt-48">
14 <h1>404</h1>
16 <h1>404</h1>
15 <p className="mt-12">It looks like nothing is here.</p>
17 <p className="mt-12">It looks like nothing is here.</p>
pages/blog.js+3−2
@@ -10,11 +10,12 @@ import BackgroundImage from "../components/BackgroundImage";
10import { getAllPosts, formatDate } from "../lib/lib";
10import { getAllPosts, formatDate } from "../lib/lib";
11
11
12export default function Blog({ posts }) {
12export default function Blog({ posts }) {
13+ const [showSearch, toggleSearch] = useState(false);
13 return (
14 return (
14 <Container>
15 <Container>
15− <Search />
16+ {showSearch && <Search toggleSearch={() => toggleSearch(!showSearch)} />}
16 <SingleColumn>
17 <SingleColumn>
17− <Header />
18+ <Header toggleSearch={() => toggleSearch(true)} />
18 <section className="layout-wide">
19 <section className="layout-wide">
19 <div className="measure">
20 <div className="measure">
20 <h2 className="pb-16">Urbit Blog</h2>
21 <h2 className="pb-16">Urbit Blog</h2>
pages/blog/[slug].js+4−3
@@ -1,4 +1,5 @@
1import { useRouter } from "next/router";
1import { useRouter } from "next/router";
2+import { useState } from "react";
2import {
3import {
3 getPostBySlug,
4 getPostBySlug,
4 getAllPosts,
5 getAllPosts,
@@ -25,12 +26,12 @@ export default function Post({ post, nextPost, previousPost }) {
25 if (!router.isFallback && !post?.slug) {
26 if (!router.isFallback && !post?.slug) {
26 return <ErrorPage />;
27 return <ErrorPage />;
27 }
28 }
28−
29+ const [showSearch, toggleSearch] = useState(false);
29 return (
30 return (
30 <Container>
31 <Container>
31− <Search />
32+ {showSearch && <Search toggleSearch={() => toggleSearch(!showSearch)} />}
32 <SingleColumn>
33 <SingleColumn>
33− <Header />
34+ <Header toggleSearch={() => toggleSearch(true)} />
34 <section className="flex flex-col layout-wide">
35 <section className="flex flex-col layout-wide">
35 <h1>{post.title}</h1>
36 <h1>{post.title}</h1>
36 {post.extra.author ? (
37 {post.extra.author ? (
pages/docs.js+14−2
@@ -86,7 +86,13 @@ function ContentArea(props) {
86 <div className="w-full">
86 <div className="w-full">
87 <header className="flex justify-between items-center px-24 pt-12 pb-8">
87 <header className="flex justify-between items-center px-24 pt-12 pb-8">
88 <div className="type-ui">Urbit Documentation</div>
88 <div className="type-ui">Urbit Documentation</div>
89+ <button
90+ onClick={(e) => {
91+ e.stopPropagation();
92+ props.toggleSearch();
93+ }}
89− <button className="button-sm bg-wall text-gray">
94+ className="button-sm bg-wall text-gray"
95+ >
90 Search Urbit.org<div className="ml-4 text-lightGray">⌘K</div>
96 Search Urbit.org<div className="ml-4 text-lightGray">⌘K</div>
91 </button>
97 </button>
92 </header>
98 </header>
@@ -101,13 +107,19 @@ function ContentArea(props) {
101}
107}
102
108
103export default function DocsLayout({ posts, data, content }) {
109export default function DocsLayout({ posts, data, content }) {
110+ const [showSearch, toggleSearch] = useState(false);
104 return (
111 return (
105 <div className="flex w-screen h-screen min-h-screen w-screen overflow-hidden">
112 <div className="flex w-screen h-screen min-h-screen w-screen overflow-hidden">
106 <Head>
113 <Head>
107 <title>Documentation / Urbit.org</title>
114 <title>Documentation / Urbit.org</title>
108 </Head>
115 </Head>
116+ {showSearch && <Search toggleSearch={() => toggleSearch(!showSearch)} />}
109 <Sidebar>{childPages("/docs", posts.children)}</Sidebar>
117 <Sidebar>{childPages("/docs", posts.children)}</Sidebar>
118+ <ContentArea
110− <ContentArea breadcrumbs={breadcrumbs(posts, [])} title={data.title}>
119+ breadcrumbs={breadcrumbs(posts, [])}
120+ title={data.title}
121+ toggleSearch={() => toggleSearch(true)}
122+ >
111 <Markdown post={{ content: content }} />
123 <Markdown post={{ content: content }} />
112 </ContentArea>
124 </ContentArea>
113 </div>
125 </div>
pages/docs/[...slug].js+10−2
@@ -98,7 +98,13 @@ function ContentArea(props) {
98 <div className="w-full">
98 <div className="w-full">
99 <header className="flex justify-between items-center px-24 pt-12 pb-8">
99 <header className="flex justify-between items-center px-24 pt-12 pb-8">
100 <div className="type-ui">Urbit Documentation</div>
100 <div className="type-ui">Urbit Documentation</div>
101+ <button
102+ onClick={(e) => {
103+ e.stopPropagation();
104+ props.toggleSearch();
105+ }}
101− <button className="button-sm bg-wall text-gray">
106+ className="button-sm bg-wall text-gray"
107+ >
102 Search Urbit.org<div className="ml-4 text-lightGray">⌘K</div>
108 Search Urbit.org<div className="ml-4 text-lightGray">⌘K</div>
103 </button>
109 </button>
104 </header>
110 </header>
@@ -113,17 +119,19 @@ function ContentArea(props) {
113}
119}
114
120
115export default function DocsLayout({ posts, data, content, params }) {
121export default function DocsLayout({ posts, data, content, params }) {
122+ const [showSearch, toggleSearch] = useState(false);
116 return (
123 return (
117 <>
124 <>
118 <Head>
125 <Head>
119 <title>{data.title} / Documentation / Urbit.org</title>
126 <title>{data.title} / Documentation / Urbit.org</title>
120 </Head>
127 </Head>
121− <Search />
128+ {showSearch && <Search toggleSearch={() => toggleSearch(!showSearch)} />}
122 <div className="flex w-screen h-screen min-h-screen w-screen overflow-hidden">
129 <div className="flex w-screen h-screen min-h-screen w-screen overflow-hidden">
123 <Sidebar>{childPages("/docs", posts.children)}</Sidebar>
130 <Sidebar>{childPages("/docs", posts.children)}</Sidebar>
124 <ContentArea
131 <ContentArea
125 breadcrumbs={breadcrumbs(posts, params.slug.slice(0, -1))}
132 breadcrumbs={breadcrumbs(posts, params.slug.slice(0, -1))}
126 title={data.title}
133 title={data.title}
134+ toggleSearch={() => toggleSearch(true)}
127 >
135 >
128 <Markdown post={{ content: content }} />
136 <Markdown post={{ content: content }} />
129 </ContentArea>
137 </ContentArea>
pages/events.js+5−2
@@ -70,11 +70,14 @@ function EventCard(props) {
70}
70}
71
71
72export default function Events({ pastEvents, currentEvents }) {
72export default function Events({ pastEvents, currentEvents }) {
73+ const [showSearch, toggleSearch] = useState(false);
73 return (
74 return (
74 <Container>
75 <Container>
75− <Search />
76+ {showSearch && (
77+ <Search toggleSearch={() => toggleSearch(!toggleSearch)} />
78+ )}
76 <SingleColumn>
79 <SingleColumn>
77− <Header />
80+ <Header toggleSearch={() => toggleSearch(true)} />
78 <section className="layout-wide">
81 <section className="layout-wide">
79 <div className="measure">
82 <div className="measure">
80 <h2 className="pb-16">Urbit Events</h2>
83 <h2 className="pb-16">Urbit Events</h2>
pages/events/[slug].js+6−3
@@ -1,4 +1,5 @@
1import { useRouter } from "next/router";
1import { useRouter } from "next/router";
2+import { useState } from "react";
2import {
3import {
3 getPostBySlug,
4 getPostBySlug,
4 getAllPosts,
5 getAllPosts,
@@ -25,12 +26,14 @@ export default function Event({ post, nextPost, previousPost }) {
25 if (!router.isFallback && !post?.slug) {
26 if (!router.isFallback && !post?.slug) {
26 return <ErrorPage />;
27 return <ErrorPage />;
27 }
28 }
28−
29+ const [showSearch, toggleSearch] = useState(false);
29 return (
30 return (
30 <Container>
31 <Container>
31− <Search />
32+ {showSearch && (
33+ <Search toggleSearch={() => toggleSearch(!toggleSearch)} />
34+ )}
32 <SingleColumn>
35 <SingleColumn>
33− <Header />
36+ <Header toggleSearch={() => toggleSearch(true)} />
34 <section className="flex flex-col layout-wide pt-24">
37 <section className="flex flex-col layout-wide pt-24">
35 <h1>{post.title}</h1>
38 <h1>{post.title}</h1>
36 {post.extra.author ? (
39 {post.extra.author ? (
pages/grants.js+5−2
@@ -63,6 +63,7 @@ export default function Grants({ posts, categories, types, featuredGrants }) {
63 const [activeTags, setTags] = useState([]);
63 const [activeTags, setTags] = useState([]);
64 const [activeTypes, setTypes] = useState(types);
64 const [activeTypes, setTypes] = useState(types);
65 const [tab, setTab] = useState(0);
65 const [tab, setTab] = useState(0);
66+ const [showSearch, toggleSearch] = useState(false);
66
67
67 const filteredPosts = posts.reduce((acc, post) => {
68 const filteredPosts = posts.reduce((acc, post) => {
68 // Posts are returned if they match both the selected category and selected tags, or if the user has no category filters set.
69 // Posts are returned if they match both the selected category and selected tags, or if the user has no category filters set.
@@ -80,8 +81,10 @@ export default function Grants({ posts, categories, types, featuredGrants }) {
80 return (
81 return (
81 <Container>
82 <Container>
82 <SingleColumn>
83 <SingleColumn>
83− <Search />
84+ {showSearch && (
84− <Header />
85+ <Search toggleSearch={() => toggleSearch(!toggleSearch)} />
86+ )}
87+ <Header toggleSearch={() => toggleSearch(true)} />
85 {
88 {
86 // Heading and introduction
89 // Heading and introduction
87 }
90 }
pages/index.js+5−2
@@ -15,11 +15,14 @@ import { contact } from "../lib/constants";
15
15
16export default function Home({ posts, events, openGrantsCount }) {
16export default function Home({ posts, events, openGrantsCount }) {
17 const [tab, setTab] = useState(0);
17 const [tab, setTab] = useState(0);
18+ const [showSearch, toggleSearch] = useState(false);
18 return (
19 return (
19 <Container>
20 <Container>
20 <SingleColumn>
21 <SingleColumn>
21− <Search />
22+ {showSearch && (
22− <Header />
23+ <Search toggleSearch={() => toggleSearch(!showSearch)} />
24+ )}
25+ <Header toggleSearch={() => toggleSearch(true)} />
23
26
24 {
27 {
25 // Hero Statement
28 // Hero Statement