Skip to content
This repository has been archived by the owner on Jul 18, 2024. It is now read-only.

Commit

Permalink
feat: init TailwindCSS & MDX components
Browse files Browse the repository at this point in the history
  • Loading branch information
CanRau committed Dec 5, 2021
2 parents 1b7ca8e + 1532093 commit cbdd3f6
Show file tree
Hide file tree
Showing 19 changed files with 4,870 additions and 842 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ node_modules
/server/build
/public/build
/build
/app/styles/windicss
/app/styles
107 changes: 107 additions & 0 deletions app/components/typography.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import * as React from "react";
import clsx from "clsx";

type TitleProps = {
variant?: "primary" | "secondary";
as?: React.ElementType;
className?: string;
id?: string;
} & (
| { children: React.ReactNode }
| {
dangerouslySetInnerHTML: {
__html: string;
};
}
);

const fontSize = {
h1: "leading-tight text-4xl md:text-5xl",
h2: "leading-tight text-3xl md:text-4xl",
h3: "text-2xl font-medium md:text-3xl",
h4: "text-xl font-medium md:text-2xl",
h5: "text-lg font-medium md:text-xl",
h6: "text-lg font-medium",
};

const titleColors = {
primary: "text-black dark:text-white",
secondary: "text-gray-400 dark:text-blueGray-500",
};

function Title({
variant = "primary",
size,
as,
className,
...rest
}: TitleProps & { size: keyof typeof fontSize }) {
const Tag = as ?? size;
return (
<Tag
className={clsx(fontSize[size], titleColors[variant], className)}
{...rest}
/>
);
}

function H1(props: TitleProps) {
return <Title {...props} size="h1" />;
}

function H2(props: TitleProps) {
return <Title {...props} size="h2" />;
}

function H3(props: TitleProps) {
return <Title {...props} size="h3" />;
}

function H4(props: TitleProps) {
return <Title {...props} size="h4" />;
}

function H5(props: TitleProps) {
return <Title {...props} size="h5" />;
}

function H6(props: TitleProps) {
return <Title {...props} size="h6" />;
}

type ParagraphProps = {
className?: string;
prose?: boolean;
textColorClassName?: string;
as?: React.ElementType;
} & (
| { children: React.ReactNode }
| { dangerouslySetInnerHTML: { __html: string } }
);

// from mdx-bundler readme
// const Paragraph: FC = (props) => {
// if (typeof props.children !== "string" && props?.children?.type === "img") {
// return <>{props.children}</>;
// }

// return <p className="mt-6" {...props} />;
// };

// from kentcdodds.com
function Paragraph({
className,
prose = true,
as = "p",
textColorClassName = "text-secondary",
...rest
}: ParagraphProps) {
return React.createElement(as, {
className: clsx("max-w-full text-lg", textColorClassName, className, {
"prose prose-light dark:prose-dark": prose,
}),
...rest,
});
}

export { H1, H2, H3, H4, H5, H6, Paragraph };
4 changes: 2 additions & 2 deletions app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { renderToString } from "react-dom/server";
import { RemixServer } from "remix";
import type { EntryContext } from "remix";
import { generateStyles } from "~/generate-styles.server";
// import { generateStyles } from "~/generate-styles.server";

