Skip to content

Commit

Permalink
Merge pull request #6 from shaun-jacks/feat/global-search
Browse files Browse the repository at this point in the history
[BLOG-42] feat/global search
  • Loading branch information
shaun-jacks authored May 31, 2020
2 parents c216364 + 190452f commit 5328668
Show file tree
Hide file tree
Showing 17 changed files with 979 additions and 100 deletions.
13 changes: 13 additions & 0 deletions gatsby-config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
const urljoin = require("url-join");
const config = require("./data/SiteConfig");
const queries = require("./src/utils/algolia");
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
});

module.exports = {
pathPrefix: config.pathPrefix === "" ? "/" : config.pathPrefix,
Expand All @@ -24,6 +28,15 @@ module.exports = {
"gatsby-plugin-sharp",
"gatsby-transformer-sharp",
"gatsby-plugin-typescript",
{
resolve: `gatsby-plugin-algolia`,
options: {
appId: process.env.GATSBY_ALGOLIA_APP_ID,
apiKey: process.env.ALGOLIA_ADMIN_KEY,
queries,
chunkSize: 10000, // default: 1000
},
},
{
resolve: `gatsby-plugin-mdx`,
options: {
Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ declare module "*.json" {
const value: any;
export default value;
}
declare module "react-instantsearch-dom";
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
"@mdx-js/react": "^1.5.1",
"@theme-ui/color": "^0.3.1",
"@theme-ui/prism": "^0.2.46",
"algoliasearch": "^4.2.0",
"disqus-react": "^1.0.8",
"gatsby": "^2.17.10",
"gatsby-image": "^2.3.4",
"gatsby-plugin-algolia": "^0.11.0",
"gatsby-plugin-catch-links": "^2.1.12",
"gatsby-plugin-feed": "^2.3.15",
"gatsby-plugin-google-analytics": "^2.1.19",
Expand Down Expand Up @@ -46,6 +48,7 @@
"react-dom": "^16.11.0",
"react-helmet": "^5.2.1",
"react-icons": "^3.10.0",
"react-instantsearch-dom": "^6.5.0",
"react-share": "^3.0.1",
"react-twitter-widgets": "^1.7.1",
"theme-ui": "^0.2.44",
Expand All @@ -55,15 +58,16 @@
"devDependencies": {
"@types/prismjs": "^1.16.1",
"@types/react": "^16.9.35",
"@types/react-dom": "^16.9.8",
"@types/react-helmet": "^6.0.0",
"@types/react-instantsearch-dom": "^6.3.0",
"@types/react-share": "^3.0.3",
"@types/theme-ui": "^0.3.2",
"@types/theme-ui__color": "^0.3.2",
"@types/url-join": "^4.0.0",
"@types/vfile-message": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^3.0.2",
"@typescript-eslint/parser": "^3.0.2",
"@types/react-dom": "^16.9.8",
"cli-glob": "^0.1.0",
"eslint": "^7.1.0",
"eslint-config-airbnb": "^18.0.1",
Expand Down
19 changes: 17 additions & 2 deletions src/components/Nav/MobileNavMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { Link } from "gatsby";
import HamburgerIcon from "./HamburgerIcon";
import ToggleMode from "./ToggleMode";
import TopDrawer from "./TopDrawer";
import { IconContext } from "react-icons";
import { MdSearch } from "react-icons/md";
import Search from "../Search/Search";

/** @jsx jsx */
import { Styled, jsx } from "theme-ui";
Expand Down Expand Up @@ -30,7 +33,8 @@ export default function MobileNavMenu({
alignItems: `center`,
maxWidth: `container`,
height: "100%",
m: "auto",
my: "auto",
mr: 3,
}}
>
<TopDrawer
Expand All @@ -55,7 +59,18 @@ export default function MobileNavMenu({
>
<div sx={{ flex: "1" }}>{siteTitle}</div>
</Link>
<div sx={{ flex: "1", display: "flex", justifyContent: "flex-end" }} />
<div
sx={{
flex: "1",
display: "flex",
justifyContent: "flex-end",
"&:hover": {
cursor: "pointer",
},
}}
>
<Search />
</div>
</div>
);
}
6 changes: 2 additions & 4 deletions src/components/Nav/ToggleMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export default function ToggleMode() {
role="presentation"
style={{
pointerEvents: `none`,
margin: 4,
}}
/>
);
Expand All @@ -35,7 +34,6 @@ export default function ToggleMode() {
role="presentation"
style={{
pointerEvents: `none`,
margin: 4,
}}
/>
);
Expand All @@ -48,8 +46,8 @@ export default function ToggleMode() {
cursor: `pointer`,
border: `none`,
outline: `none`,
pr: "1rem",
py: 0,
p: 0,
mx: 3,
}}
title="Toggle Dark Mode"
>
Expand Down
26 changes: 10 additions & 16 deletions src/components/Nav/TopDrawerOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,22 @@ import React from "react";
import { Styled, jsx } from "theme-ui";

interface TopDrawerOverlayProps {
isOpen: boolean;
toggleOpen: () => void;
}

export default function TopDrawerOverlay({
isOpen,
toggleOpen,
}: TopDrawerOverlayProps) {
return (
<div>
{isOpen && (
<div
onClick={toggleOpen}
sx={{
width: "100%",
height: "100%",
color: "rgba(0, 0, 0, .25)",
backgroundColor: "rgba(0, 0, 0, .5)",
zIndex: 10,
}}
/>
)}
</div>
<div
onClick={toggleOpen}
sx={{
width: "100%",
height: "100%",
color: "rgba(0, 0, 0, .25)",
backgroundColor: "rgba(0, 0, 0, .5)",
zIndex: 10,
}}
></div>
);
}
8 changes: 1 addition & 7 deletions src/components/Nav/TopDrawerPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@ import { Styled, jsx } from "theme-ui";
import ToggleMode from "./ToggleMode";

interface TopDrawerPanelProps {
isOpen: boolean;
menuLinks: { url: string; name: string }[];
}

export default function TopDrawerPanel({
isOpen,
menuLinks,
}: TopDrawerPanelProps) {
export default function TopDrawerPanel({ menuLinks }: TopDrawerPanelProps) {
return (
<div
sx={{
Expand All @@ -23,8 +19,6 @@ export default function TopDrawerPanel({
backgroundColor: "panelBackground",
color: "background",
zIndex: 1000,
transformOrigin: "top",
transform: isOpen ? "scaleY(1)" : "scaleY(0)",
}}
>
<div
Expand Down
22 changes: 20 additions & 2 deletions src/components/Nav/WideNavMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import React from "react";
import ToggleMode from "./ToggleMode";
import { Link } from "gatsby";
import NavItem from "./NavItem";
import { IconContext } from "react-icons";
import { MdSearch } from "react-icons/md";
import Search from "../Search/Search";

/** @jsx jsx */
import { Styled, jsx } from "theme-ui";
Expand Down Expand Up @@ -38,13 +41,28 @@ export default function WideNavMenu({
},
}}
>
<div sx={{ pl: "1rem" }}>{siteTitle}</div>
<div sx={{ ml: 3, pl: 3 }}>{siteTitle}</div>
</Link>
<div style={{ display: `flex`, alignItems: `center` }}>
<div style={{ display: `flex`, alignItems: `center`, maxHeight: "100%" }}>
{menuLinks.map((link, i) => {
return <NavItem key={i} link={link} />;
})}
<ToggleMode />
<div
sx={{
width: "100%",
my: "auto",
mr: 3,
ml: "1rem",
pt: ".1rem",
pr: 3,
"&:hover": {
cursor: "pointer",
},
}}
>
<Search />
</div>
</div>
</nav>
);
Expand Down
20 changes: 20 additions & 0 deletions src/components/Search/CustomStateResults.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";
import { connectStateResults } from "react-instantsearch-dom";

/** @jsx jsx */
import { Styled, jsx } from "theme-ui";

const StateResults = ({ searchResults }: { searchResults: any }) => {
const hasResults = searchResults && searchResults.nbHits !== 0;
const nbHits = searchResults && searchResults.nbHits;

return (
<div>
<div hidden={!hasResults}>
{nbHits} result{nbHits === 1 ? "" : "s"}
</div>
<div hidden={hasResults}>No results</div>
</div>
);
};
export default connectStateResults(StateResults);
36 changes: 36 additions & 0 deletions src/components/Search/InputSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from "react";
import { connectSearchBox } from "react-instantsearch-dom";
import { IconContext } from "react-icons";
import { FaSearch } from "react-icons/fa";
import { InputStyles } from "./styles";

/** @jsx jsx */
import { Styled, jsx } from "theme-ui";

interface InputSearchProps {
refine: any;
focus: boolean;
setFocus: (value?: boolean) => void;
}

export default connectSearchBox(
({ refine, focus, setFocus }: InputSearchProps) => (
<Styled sx={InputStyles(focus)}>
{focus ? (
<form>
<input
type="text"
placeholder="Search"
aria-label="Search"
onChange={(e) => refine(e.target.value)}
autoFocus
/>
</form>
) : (
<IconContext.Provider value={{ size: "1.25rem" }}>
<FaSearch onClick={() => setFocus(true)} />
</IconContext.Provider>
)}
</Styled>
)
);
43 changes: 43 additions & 0 deletions src/components/Search/PostHit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react";
import { Link } from "gatsby";
import { Highlight, Snippet } from "react-instantsearch-dom";
import { PostHitHeader } from "./styles";

/** @jsx jsx */
import { Styled, jsx } from "theme-ui";

interface PostHitProps {
hit: any;
}

export default function PostHit({ hit }: PostHitProps) {
return (
<Styled key={hit.slug}>
<Link to={hit.slug}>
<Styled.h1 sx={PostHitHeader}>
<Highlight attribute="title" hit={hit} tagName="mark" />
</Styled.h1>
</Link>
<div style={{ display: "flex", flexDirection: "column" }}>
<section>
<Styled.p sx={{ m: 0, fontSize: "14px" }}>
<Highlight attribute="date" hit={hit} tagName="mark" />
</Styled.p>
</section>
<section>
<Styled.p sx={{ m: 0, fontSize: "12px" }}>
{hit.tags.map((tag: string, index: number) => (
<React.Fragment key={tag}>
{index > 0 && `, `}
{tag}
</React.Fragment>
))}
</Styled.p>
</section>
</div>
<Styled.p sx={{ fontSize: "12px", mt: 1 }}>
<Snippet attribute="excerpt" hit={hit} tagName="mark" />
</Styled.p>
</Styled>
);
}
Loading

0 comments on commit 5328668

Please sign in to comment.