1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-11-02 16:14:03 -05:00

<IFrame /> component

This commit is contained in:
2022-01-18 13:54:12 -05:00
parent eb172b83b0
commit caac9b905a
15 changed files with 141 additions and 78 deletions

View File

@@ -3,13 +3,6 @@
line-height: 1.7; line-height: 1.7;
} }
.content blockquote {
margin-left: 0;
padding-left: 1.5em;
border-left: 3px solid var(--link);
color: var(--medium-dark);
}
.content h2, .content h2,
.content h3, .content h3,
.content h4 { .content h4 {
@@ -43,6 +36,13 @@
padding-left: 0.25em; padding-left: 0.25em;
} }
.content blockquote {
margin-left: 0;
padding-left: 1.5em;
border-left: 3px solid var(--link);
color: var(--medium-dark);
}
.content hr { .content hr {
margin: 1.5em auto; margin: 1.5em auto;
height: 2px; height: 2px;
@@ -50,33 +50,6 @@
background-color: var(--light); background-color: var(--light);
} }
.content :global(.image_wrapper) {
line-height: 0;
}
/* default to centering all images */
.content :global(.image_wrapper),
.content figure {
margin: 1em auto;
text-align: center;
}
.content figure :global(.image_wrapper) {
margin-bottom: 0;
}
.content figure figcaption {
margin-top: 0.75em;
font-size: 0.9em;
line-height: 1.5;
color: var(--medium);
}
/* some figcaptions contain paragraphs, some don't, so reset all of them */
.content figure figcaption p {
margin: 0;
}
/* sub-heading anchor styles */ /* sub-heading anchor styles */
.content :global(.h-anchor) { .content :global(.h-anchor) {
margin: 0 0.25em; margin: 0 0.25em;

View File

@@ -0,0 +1,15 @@
.figure {
margin: 1em auto;
text-align: center;
}
.caption {
font-size: 0.9em;
line-height: 1.5;
color: var(--medium);
}
/* some figcaptions contain paragraphs, some don't, so reset all of them */
.caption p {
margin: 0;
}

View File

@@ -3,6 +3,8 @@ import innerText from "react-innertext";
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import type { ImageProps as NextImageProps } from "next/image"; import type { ImageProps as NextImageProps } from "next/image";
import styles from "./Figure.module.css";
type Props = Omit<NextImageProps, "alt"> & { type Props = Omit<NextImageProps, "alt"> & {
children: ReactNode; // caption (can be in markdown, yay!!!) children: ReactNode; // caption (can be in markdown, yay!!!)
alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing
@@ -10,9 +12,9 @@ type Props = Omit<NextImageProps, "alt"> & {
const Figure = ({ children, alt, ...imageProps }: Props) => { const Figure = ({ children, alt, ...imageProps }: Props) => {
return ( return (
<figure> <figure className={styles.figure}>
<Image alt={alt || innerText(children)} {...imageProps} /> <Image alt={alt || innerText(children)} {...imageProps} />
<figcaption>{children}</figcaption> <figcaption className={styles.caption}>{children}</figcaption>
</figure> </figure>
); );
}; };

View File

@@ -0,0 +1,6 @@
.frame {
width: 100%;
display: block;
margin: 1em auto;
border: 2px solid var(--kinda-light);
}

View File

@@ -0,0 +1,28 @@
import styles from "./IFrame.module.css";
type Props = {
src: string;
title?: string;
height: number;
width?: number; // defaults to 100%
allowScripts?: boolean;
noScroll?: boolean;
};
const IFrame = ({ src, title, height, width, allowScripts, noScroll, ...rest }: Props) => (
<iframe
className={styles.frame}
src={src}
title={title}
sandbox={allowScripts ? "allow-same-origin allow-scripts allow-popups" : undefined}
scrolling={noScroll ? "no" : undefined}
loading="lazy"
style={{
height: `${height}px`,
maxWidth: width ? `${width}px` : undefined,
}}
{...rest}
/>
);
export default IFrame;

View File

@@ -0,0 +1,7 @@
.wrapper {
line-height: 0;
/* default to centering all images */
margin: 1em auto;
text-align: center;
}

View File

@@ -1,9 +1,11 @@
import NextImage from "next/image"; import NextImage from "next/image";
import type { ImageProps as NextImageProps } from "next/image"; import type { ImageProps as NextImageProps } from "next/image";
import styles from "./Image.module.css";
const Image = ({ src, width, height, alt, quality, priority }: NextImageProps) => { const Image = ({ src, width, height, alt, quality, priority }: NextImageProps) => {
return ( return (
<div className="image_wrapper"> <div className={styles.wrapper}>
<NextImage <NextImage
src={(src as string).replace(/^\/public/g, "")} src={(src as string).replace(/^\/public/g, "")}
layout="intrinsic" layout="intrinsic"

View File

@@ -0,0 +1,11 @@
.link {
margin: 0 0.4em;
color: var(--text);
background: none !important;
padding-bottom: 0;
transition: none;
}
.link:hover {
color: var(--link);
}

View File

@@ -1,17 +1,13 @@
import { OctocatOcticon } from "../Icons"; import { OctocatOcticon } from "../Icons";
import styles from "./OctocatLink.module.css";
type Props = { type Props = {
repo: string; repo: string;
}; };
const OctocatLink = (props: Props) => ( const OctocatLink = (props: Props) => (
<a <a className={styles.link} href={`https://github.com/${props.repo}`} target="_blank" rel="noopener noreferrer">
className="no-underline"
href={`https://github.com/${props.repo}`}
target="_blank"
rel="noopener noreferrer"
style={{ margin: "0 0.4em", color: "var(--text)" }}
>
<OctocatOcticon fill="currentColor" /> <OctocatOcticon fill="currentColor" />
</a> </a>
); );

View File

@@ -8,6 +8,7 @@ export { default as code } from "../components/CodeBlock/CodeBlock";
// All of these components are technically passed into all posts, but next/dynamic ensures they're loaded only // All of these components are technically passed into all posts, but next/dynamic ensures they're loaded only
// when they're referenced in the individual mdx files. // when they're referenced in the individual mdx files.
export const IFrame = dynamic(() => import("../components/IFrame/IFrame"));
export const Video = dynamic(() => import("../components/Video/Video")); export const Video = dynamic(() => import("../components/Video/Video"));
export const YouTube = dynamic(() => import("../components/YouTubeEmbed/YouTubeEmbed")); export const YouTube = dynamic(() => import("../components/YouTubeEmbed/YouTubeEmbed"));
export const Tweet = dynamic(() => import("../components/TweetEmbed/TweetEmbed")); export const Tweet = dynamic(() => import("../components/TweetEmbed/TweetEmbed"));

View File

@@ -19,12 +19,12 @@ Below are the code snippets you can grab and customize to make your own ["waving
## Demo ## Demo
<iframe <IFrame
height="500"
width="100%"
src="https://codepen.io/jakejarvis/embed/pBZWZw/?theme-id=light&amp;default-tab=css,result" src="https://codepen.io/jakejarvis/embed/pBZWZw/?theme-id=light&amp;default-tab=css,result"
scrolling="no" height={500}
></iframe> allowScripts
noScroll
/>
## CSS ## CSS

View File

@@ -29,21 +29,14 @@ I've written a simple implementation below, which...
...meaning that any CSS selectors beginning with `body.dark` or `body.light` will only apply when the respective mode is active. A good place to start is by separating any color rules — your background, text, links, etc. — into a different section of your CSS. Using [SASS or SCSS](https://sass-lang.com/) makes this a whole lot [easier with nesting](https://sass-lang.com/guide#topic-3) but is not required; this was written with a [KISS](https://getyarn.io/yarn-clip/embed/eed08f4f-d1c9-4cc0-b041-f280a5dbf0a5?autoplay=false) mentality. ...meaning that any CSS selectors beginning with `body.dark` or `body.light` will only apply when the respective mode is active. A good place to start is by separating any color rules — your background, text, links, etc. — into a different section of your CSS. Using [SASS or SCSS](https://sass-lang.com/) makes this a whole lot [easier with nesting](https://sass-lang.com/guide#topic-3) but is not required; this was written with a [KISS](https://getyarn.io/yarn-clip/embed/eed08f4f-d1c9-4cc0-b041-f280a5dbf0a5?autoplay=false) mentality.
<iframe <IFrame
src="https://jakejarvis.github.io/dark-mode-example/" src="https://jakejarvis.github.io/dark-mode-example/"
title="Dark Mode Example" title="Dark Mode Example"
sandbox="allow-same-origin allow-scripts allow-popups"
loading="lazy" loading="lazy"
style={{ height={190}
height: "190px", width={650}
width: "100%", allowScripts
maxWidth: "650px", />
display: "block",
boxSizing: "border-box",
margin: "0 auto",
border: "2px solid var(--kinda-light)",
}}
></iframe>
A _very_ barebones example is embedded above ([view the source here](https://github.com/jakejarvis/dark-mode-example), or [open in a new window](https://jakejarvis.github.io/dark-mode-example/) if your browser is blocking the frame) and you can try it out on this site by clicking the 💡 lightbulb in the upper right corner of this page. You'll notice that the dark theme sticks when refreshing this page, navigating between other pages, or if you were to return to this example weeks from now. A _very_ barebones example is embedded above ([view the source here](https://github.com/jakejarvis/dark-mode-example), or [open in a new window](https://jakejarvis.github.io/dark-mode-example/) if your browser is blocking the frame) and you can try it out on this site by clicking the 💡 lightbulb in the upper right corner of this page. You'll notice that the dark theme sticks when refreshing this page, navigating between other pages, or if you were to return to this example weeks from now.

View File

@@ -60,7 +60,7 @@ const Note = ({ frontMatter, source }: NoteType) => {
</Content> </Content>
{frontMatter.noComments !== true && ( {frontMatter.noComments !== true && (
<InView rootMargin="140px" triggerOnce={true} fallbackInView={true}> <InView rootMargin="140px" triggerOnce fallbackInView>
{({ inView, ref }) => ( {({ inView, ref }) => (
<div id="comments" ref={ref}> <div id="comments" ref={ref}>
{inView && <Comments title={frontMatter.title} />} {inView && <Comments title={frontMatter.title} />}

View File

@@ -2,6 +2,7 @@ import Image from "next/image";
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import IFrame from "../components/IFrame/IFrame";
import { FloppyIcon, SirenIcon } from "../components/Icons"; import { FloppyIcon, SirenIcon } from "../components/Icons";
/* eslint-disable camelcase */ /* eslint-disable camelcase */
@@ -75,12 +76,14 @@ const Previously = () => (
experience anyway. experience anyway.
</a> </a>
</p> </p>
<figure> <figure>
<iframe <IFrame
className="y2k_frame"
src="https://jakejarvis.github.io/my-first-website/" src="https://jakejarvis.github.io/my-first-website/"
title="My Terrible, Horrible, No Good, Very Bad First Website" title="My Terrible, Horrible, No Good, Very Bad First Website"
></iframe> height={500}
allowScripts
/>
<figcaption> <figcaption>
November 2001 ( November 2001 (
<a href="https://github.com/jakejarvis/my-first-website" target="_blank" rel="noopener noreferrer"> <a href="https://github.com/jakejarvis/my-first-website" target="_blank" rel="noopener noreferrer">
@@ -236,10 +239,24 @@ const Previously = () => (
footer > div { footer > div {
font-size: 0.95em !important; font-size: 0.95em !important;
} }
.y2k_frame { figure {
width: 100%; margin: 1em auto;
height: 500px; text-align: center;
border: 2px solid #e3d18c; }
figure img {
margin-bottom: 0;
}
figcaption {
margin-top: 0.2em;
font-size: 0.9em;
line-height: 1.5;
color: var(--medium);
}
hr {
margin: 1em auto !important;
}
iframe {
margin-bottom: 0.6em !important;
} }
.limegreen { .limegreen {
color: #32cd32; color: #32cd32;

View File

@@ -3,6 +3,7 @@ import Link from "next/link";
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import IFrame from "../components/IFrame/IFrame";
import { PrivacyIcon } from "../components/Icons"; import { PrivacyIcon } from "../components/Icons";
import faunaImg from "../public/static/images/privacy/fauna_hits.png"; import faunaImg from "../public/static/images/privacy/fauna_hits.png";
@@ -24,6 +25,7 @@ const Privacy = () => (
<p>Okay, this is an easy one. 😉</p> <p>Okay, this is an easy one. 😉</p>
<h2 id="hosting">Hosting</h2> <h2 id="hosting">Hosting</h2>
<p> <p>
Pages and first-party assets on this website are served by{" "} Pages and first-party assets on this website are served by{" "}
<a href="https://vercel.com/" target="_blank" rel="noopener noreferrer"> <a href="https://vercel.com/" target="_blank" rel="noopener noreferrer">
@@ -35,6 +37,7 @@ const Privacy = () => (
</a>{" "} </a>{" "}
for more information. for more information.
</p> </p>
<p> <p>
For a likely excessive level of privacy and security, this website is also mirrored on the{" "} For a likely excessive level of privacy and security, this website is also mirrored on the{" "}
<a href="https://www.torproject.org/" target="_blank" rel="noopener noreferrer"> <a href="https://www.torproject.org/" target="_blank" rel="noopener noreferrer">
@@ -42,6 +45,7 @@ const Privacy = () => (
</a>{" "} </a>{" "}
at: at:
</p> </p>
<blockquote> <blockquote>
<p> <p>
<a <a
@@ -55,6 +59,7 @@ const Privacy = () => (
</blockquote> </blockquote>
<h2 id="analytics">Analytics</h2> <h2 id="analytics">Analytics</h2>
<p> <p>
A very simple hit counter on each blog post tallies an aggregate number of pageviews (i.e.{" "} A very simple hit counter on each blog post tallies an aggregate number of pageviews (i.e.{" "}
<code>hits = hits + 1</code>) in a{" "} <code>hits = hits + 1</code>) in a{" "}
@@ -64,6 +69,7 @@ const Privacy = () => (
database. Individual views and identifying (or non-identifying) details are{" "} database. Individual views and identifying (or non-identifying) details are{" "}
<strong>never stored or logged</strong>. <strong>never stored or logged</strong>.
</p> </p>
<p> <p>
The{" "} The{" "}
<a <a
@@ -87,7 +93,9 @@ const Privacy = () => (
</a>{" "} </a>{" "}
are public. are public.
</p> </p>
<Image src={faunaImg} placeholder="blur" alt="The entire database schema." /> <Image src={faunaImg} placeholder="blur" alt="The entire database schema." />
<p> <p>
<a href="https://usefathom.com/ref/ZEYG0O" target="_blank" rel="noopener noreferrer"> <a href="https://usefathom.com/ref/ZEYG0O" target="_blank" rel="noopener noreferrer">
<strong>Fathom Analytics</strong> <strong>Fathom Analytics</strong>
@@ -103,15 +111,14 @@ const Privacy = () => (
</a>{" "} </a>{" "}
is completely public, too!) is completely public, too!)
</p> </p>
<iframe src="https://app.usefathom.com/share/wbgnqukw/jarv.is" title="Fathom Analytics dashboard">
<style jsx>{` <IFrame
iframe { src="https://app.usefathom.com/share/wbgnqukw/jarv.is"
width: 100%; title="Fathom Analytics dashboard"
height: 500px; height={500}
border: 2px solid var(--kinda-light); allowScripts
} />
`}</style>
</iframe>
<p> <p>
<a href="https://vercel.com/analytics" target="_blank" rel="noopener noreferrer"> <a href="https://vercel.com/analytics" target="_blank" rel="noopener noreferrer">
<strong>Vercel Analytics</strong> <strong>Vercel Analytics</strong>
@@ -124,10 +131,12 @@ const Privacy = () => (
</p> </p>
<h2 id="third-party">Third-Party Content</h2> <h2 id="third-party">Third-Party Content</h2>
<p> <p>
Occasionally, embedded content from third-party services is included in posts, and some may contain tracking Occasionally, embedded content from third-party services is included in posts, and some may contain tracking
code that is outside of my control. Please refer to their privacy policies for more information: code that is outside of my control. Please refer to their privacy policies for more information:
</p> </p>
<ul> <ul>
<li> <li>
<a href="https://blog.codepen.io/documentation/privacy/" target="_blank" rel="noopener noreferrer"> <a href="https://blog.codepen.io/documentation/privacy/" target="_blank" rel="noopener noreferrer">
@@ -171,6 +180,7 @@ const Privacy = () => (
</ul> </ul>
<h2 id="hcaptcha">Fighting Spam</h2> <h2 id="hcaptcha">Fighting Spam</h2>
<p> <p>
Using{" "} Using{" "}
<a href="https://www.hcaptcha.com/" target="_blank" rel="noopener noreferrer"> <a href="https://www.hcaptcha.com/" target="_blank" rel="noopener noreferrer">
@@ -186,6 +196,7 @@ const Privacy = () => (
</a> </a>
. .
</p> </p>
<p> <p>
You can refer to hCaptcha's{" "} You can refer to hCaptcha's{" "}
<a href="https://www.hcaptcha.com/privacy" target="_blank" rel="noopener noreferrer"> <a href="https://www.hcaptcha.com/privacy" target="_blank" rel="noopener noreferrer">
@@ -206,6 +217,7 @@ const Privacy = () => (
</a> </a>
. 🚗 . 🚗
</p> </p>
<p> <p>
I also enabled the setting to donate 100% of my{" "} I also enabled the setting to donate 100% of my{" "}
<a href="https://humanprotocol.org/?lng=en-US" target="_blank" rel="noopener noreferrer"> <a href="https://humanprotocol.org/?lng=en-US" target="_blank" rel="noopener noreferrer">