// const cachedStyles: Record<string, boolean> = {};
const isProd = process.env.NODE_ENV === "production";
Expand All @@ -24,7 +24,7 @@ export default async function handleRequest(
// if (!cachedStyles[request.url]) {
// console.log(`generating styles for ${request.url}`);
const url = new URL(request.url);
await generateStyles({ url, html: markup, minify: isProd });
// await generateStyles({ url, html: markup, minify: isProd });
// cachedStyles[request.url] = true;
// }

Expand Down
72 changes: 72 additions & 0 deletions app/geneate-styles.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import fs from "fs/promises";
import { join } from "path";
import slugify from "@sindresorhus/slugify";
import { Processor } from "windicss/lib";
import { HTMLParser } from "windicss/utils/parser";

type IGenerateStyles = {
url: URL;
html: string;
minify?: boolean;
};

export async function generateStyles({
url,
html,
minify = false,
}: IGenerateStyles) {
// Get windi processor
const processor = new Processor();

// Parse all classes and put into one line to simplify operations
const htmlClasses = new HTMLParser(html)
.parseClasses()
.map((i) => i.result)
.join(" ");

// Generate preflight based on the html we input
// const preflightSheet = processor.preflight(html);

// Process the html classes to an interpreted style sheet
const interpretedSheet = processor.interpret(htmlClasses).styleSheet;

// Build styles
// const APPEND = false;
// const styles = interpretedSheet.extend(preflightSheet, APPEND).build(minify);
const styles = interpretedSheet.build(minify);

const cssFileName = url.pathname === "/" ? "index" : slugify(url.pathname);
const cssPath = join(
process.cwd(),
"app",
"styles",
"windicss",
`${cssFileName}.css`,
);
await fs.writeFile(cssPath, styles);

return styles;
}

export async function generatePreflightStyles({
minify = false,
}: {
minify: boolean;
}) {
// Get windi processor
const processor = new Processor();

// Generate preflight based on the html we input
const preflightSheet = processor.preflight();
// Build styles
const styles = preflightSheet.build(minify);

const cssPath = join(
process.cwd(),
"app",
"styles",
"windicss",
"preflight.css",
);
await fs.writeFile(cssPath, styles);
}
52 changes: 23 additions & 29 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import {
NavLink,
} from "remix";

// import preflightStyles from "~/styles/windicss/preflight.css";
import deleteMeRemixStyles from "~/styles/demos/remix.css";
import globalStylesUrl from "~/styles/global.css";
import darkStylesUrl from "~/styles/dark.css";
import tailwindStyles from "~/styles/tailwind.css";
// import deleteMeRemixStyles from "~/styles/demos/remix.css";
// import globalStylesUrl from "~/styles/global.css";
// import darkStylesUrl from "~/styles/dark.css";
// import acceptLanguage from "accept-language";
// import { languages } from "/remix.config.js";

Expand Down Expand Up @@ -49,14 +49,14 @@ import darkStylesUrl from "~/styles/dark.css";
*/
export let links: LinksFunction = () => {
return [
// { rel: "stylesheet", href: preflightStyles },
{ rel: "stylesheet", href: globalStylesUrl },
{
rel: "stylesheet",
href: darkStylesUrl,
media: "(prefers-color-scheme: dark)",
},
{ rel: "stylesheet", href: deleteMeRemixStyles },
{ rel: "stylesheet", href: tailwindStyles },
// { rel: "stylesheet", href: globalStylesUrl },
// {
// rel: "stylesheet",
// href: darkStylesUrl,
// media: "(prefers-color-scheme: dark)",
// },
// { rel: "stylesheet", href: deleteMeRemixStyles },
];
};

Expand Down Expand Up @@ -87,15 +87,15 @@ function Document({
lang: string;
}) {
return (
<html lang={lang}>
<html lang={lang} className="dark">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
{title ? <title>{title}</title> : null}
<Meta />
<Links />
</head>
<body>
<body className="dark:bg-gray-900">
{children}
<ScrollRestoration />
<Scripts />
Expand All @@ -107,34 +107,28 @@ function Document({

function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="remix-app">
<header className="remix-app__header">
<div className="container remix-app__header-content">
<Link to="/" title="Remix" className="remix-app__header-home-link">
<div className="remix-app mx-10vw">
<header className="px-5vw py-9 lg:py-12">
<div className="lg:max-w-3xl mx-auto flex item-center justify-between dark:text-gray-400">
<Link to="/" title="Can Rau Homepage" className="text-2xl">
{/* <RemixLogo /> */}
<h2>Can Rau</h2>
</Link>
<nav aria-label="Main navigation" className="remix-app__header-nav">
<ul>
<li>
<ul className="flex">
<li className="px-5 py-2">
<Link to="/">Home</Link>
</li>
<li>
<a href="https://remix.run/docs">Remix Docs</a>
</li>
<li>
<a href="https://github.com/remix-run/remix">GitHub</a>
</li>
</ul>
</nav>
</div>
</header>
<div className="remix-app__main">
<div className="container remix-app__main-content">{children}</div>
<div className="">{children}</div>
</div>
<footer className="remix-app__footer">
<div className="container remix-app__footer-content">
<p>&copy; You!</p>
<div className="flex items-center justify-center mt-8 mb-2 mx-5vw dark:text-gray-600">
<p>&copy; 2021 Can Rau</p>
</div>
</footer>
</div>
Expand Down
34 changes: 31 additions & 3 deletions app/routes/$lang/$slug.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import type { MetaFunction, LoaderFunction, LinksFunction } from "remix";
import { useLoaderData, json, Link, redirect } from "remix";
import { useMemo } from "react";
import { useMemo, FC } from "react";
// import { bundleMDX } from "mdx-bundler";
import {
bundleMDX,
getContentPath,
getFilePath,
} from "~/utils/compile-mdx.server";
import { getMDXComponent, getMDXExport } from "mdx-bundler/client";
import * as typography from "~/components/typography";
import prismPlus from "~/styles/prism-plus.css";
import prismTheme from "~/styles/prism-theme.css";

export const meta: MetaFunction = ({ data, parentsData, location, params }) => {
console.log({ parentsData });
Expand All @@ -18,11 +21,25 @@ export const meta: MetaFunction = ({ data, parentsData, location, params }) => {
title: title || "Missing Title",
description: description || "Missing description",
"og:image": cover ? `/build/_assets${slug}/${cover}` : "",
"twitter:image": cover ? `/build/_assets${slug}/${cover}` : "",
// 'og:url': url,
// 'og:title': title,
// 'og:description': description,
// 'og:image': image,
// 'twitter:card': image ? 'summary_large_image' : 'summary',
// 'twitter:creator': '@kentcdodds',
// 'twitter:site': '@kentcdodds',
// 'twitter:title': title,
// 'twitter:description': description,
// 'twitter:image': image,
// 'twitter:alt': title,
};
};

export const links: LinksFunction = () => {
return [
{ rel: "stylesheet", href: prismPlus },
{ rel: "stylesheet", href: prismTheme },
// { rel: "stylesheet", href: globalStylesUrl },
// {
// rel: "stylesheet",
Expand Down Expand Up @@ -53,14 +70,25 @@ export const loader: LoaderFunction = async ({ params }) => {
return { frontmatter, code };
};

// note: more on [component substitution](https://github.com/wooorm/xdm#components)
const components = {
h1: typography.H1,
h2: typography.H2,
h3: typography.H3,
h4: typography.H4,
h5: typography.H5,
h6: typography.H6,
p: typography.Paragraph,
};

export default function Post() {
const { code, frontmatter } = useLoaderData();
const Component = useMemo(() => getMDXComponent(code), [code]);
// console.log({ frontmatter }, getMDXExport(code));
return (
<>
<main>
<Component />
<main className="prose prose-light dark:prose-dark mx-auto">
<Component components={components} />
</main>
</>
);
Expand Down
2 changes: 1 addition & 1 deletion app/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default function Index() {
<main>
<h2 className="bg-red-600">Welcome to Remix!</h2>
<p>We're stoked that you're here. 🥳</p>
<p>
<p className="text-green-300">
Feel free to take a look around the code to see how Remix does things,
it might be a bit different than what you’re used to. When you're
ready to dive deeper, we've got plenty of resources to get you
Expand Down
Loading

0 comments on commit cbdd3f6

Please sign in to comment.