Skip to content

Commit

Permalink
feat: open notes on the side 🎉
Browse files Browse the repository at this point in the history
  • Loading branch information
aravindballa committed May 20, 2020
1 parent 908da9f commit 4e287e1
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 73 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"@tippyjs/react": "^4.0.2",
"gatsby": "^2.20.36",
"gatsby-plugin-postcss": "^2.2.4",
"gatsby-theme-andy": "^0.0.5",
"gatsby-theme-andy": "^0.1.0",
"querystring": "^0.2.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-helmet": "^6.0.0"
Expand Down
151 changes: 115 additions & 36 deletions src/gatsby-theme-andy/components/BrainNote.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,92 @@
import React from 'react';
import { Link } from 'gatsby';
import MDXRenderer from 'gatsby-plugin-mdx/mdx-renderer';
import { Helmet } from 'react-helmet';
import Portal from '@reach/portal';
import { MDXProvider } from '@mdx-js/react';
import qs from 'querystring';

import '../../style.css';

import components from 'gatsby-theme-andy/src/components/MdxComponents';

const BrainNote = ({ note }) => {
const location = typeof window !== `undefined` ? window.location : { href: '' };

const NOTE_WIDTH = 576;

const BrainNoteContainer = ({ note }) => {
const [stackedNotes, setStackedNotes] = React.useState([]);
const [scrollPosition, setScrollPosition] = React.useState(0);
const notesContainerRef = React.useRef();

const stackedNotesSlugs = React.useMemo(() => {
if (!location.search) return [];
const res = qs.parse(location.search.replace(/^\?/, '')).stackedNotes || [];
if (typeof res === 'string') {
return [res];
}
return res;
}, [location.href]);

React.useEffect(() => {
Promise.all(
// hook into the internals of Gatsby to dynamically fetch the notes
stackedNotesSlugs.map((slug) => window.___loader.loadPage(slug))
).then((data) =>
setStackedNotes(
// filter out 404s
data.filter((x) => x.json.data.brainNote)
)
);
}, [stackedNotesSlugs]);

React.useEffect(() => {
if (notesContainerRef.current) {
notesContainerRef.current.scrollTo({
top: 0,
left: NOTE_WIDTH * (stackedNotes.length + 1),
behavior: 'smooth',
});
}
}, [stackedNotes]);

const onContainerScroll = (e) => {
setScrollPosition(e.target.scrollLeft);
};

return (
<>
<Helmet>
<meta charSet="utf-8" />
<title>{note.title} - aravindballa's notes</title>
</Helmet>
<div id="brainNote" className="text-gray-900 flex flex-col min-h-screen h-screen">
<div className="font-bold py-2 border-b px-4">
<Link to="/" className="no-underline text-gray-900">
@aravindballa's notes
</Link>
</div>
<div
ref={notesContainerRef}
className="notes-container flex flex-1 overflow-x-auto overflow-y-hidden"
onScroll={onContainerScroll}
>
<BrainNote note={note} almostHidden={scrollPosition > NOTE_WIDTH - 100} />
{stackedNotes.map((sn, i) => (
<BrainNote
key={i}
index={i + 1}
note={sn.json.data.brainNote}
stackedNote
almostHidden={scrollPosition > NOTE_WIDTH * (i + 2) - 100}
/>
))}
</div>
</div>
</>
);
};

const BrainNote = ({ note, index = 0, stackedNote, almostHidden }) => {
let references = [];
let referenceBlock;
if (note.inboundReferenceNotes != null) {
Expand Down Expand Up @@ -53,48 +131,49 @@ const BrainNote = ({ note }) => {
});
}

const AnchorTag = (props) => <components.a {...props} popups={popups} />;
const AnchorTagWithPopups = (props) => <components.a {...props} popups={popups} index={index} />;

return (
<MDXProvider components={{ a: AnchorTag }}>
<Helmet>
<meta charSet="utf-8" />
<title>{note.title} - aravindballa's notes</title>
</Helmet>
<MDXProvider components={{ a: AnchorTagWithPopups }}>
<div
id="brainNote"
className="container max-w-2xl px-4 mx-auto text-gray-900 flex flex-col min-h-screen"
className={`container max-w-xl px-4 overflow-y-auto sticky bg-white ${
stackedNote ? `shadow-lg` : ``
}`}
style={{ minWidth: NOTE_WIDTH, left: 40 * index, right: -585 }}
>
<div className="font-bold py-2 border-b -mx-4 px-4">@aravindballa's notes</div>
<div className="flex-1">
<h1 className="my-4">{note.title}</h1>
<MDXRenderer>{note.childMdx.body}</MDXRenderer>
<div
className={`transition-opacity duration-200 ${
almostHidden ? `opacity-100` : `opacity-0`
}`}
>
<div className={`transform rotate-90 origin-left pb-4 absolute`}>
<p className="m-0 font-bold">{note.title}</p>
</div>
</div>
<div className="refs-box bg-indigo-100 text-gray-600 rounded-lg mb-4 p-4">
{referenceBlock}
<p className="text-sm m-0">
If you think this note resonated, be it positive or negative, send me a{' '}
<a href="https://twitter.com/messages/compose?recipient_id=532906019">direct message</a>{' '}
on Twitter or an <a href="mailto:[email protected]">email</a> and we can talk.
</p>
<div
className={`flex flex-col min-h-full transition-opacity duration-200 ${
almostHidden ? `opacity-0` : `opacity-100`
}`}
>
<div className="flex-1">
<h1 className="my-4">{note.title}</h1>
<MDXRenderer>{note.childMdx.body}</MDXRenderer>
</div>
<div className="refs-box bg-indigo-100 text-gray-600 rounded-lg mb-4 p-4">
{referenceBlock}
<p className="text-sm m-0">
If you think this note resonated, be it positive or negative, send me a{' '}
<a href="https://twitter.com/messages/compose?recipient_id=532906019">
direct message
</a>{' '}
on Twitter or an <a href="mailto:[email protected]">email</a> and we can
talk.
</p>
</div>
</div>
</div>
{note.outboundReferenceNotes &&
note.outboundReferenceNotes
.filter((reference) => !!reference.childMdx.excerpt)
.map((ln, i) => (
<Portal key={i}>
<div
id={ln.slug}
className="fixed w-64 p-4 bg-gray-100 rounded-lg shadow-lg border border-blue-200"
>
<h5 className="mb-2">{ln.title}</h5>
<p className="text-sm m-0">{ln.childMdx.excerpt}</p>
</div>
</Portal>
))}
</MDXProvider>
);
};

