on master help sign in
search polish
977ad50Gavin Atkinson
components/Search.js+103−87
@@ -17,6 +17,7 @@ export default function Search(props) {
17
17
18 const onChange = useCallback((event) => {
18 const onChange = useCallback((event) => {
19 const query = event.target.value;
19 const query = event.target.value;
20+
20 SetQuery(query);
21 SetQuery(query);
21 if (query.length) {
22 if (query.length) {
22 fetch(searchEndpoint(query))
23 fetch(searchEndpoint(query))
@@ -52,102 +53,117 @@ export default function Search(props) {
52 SetQuery("");
53 SetQuery("");
53 }, []);
54 }, []);
54
55
56+ // Locks document scrolling when search is open
57+ if (typeof document !== "undefined") {
58+ if (props.showSearch) {
59+ document.body.style.overflow = "hidden";
60+ } else {
61+ document.body.style.overflow = "visible";
62+ }
63+ }
64+
65+ if (props.showSearch) {
55− return (
66+ return (
56− <div className="fixed w-screen h-screen bg-black bg-opacity-30 z-50 flex flex-col">
67+ <div className="fixed w-screen h-screen bg-washedWall z-50 flex flex-col items-center">
57− <div className="p-12 w-100 flex flex-col min-h-0">
68+ <div
69+ className="relative my-32 flex flex-col max-w-screen-lg w-10/12 md:w-10/12 lg:w-8/12 xl:w-6/12 rounded-xl bg-white"
58− <div className="relative flex flex-col" ref={searchRef}>
70+ ref={searchRef}
71+ >
72+ <div className="">
59− <input
73+ <input
60− className="bg-white type-ui text-green rounded-xl border-transparent p-2 outline-none relative"
74+ className="type-ui text-green bg-transparent py-2 px-4 outline-none relative w-full"
61− onChange={onChange}
75+ onChange={onChange}
62− onFocus={onFocus}
76+ onFocus={onFocus}
63− placeholder="Search..."
77+ placeholder="Search..."
64− type="text"
78+ type="text"
65− value={query}
79+ value={query}
66− autoFocus={true}
80+ autoFocus={true}
67− />
81+ />
68− {query.length > 0 && (
82+
69 <span
83 <span
70− onClick={clear}
84+ onClick={props.toggleSearch}
71− className="absolute right-3"
85+ className="absolute right-2 top-2 cursor-pointer"
72− style={{ top: 13 }}
73 >
86 >
74− <svg
87+ <p className="px-2 h-8 bg-wall flex items-center justify-center text-sm rounded">
75− width="16"
88+ ESC
76− height="16"
89+ </p>
77− viewBox="0 0 16 16"
78− fill="none"
79− xmlns="http://www.w3.org/2000/svg"
80− >
81− <path
82− fill-rule="evenodd"
83− clip-rule="evenodd"
84− d="M0.39382 13.7045C-0.131273 14.2296 -0.131274 15.081 0.39382 15.6061C0.918913 16.1312 1.77026 16.1312 2.29535 15.6061L7.99999 9.90142L13.7047 15.6061C14.2297 16.1312 15.0811 16.1312 15.6062 15.6061C16.1313 15.081 16.1313 14.2296 15.6062 13.7046L9.90152 7.99989L15.6061 2.29535C16.1311 1.77026 16.1312 0.918913 15.6061 0.39382C15.081 -0.131273 14.2296 -0.131273 13.7045 0.39382L7.99999 6.09836L2.29548 0.393844C1.77038 -0.131249 0.919038 -0.131249 0.393945 0.393844C-0.131148 0.918937 -0.131148 1.77028 0.393945 2.29537L6.09846 7.99989L0.39382 13.7045Z"
85− fill="black"
86− fill-opacity="0.6"
87− />
88− </svg>
89 </span>
90 </span>
90− )}
91− </div>
91+ </div>
92+
92− <div
93+ <div
93− className={
94+ className={
94− "bg-white overflow-scroll min-h-0 rounded-xl border-transparent mt-2 " +
95+ "overflow-scroll min-h-0 pb-2" +
95− (query.length > 0 ? "" : "hidden")
96+ (query.length > 0 ? "" : "hidden")
96− }
97+ }
97− >
98+ >
99+ {active &&
100+ results.length === 0 &&
101+ glossaryResults.length === 0 &&
102+ query !== "" ? (
103+ <div className="flex font-semibold text-sm p-3 py-8 w-full">
104+ <p className="mr-2 text-gray">No Results found for</p>
105+ <p className="font-semibold">"{query}"</p>
106+ </div>
107+ ) : null}
98− {active && glossaryResults.length > 0 && (
108+ {active && glossaryResults.length > 0 ? (
99− <ul>
109+ <div>
110+ <div className="flex font-semibold text-sm p-3 py-1 w-full bg-ultraDeepWall text-white">
111+ <p className="font-semibold text-sm">Glossary</p>
112+ </div>
113+
100− {glossaryResults.map(({ name, link, desc, symbol }) => {
114+ {glossaryResults.map(({ name, link, desc, symbol }) => {
101− return (
115+ return (
102− <div className="border-b border-gray">
116+ <Link href={link} as={link} key={link}>
103− <p className="font-semibold text-sm pb-4 text-gray pl-3 pt-2">
104− Glossary Result
105− </p>
106− <li key={link} className="cursor-pointer hover:bg-wall">
117+ <div className="cursor-pointer hover:bg-wall">
107− <Link href={link} as={link}>
108− <div className="font-semibold px-3">
118+ <div className="font-semibold p-3">
109 {symbol.length > 0 && (
119 {symbol.length > 0 && (
110− <code className="mr-1">{symbol}</code>
120+ <code className="mr-1 bg-wall rounded px-1 py-0.5">
121+ {symbol}
122+ </code>
111 )}
123 )}
112 {name}
124 {name}
113− <p className="font-normal text-base pt-1 pb-4">
125+ <p className="font-normal text-base mt-1">{desc}</p>
114− {desc}
115− </p>
116 </div>
126 </div>
117− </Link>
118− </li>
119− </div>
120− );
121− })}
122− </ul>
123− )}
124− {active && results.length > 0 && (
125− <ul className="p-2">
126− <div>
127− <p className="font-semibold text-sm pb-4 text-gray">
128− {results.length} results for "{query}"
129− </p>
130− </div>
127+ </div>
131− {results
132− .filter((e) => e.parent !== "Glossary")
133− .map(({ title, slug, content, parent }) => {
134− return (
135− <li key={slug} className="cursor-pointer hover:bg-wall">
136− <Link href={slug} as={slug}>
137− <div>
138− <p className="font-medium text-base">
139− {parent} / {title}
140− </p>
141− <p className="text-base font-regular">{content}</p>
142− </div>
143− </Link>
128+ </Link>
144− </li>
145 );
129 );
146 })}
130 })}
131+ </div>
132+ ) : null}
133+ {active && results.length > 0 && (
134+ <ul className="">
135+ <div>
136+ <p className="font-semibold text-sm p-3 py-1 bg-ultraDeepWall text-white">
137+ {results.length} results for "{query}"
138+ </p>
139+ </div>
140+ {results
141+ .filter((e) => e.parent !== "Glossary")
142+ .map(({ title, slug, content, parent }) => {
143+ return (
144+ <li
145+ key={slug}
146+ className="cursor-pointer hover:bg-wall p-3"
147+ >
148+ <Link href={slug} as={slug}>
149+ <div>
150+ <p className="font-medium text-base">
151+ {parent} / {title}
152+ </p>
153+ <p className="text-base font-regular text-small text-gray">
154+ {content}
155+ </p>
156+ </div>
157+ </Link>
158+ </li>
159+ );
160+ })}
147− </ul>
161+ </ul>
148− )}
162+ )}
163+ </div>
149 </div>
164 </div>
150 </div>
165 </div>
151− </div>
152− );
166+ );
167+ }
168+ return null;
153}
169}
pages/_app.js+12−3
@@ -8,17 +8,26 @@ import "../styles/prism.css";
8function MyApp({ Component, pageProps }) {
8function MyApp({ Component, pageProps }) {
9 const [showSearch, toggleSearch] = useState(false);
9 const [showSearch, toggleSearch] = useState(false);
10
10
11+ const invertToggle = (event) => {
12+ if (event.preventDefault) {
13+ event.preventDefault();
14+ }
11− const invertToggle = () => toggleSearch((state) => !state);
15+ toggleSearch((state) => !state);
16+ };
12 const keyMap = { search: ["command+k", "ctrl+k", "esc"] };
17 const keyMap = { search: ["command+k", "ctrl+k", "esc"] };
13− const handlers = { search: invertToggle };
18+ const handlers = { search: (event) => invertToggle(event) };
14 configure({
19 configure({
15 ignoreTags: [],
20 ignoreTags: [],
21+ stopEventPropagationAfterHandling: true,
16 });
22 });
17
23
18 return (
24 return (
19 <>
25 <>
20 <GlobalHotKeys keyMap={keyMap} handlers={handlers} />
26 <GlobalHotKeys keyMap={keyMap} handlers={handlers} />
27+ <Search
28+ showSearch={showSearch}
21− {showSearch && <Search toggleSearch={() => toggleSearch(false)} />}
29+ toggleSearch={() => toggleSearch(false)}
30+ />
22 <Component {...pageProps} toggleSearch={invertToggle} />
31 <Component {...pageProps} toggleSearch={invertToggle} />
23 </>
32 </>
24 );
33 );
pages/grants/[slug].js+8−2
@@ -21,7 +21,13 @@ import { name, contact } from "../../lib/constants";
21import markdownStyles from "../../styles/markdown.module.css";
21import markdownStyles from "../../styles/markdown.module.css";
22import { decode } from "html-entities";
22import { decode } from "html-entities";
23
23
24−export default function Grant({ post, nextPost, markdown, previousPost }) {
24+export default function Grant({
25+ post,
26+ nextPost,
27+ markdown,
28+ previousPost,
29+ toggleSearch,
30+}) {
25 const router = useRouter();
31 const router = useRouter();
26 if (!router.isFallback && !post?.slug) {
32 if (!router.isFallback && !post?.slug) {
27 return <ErrorPage />;
33 return <ErrorPage />;
@@ -30,7 +36,7 @@ export default function Grant({ post, nextPost, markdown, previousPost }) {
30 return (
36 return (
31 <Container>
37 <Container>
32 <SingleColumn>
38 <SingleColumn>
33− <Header />
39+ <Header toggleSearch={() => toggleSearch(true)} />
34 <section className="flex flex-col layout-wide">
40 <section className="flex flex-col layout-wide">
35 <h1>{post.title}</h1>
41 <h1>{post.title}</h1>
36 {post.extra.author ? (
42 {post.extra.author ? (
tailwind.config.js+4
@@ -8,6 +8,9 @@ module.exports = {
8 gray: "rgba(0, 0, 0, 0.6)",
8 gray: "rgba(0, 0, 0, 0.6)",
9 lightGray: "rgba(0, 0, 0, 0.2)",
9 lightGray: "rgba(0, 0, 0, 0.2)",
10 wall: "rgba(244, 243, 241, 1)",
10 wall: "rgba(244, 243, 241, 1)",
11+ deepWall: "#E8E4DD",
12+ ultraDeepWall: "#32302D",
13+ washedWall: "rgba(232, 228, 221, .8)",
11 yellow: "#FCDB63",
14 yellow: "#FCDB63",
12 midYellow: "rgba(255, 199, 0, 0.6)",
15 midYellow: "rgba(255, 199, 0, 0.6)",
13 lightYellow: "rgba(255, 199, 0, 0.3)",
16 lightYellow: "rgba(255, 199, 0, 0.3)",
@@ -19,6 +22,7 @@ module.exports = {
19 blue: "#219DFF",
22 blue: "#219DFF",
20 purple: "rgba(157,82,255,0.8)",
23 purple: "rgba(157,82,255,0.8)",
21 red: "#ff4136",
24 red: "#ff4136",
25+ transparent: "rgba(0,0,0,0)",
22 },
26 },
23 fontFamily: {
27 fontFamily: {
24 sans: ["Inter", "-apple-system", "sans-serif"],
28 sans: ["Inter", "-apple-system", "sans-serif"],