mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-09-14 01:55:31 -04:00
clean up global styles
This commit is contained in:
@@ -16,31 +16,43 @@
|
|||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
|
||||||
|
/* offset (approximately) with sticky header so jumped-to content isn't hiding behind it */
|
||||||
|
scroll-margin-top: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* special bottom border for H2s */
|
/* special bottom border for <h2>s */
|
||||||
.content h2 {
|
.content h2 {
|
||||||
padding-bottom: 0.25em;
|
padding-bottom: 0.25em;
|
||||||
border-bottom: 1px solid var(--kinda-light);
|
border-bottom: 1px solid var(--kinda-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content figure {
|
.content h3,
|
||||||
|
.content h4 {
|
||||||
|
scroll-margin-top: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default to centering all images */
|
||||||
|
.content figure,
|
||||||
|
.content :global(.image_wrapper) {
|
||||||
margin: 1em auto;
|
margin: 1em auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content figure img {
|
.content figure :global(.image_wrapper) {
|
||||||
height: auto;
|
margin-bottom: 0;
|
||||||
max-width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content figure figcaption {
|
.content figure figcaption {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-top: 0.3em;
|
|
||||||
color: var(--medium);
|
color: var(--medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content figure figcaption p {
|
||||||
|
margin-top: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
.content ul,
|
.content ul,
|
||||||
.content ol {
|
.content ol {
|
||||||
margin-left: 1.5em;
|
margin-left: 1.5em;
|
||||||
@@ -58,9 +70,42 @@
|
|||||||
background-color: var(--light);
|
background-color: var(--light);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sub-heading anchor styles */
|
||||||
|
.content :global(.h-anchor) {
|
||||||
|
margin: 0 0.25em;
|
||||||
|
padding: 0 0.25em;
|
||||||
|
color: var(--medium-light);
|
||||||
|
background: none;
|
||||||
|
font-weight: 300;
|
||||||
|
opacity: 0; /* overridden on hover */
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.content :global(.h-anchor::before) {
|
||||||
|
content: "\0023"; /* pound sign `#`, done here to keep content DOM cleaner */
|
||||||
|
}
|
||||||
|
.content :global(.h-anchor:hover) {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make anchor `#` link show up on hover over the corresponding heading */
|
||||||
|
.content h2:hover :global(.h-anchor),
|
||||||
|
.content h3:hover :global(.h-anchor),
|
||||||
|
.content h4:hover :global(.h-anchor) {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
.content {
|
.content {
|
||||||
font-size: 0.925em;
|
font-size: 0.925em;
|
||||||
line-height: 1.85;
|
line-height: 1.85;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content h2 {
|
||||||
|
scroll-margin-top: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h3,
|
||||||
|
.content h4 {
|
||||||
|
scroll-margin-top: 6em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,28 +1,35 @@
|
|||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
type Props = {
|
type CustomCodeProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomCode = (props: Props) => {
|
const CustomCode = (props: CustomCodeProps) => {
|
||||||
if (props.className?.split(" ").includes("hljs")) {
|
if (props.className?.split(" ").includes("hljs")) {
|
||||||
const CopyButton = dynamic(() => import("../clipboard/CopyButton"));
|
const CopyButton = dynamic(() => import("../clipboard/CopyButton"));
|
||||||
|
|
||||||
// full multi-line code blocks with highlight.js and copy-to-clipboard button
|
// full multi-line code blocks with highlight.js and copy-to-clipboard button
|
||||||
return (
|
return (
|
||||||
<div className="code_block">
|
<div>
|
||||||
<CopyButton source={props.children} />
|
<CopyButton source={props.children} />
|
||||||
<code {...props}>{props.children}</code>
|
<code {...props}>{props.children}</code>
|
||||||
|
|
||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
.code_block {
|
div {
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div > code {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 1em;
|
||||||
|
tab-size: 2;
|
||||||
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
|
|
||||||
<style jsx global>{`
|
<style jsx global>{`
|
||||||
|
@@ -1,14 +1,17 @@
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
||||||
import type { ImageProps } from "next/image";
|
import type { ImageProps } from "next/image";
|
||||||
|
import type { CSSProperties } from "react";
|
||||||
|
|
||||||
// TODO: infer ratio when given zero/one dimensions
|
// TODO: infer ratio when given zero/one dimensions
|
||||||
// TODO: fold figure/figcaption tags into this component
|
// TODO: fold figure/figcaption tags into this component
|
||||||
|
|
||||||
const CustomImg = (props: ImageProps) => {
|
type CustomImageProps = ImageProps & {
|
||||||
|
style?: CSSProperties;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomImage = (props: CustomImageProps) => {
|
||||||
return (
|
return (
|
||||||
// the required height and width are part of the props, so they get automatically passed here with {...props}
|
<div className="image_wrapper" style={props.style}>
|
||||||
<div style={{ margin: "1em auto", textAlign: "center" }}>
|
|
||||||
<Image
|
<Image
|
||||||
src={props.src}
|
src={props.src}
|
||||||
layout="intrinsic"
|
layout="intrinsic"
|
||||||
@@ -23,4 +26,4 @@ const CustomImg = (props: ImageProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CustomImg;
|
export default CustomImage;
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
import type { LinkProps } from "next/link";
|
import type { LinkProps } from "next/link";
|
||||||
|
|
||||||
type CustomLinkProps = LinkProps & {
|
type CustomLinkProps = LinkProps & {
|
||||||
@@ -7,10 +6,12 @@ type CustomLinkProps = LinkProps & {
|
|||||||
rel?: string;
|
rel?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: unknown;
|
children?: unknown;
|
||||||
|
rest?: unknown;
|
||||||
};
|
};
|
||||||
const CustomLink = ({ href, target, rel, className, children }: CustomLinkProps) => (
|
|
||||||
|
const CustomLink = ({ href, target, rel, className, children, ...rest }: CustomLinkProps) => (
|
||||||
<Link href={href} passHref={true}>
|
<Link href={href} passHref={true}>
|
||||||
<a className={className} target={target} rel={rel}>
|
<a className={className} target={target} rel={rel} {...rest}>
|
||||||
{children}
|
{children}
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import ReactPlayer, { ReactPlayerProps } from "react-player/lazy";
|
import ReactPlayer from "react-player/lazy";
|
||||||
|
import type { ReactPlayerProps } from "react-player";
|
||||||
|
|
||||||
const Video = (props: ReactPlayerProps) => (
|
const Video = (props: ReactPlayerProps) => (
|
||||||
<div style={{ position: "relative", paddingTop: "56.25%" }}>
|
<div style={{ position: "relative", paddingTop: "56.25%" }}>
|
||||||
|
@@ -39,7 +39,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
.section .year {
|
.year {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,22 +1,10 @@
|
|||||||
import { intlFormat, formatDistanceToNowStrict } from "date-fns";
|
import { intlFormat, formatDistanceToNowStrict } from "date-fns";
|
||||||
import { StarOcticon, ForkOcticon } from "../icons/octicons";
|
import { StarOcticon, ForkOcticon } from "../icons/octicons";
|
||||||
|
import { RepoType } from "../../types";
|
||||||
|
|
||||||
import styles from "./RepoCard.module.css";
|
import styles from "./RepoCard.module.css";
|
||||||
|
|
||||||
type Props = {
|
const RepoCard = (props: RepoType) => (
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
description?: string;
|
|
||||||
language?: {
|
|
||||||
name: string;
|
|
||||||
color?: string;
|
|
||||||
};
|
|
||||||
stars?: number;
|
|
||||||
forks?: number;
|
|
||||||
updatedAt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const RepoCard = (props: Props) => (
|
|
||||||
<div className={styles.card}>
|
<div className={styles.card}>
|
||||||
<a className={styles.name} href={props.url} target="_blank" rel="noopener noreferrer">
|
<a className={styles.name} href={props.url} target="_blank" rel="noopener noreferrer">
|
||||||
{props.name}
|
{props.name}
|
||||||
|
@@ -53,7 +53,6 @@ export const getNote = async (slug: string): Promise<NoteType> => {
|
|||||||
const { code: mdxSource } = await bundleMDX({
|
const { code: mdxSource } = await bundleMDX({
|
||||||
source: content,
|
source: content,
|
||||||
cwd: process.cwd(),
|
cwd: process.cwd(),
|
||||||
// cwd: path.join("/Users/jake/source/jarv.is", "components"),
|
|
||||||
xdmOptions: (options) => {
|
xdmOptions: (options) => {
|
||||||
options.remarkPlugins = [...(options.remarkPlugins ?? []), [remarkGfm, { singleTilde: false }]];
|
options.remarkPlugins = [...(options.remarkPlugins ?? []), [remarkGfm, { singleTilde: false }]];
|
||||||
options.rehypePlugins = [
|
options.rehypePlugins = [
|
||||||
@@ -62,7 +61,12 @@ export const getNote = async (slug: string): Promise<NoteType> => {
|
|||||||
[rehypeSlug, {}],
|
[rehypeSlug, {}],
|
||||||
[
|
[
|
||||||
rehypeAutolinkHeadings,
|
rehypeAutolinkHeadings,
|
||||||
{ behavior: "append", properties: { className: "h-anchor" }, content: [], test: ["h2", "h3"] },
|
{
|
||||||
|
behavior: "append",
|
||||||
|
properties: { className: "h-anchor", ariaHidden: true, tabIndex: -1 },
|
||||||
|
content: [],
|
||||||
|
test: ["h2", "h3"],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
[rehypeHighlight, {}],
|
[rehypeHighlight, {}],
|
||||||
];
|
];
|
||||||
|
@@ -4,8 +4,9 @@ import PageTitle from "../components/page/PageTitle";
|
|||||||
import RepoCard from "../components/projects/RepoCard";
|
import RepoCard from "../components/projects/RepoCard";
|
||||||
import { ProjectsIcon } from "../components/icons";
|
import { ProjectsIcon } from "../components/icons";
|
||||||
import type { GetStaticProps } from "next";
|
import type { GetStaticProps } from "next";
|
||||||
|
import { RepoType } from "../types";
|
||||||
|
|
||||||
const Projects = ({ repos }) => (
|
const Projects = (props: { repos: RepoType[] }) => (
|
||||||
<>
|
<>
|
||||||
<NextSeo
|
<NextSeo
|
||||||
title="Projects"
|
title="Projects"
|
||||||
@@ -23,7 +24,7 @@ const Projects = ({ repos }) => (
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{repos.map((repo) => (
|
{props.repos.map((repo: RepoType) => (
|
||||||
<div key={repo.name} className="repo_card">
|
<div key={repo.name} className="repo_card">
|
||||||
<RepoCard {...repo} />
|
<RepoCard {...repo} />
|
||||||
</div>
|
</div>
|
||||||
@@ -103,7 +104,7 @@ export const getStaticProps: GetStaticProps = async () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const repos = user.repositories.edges.map(({ node: repo }) => ({
|
const repos: RepoType[] = user.repositories.edges.map(({ node: repo }) => ({
|
||||||
name: repo.name,
|
name: repo.name,
|
||||||
url: repo.url,
|
url: repo.url,
|
||||||
description: repo.description,
|
description: repo.description,
|
||||||
|
@@ -20,7 +20,7 @@ a:hover {
|
|||||||
background-size: 100% 2px;
|
background-size: 100% 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set an anchor's class to `no-underline` to disable all of this */
|
/* set an anchor's class to `no-underline` to disable all of the above */
|
||||||
.no-underline {
|
.no-underline {
|
||||||
background: none !important;
|
background: none !important;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
@@ -49,59 +49,6 @@ code {
|
|||||||
padding: 0.1em 0.25em;
|
padding: 0.1em 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* code blocks */
|
|
||||||
pre code {
|
|
||||||
display: block;
|
|
||||||
overflow-x: auto;
|
|
||||||
padding: 1em;
|
|
||||||
tab-size: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* sub-heading anchor styles */
|
|
||||||
.h-anchor {
|
|
||||||
margin: 0 0.25em;
|
|
||||||
padding: 0 0.25em;
|
|
||||||
color: var(--medium-light);
|
|
||||||
background: none;
|
|
||||||
font-weight: 300;
|
|
||||||
opacity: 0; /* overridden on hover */
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
.h-anchor::before {
|
|
||||||
content: "\0023"; /* pound sign `#`, done here to keep content DOM cleaner */
|
|
||||||
}
|
|
||||||
.h-anchor:hover {
|
|
||||||
color: var(--link);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make anchor `#` link show up on hover over the corresponding heading */
|
|
||||||
h2:hover .h-anchor,
|
|
||||||
h3:hover .h-anchor,
|
|
||||||
h4:hover .h-anchor {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* offset (approximately) with sticky header so jumped-to content isn't hiding behind it */
|
|
||||||
h2 {
|
|
||||||
scroll-margin-top: 4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3,
|
|
||||||
h4 {
|
|
||||||
scroll-margin-top: 5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
|
||||||
h2 {
|
|
||||||
scroll-margin-top: 5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3,
|
|
||||||
h4 {
|
|
||||||
scroll-margin-top: 6em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://web.dev/prefers-reduced-motion/#(bonus)-forcing-reduced-motion-on-all-websites */
|
/* https://web.dev/prefers-reduced-motion/#(bonus)-forcing-reduced-motion-on-all-websites */
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
*,
|
*,
|
||||||
|
13
types/index.d.ts
vendored
13
types/index.d.ts
vendored
@@ -15,3 +15,16 @@ export type NoteType = {
|
|||||||
frontMatter: NoteMetaType;
|
frontMatter: NoteMetaType;
|
||||||
mdxSource: string;
|
mdxSource: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type RepoType = {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
description?: string;
|
||||||
|
language?: {
|
||||||
|
name: string;
|
||||||
|
color?: string;
|
||||||
|
};
|
||||||
|
stars?: number;
|
||||||
|
forks?: number;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
Reference in New Issue
Block a user