export default BrainNote;
export default BrainNoteContainer;
27 changes: 23 additions & 4 deletions src/gatsby-theme-andy/components/MdxComponents.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
import React from 'react';
import { Link } from 'gatsby';
import { Link, navigate, withPrefix } from 'gatsby';
import Tippy from '@tippyjs/react';
import qs from 'querystring';

// Animation styles are imported in `src/styles.css`

const AnchorTag = ({ href, popups = {}, ...restProps }) => {
const AnchorTag = ({ href, popups = {}, index, ...restProps }) => {
if (!href.match(/^http/))
return (
<Tippy content={popups[href.replace(/^\//, '')]} placement="top" animation="shift-away">
<Link {...restProps} to={href} />
<Tippy content={popups[href.replace(/^\//, '')]} placement="right" animation="shift-away">
<Link
{...restProps}
to={href}
onClick={(ev) => {
ev.preventDefault();
const search = qs.parse(window.location.search.replace(/^\?/, ''));
let stackedNotes = search.stackedNotes || [];
if (typeof stackedNotes === 'string') {
stackedNotes = [stackedNotes];
}
stackedNotes.splice(index, stackedNotes.length - index, href);
search.stackedNotes = stackedNotes;
navigate(
`${window.location.pathname.replace(withPrefix(''), '')}?${qs.stringify(search)}`
);

// TODO: if note is already open - scrollback to it
}}
/>
</Tippy>
);
return (
Expand Down
8 changes: 6 additions & 2 deletions src/style.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/* purgecss start ignore */
@tailwind base;

body {
height: 100vh;
}

h1 {
@apply text-3xl font-bold;
}
Expand Down Expand Up @@ -100,8 +104,8 @@ pre > code {
position: absolute;
z-index: 2;
display: block;
top: 430px;
left: calc(50% - 28px);
top: 310px;
left: calc(50% - 63px);
}

/* purgecss end ignore */
38 changes: 8 additions & 30 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# yarn lockfile v1


"@aengusm/gatsby-theme-brain@^1.0.5":
"@aengusm/[email protected]":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@aengusm/gatsby-theme-brain/-/gatsby-theme-brain-1.0.5.tgz#8c46bd467845c1a7aae61e137fff92c2742862b5"
integrity sha512-lXPJMP11Utetq4mwseJVxuyJIZkwYT5gm3RWpq0aQG3PHLVL9C9ebIQ40LwIGXvsyk2/CXA56/mTdmUhQOcUaw==
Expand Down Expand Up @@ -1048,14 +1048,6 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.4.0.tgz#0e1bdf8d021e7ea58affade33d9d607e11365915"
integrity sha512-NMrDy6EWh9TPdSRiHmHH2ye1v5U0gBD7pRYwSwJvomx7Bm4GG04vu63dYiVzebLOx2obPpJugew06xVP0Nk7hA==

"@reach/portal@^0.10.0":
version "0.10.1"
resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.10.1.tgz#07329846ef45bb1af362d4470dd137087b39da68"
integrity sha512-axap4IxA0xgsxluqyeyVuGZrStqaZ81iyiHmXFn+D+bjDNdd29colHm5GEB5mjGnkqktcXWyx5DQ+aRHIyGEkQ==
dependencies:
"@reach/utils" "^0.10.1"
tslib "^1.11.1"

"@reach/router@^1.3.3":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.3.3.tgz#58162860dce6c9449d49be86b0561b5ef46d80db"
Expand All @@ -1066,15 +1058,6 @@
prop-types "^15.6.1"
react-lifecycles-compat "^3.0.4"

"@reach/utils@^0.10.1":
version "0.10.1"
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.10.1.tgz#ee0283f81e161db4126a943b5c908a69f6a66d7e"
integrity sha512-YzwZWVK+rSiUATNVtK7H2/ZkT/GhNKmkRjnj3hnVhSYLGxY9uQdfc+npetOqkh4hTAOXiErDa64ybVClR3h0TA==
dependencies:
"@types/warning" "^3.0.0"
tslib "^1.11.1"
warning "^4.0.3"

"@sindresorhus/is@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
Expand Down Expand Up @@ -1277,11 +1260,6 @@
"@types/unist" "*"
"@types/vfile-message" "*"

"@types/warning@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52"
integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI=

"@types/yargs-parser@*":
version "15.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
Expand Down Expand Up @@ -5164,13 +5142,13 @@ gatsby-telemetry@^1.2.6:
stack-utils "1.0.2"
uuid "3.4.0"

gatsby-theme-andy@^0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/gatsby-theme-andy/-/gatsby-theme-andy-0.0.5.tgz#2aa81a0a5df67909687aab6c574802e1eaeb0808"
integrity sha512-vAJkqp5RUaGZJyDZETyNBumgY7iq6PIpXX5Vw1tBTVvpzO8s2Fjs1MgHoYTUBUQnrnCpS5pAlBQvSGd4mNLuVA==
gatsby-theme-andy@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/gatsby-theme-andy/-/gatsby-theme-andy-0.1.0.tgz#5ed4afb914670cb3d9cae836ea1bf33d7eeafa8a"
integrity sha512-4VZ/iW23l/PLp7h9iDi3vZgnyj9r2erUUoFGGYeQQAoRz+/UMA/AAtzHVABVl++0vcqPQ8TXlkDQ0/ntr46CHQ==
dependencies:
"@aengusm/gatsby-theme-brain" "^1.0.5"
"@reach/portal" "^0.10.0"
"@aengusm/gatsby-theme-brain" "1.0.5"
"@tippyjs/react" "^4.0.2"

gatsby-transformer-remark@^2.7.2:
version "2.7.5"
Expand Down Expand Up @@ -11560,7 +11538,7 @@ ts-pnp@^1.1.6:
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==

tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0:
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
version "1.11.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
Expand Down

0 comments on commit 4e287e1

Please sign in to comment.