1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-09-15 04:25:31 -04: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;
}
.content blockquote {
margin-left: 0;
padding-left: 1.5em;
border-left: 3px solid var(--link);
color: var(--medium-dark);
}
.content h2,
.content h3,
.content h4 {
@@ -43,6 +36,13 @@
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 {
margin: 1.5em auto;
height: 2px;
@@ -50,33 +50,6 @@
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 */
.content :global(.h-anchor) {
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 { ImageProps as NextImageProps } from "next/image";
import styles from "./Figure.module.css";
type Props = Omit<NextImageProps, "alt"> & {
children: ReactNode; // caption (can be in markdown, yay!!!)
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) => {
return (
<figure>
<figure className={styles.figure}>
<Image alt={alt || innerText(children)} {...imageProps} />
<figcaption>{children}</figcaption>
<figcaption className={styles.caption}>{children}</figcaption>
</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 type { ImageProps as NextImageProps } from "next/image";
import styles from "./Image.module.css";
const Image = ({ src, width, height, alt, quality, priority }: NextImageProps) => {
return (
<div className="image_wrapper">
<div className={styles.wrapper}>
<NextImage
src={(src as string).replace(/^\/public/g, "")}
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 styles from "./OctocatLink.module.css";
type Props = {
repo: string;
};
const OctocatLink = (props: Props) => (
<a
className="no-underline"
href={`https://github.com/${props.repo}`}
target="_blank"
rel="noopener noreferrer"
style={{ margin: "0 0.4em", color: "var(--text)" }}
>
<a className={styles.link} href={`https://github.com/${props.repo}`} target="_blank" rel="noopener noreferrer">
<OctocatOcticon fill="currentColor" />
</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
// 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 YouTube = dynamic(() => import("../components/YouTubeEmbed/YouTubeEmbed"));
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
<iframe
height="500"
width="100%"
<IFrame
src="https://codepen.io/jakejarvis/embed/pBZWZw/?theme-id=light&amp;default-tab=css,result"
scrolling="no"
></iframe>
height={500}
allowScripts
noScroll
/>
## 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.
<iframe
<IFrame
src="https://jakejarvis.github.io/dark-mode-example/"
title="Dark Mode Example"
sandbox="allow-same-origin allow-scripts allow-popups"
loading="lazy"
style={{
height: "190px",
width: "100%",
maxWidth: "650px",
display: "block",
boxSizing: "border-box",
margin: "0 auto",
border: "2px solid var(--kinda-light)",
}}
></iframe>
height={190}
width={650}
allowScripts
/>
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>
{frontMatter.noComments !== true && (
<InView rootMargin="140px" triggerOnce={true} fallbackInView={true}>
<InView rootMargin="140px" triggerOnce fallbackInView>
{({ inView, ref }) => (
<div id="comments" ref={ref}>
{inView && <Comments title={frontMatter.title} />}

View File

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

View File

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