Skip to content

Commit

Permalink
container api
Browse files Browse the repository at this point in the history
  • Loading branch information
GeorgeIpsum committed Jun 14, 2023
1 parent 8c7d014 commit 19060d6
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 19 deletions.
1 change: 1 addition & 0 deletions postcss.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const config = {
plugins: {
tailwindcss: {},
autoprefixer: {},
...(process.env.NODE_ENV === "production" ? { cssnano: {} } : {}),
},
};

Expand Down
38 changes: 38 additions & 0 deletions scripts/codegen.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
*
* @param {import('plop').NodePlopAPI} plop
*/
export default function plop(plop) {
plop.setGenerator("resource", {
description: "build boilerplate for new db resource",
prompts: [
{
type: "input",
name: "Name",
message: "Resource name",
},
],
actions: [
{
type: "add",
path: "src/server/api/routers/{{name}}.queries.ts",
},
{
type: "add",
path: "src/server/api/routers/{{name}}.mutations.ts",
},
{
type: "add",
path: "src/server/api/routers/{{name}}.validators.ts",
},
],
});

plop.setGenerator("component", {});

plop.setGenerator("atom", {});

plop.setGenerator("hook", {});

plop.setGenerator("page", {});
}
93 changes: 81 additions & 12 deletions src/atoms/Container.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import { useMemo } from "react";

import { renderGeneric } from "@/utils/render";
import type { Renderable } from "@/utils/render";

import type { ContainerBoundaryProps } from "./ContainerBoundary";
import ContainerBoundary from "./ContainerBoundary";

interface ContainerProps {
header?: string | true | JSX.Element;
headerProps?: ContainerBoundaryProps;
externalHeader?: true;
footer?: string | true | JSX.Element;
footerProps?: ContainerBoundaryProps;
externalFooter?: true;
loading?: boolean;
loadingSkeleton?: JSX.Element | React.FC | React.ReactNode;
}

const renderContainerBoundary = (
boundary: Renderable,
boundaryProps: ContainerBoundaryProps
Expand All @@ -27,18 +18,96 @@ const renderContainerBoundary = (
boundaryProps
);

enum RoundingConfig {
TOP = "top",
BOTTOM = "bottom",
NONE = "none",
ALL = "all",
}

const roundingMap: Record<RoundingConfig, string> = {
top: "rounded-t",
bottom: "rounded-b",
none: "",
all: "rounded",
};

const createContainerClasses = (
classString = "",
roundingConfig = RoundingConfig.ALL
) => {
const classes = classString.split(" ");

const bgPrefix = "bg-";
const borderPrefix = "border-";
const inputBg: string[] = [];
const inputBorder: string[] = [];

classes.forEach((className) => {
if (className.includes(bgPrefix)) inputBg.push(className);
if (className.includes(borderPrefix)) inputBorder.push(className);
});

const spacingClasses = "px-4 py-3";
const bgClasses = inputBg.length
? inputBg.join(" ")
: "bg-green-100 dark:bg-green-950";
const borderClasses = inputBorder.length
? inputBorder.join(" ")
: "border-green-200 border-[2px] border-solid";
const roundingClasses = roundingMap[roundingConfig];
const otherClasses = "rounded";

return [
spacingClasses,
bgClasses,
borderClasses,
roundingClasses,
otherClasses,
].join(" ");
};

interface ContainerProps {
header?: string | true | JSX.Element;
headerProps?: ContainerBoundaryProps;
externalHeader?: true;
footer?: string | true | JSX.Element;
footerProps?: ContainerBoundaryProps;
externalFooter?: true;
loading?: boolean;
loadingSkeleton?: JSX.Element | React.FC | React.ReactNode;
containerStyle?: React.CSSProperties;
containerClassname?: string;
}
const Container: React.FC<React.PropsWithChildren<ContainerProps>> = ({
children,
header = null,
headerProps = {},
externalHeader,
footer = null,
footerProps = {},
externalFooter,
loading,
loadingSkeleton,
containerStyle = {},
containerClassname = "",
}) => {
const renderHeader = () => renderContainerBoundary(header, headerProps);
const renderFooter = () => renderContainerBoundary(footer, footerProps);

const containerClasses = useMemo(() => {
let roundingConfig = RoundingConfig.NONE;
if (externalFooter && externalHeader) roundingConfig = RoundingConfig.ALL;
else if (externalFooter && !externalHeader)
roundingConfig = RoundingConfig.TOP;
else if (externalHeader && !externalFooter)
roundingConfig = RoundingConfig.BOTTOM;

return createContainerClasses(containerClassname, roundingConfig);
}, [containerClassname, externalFooter, externalHeader]);

return (
<div>
<div className={containerClasses} style={containerStyle}>
{renderHeader()}
<div>{children}</div>
{renderFooter()}
Expand Down
51 changes: 51 additions & 0 deletions src/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Document, { Head, Html, Main, NextScript } from "next/document";
import type { DocumentContext, DocumentInitialProps } from "next/document";

const persistThemeScript = `
document.documentElement.dataset.mode = (() => {
const persistentTheme = window.localStorage.getItem("theme");
if(persistentTheme === "dark" || persistentTheme === "light") {
return persistentTheme;
}
const mqTheme = window.matchMedia("(prefers-color-scheme: dark)");
return mqTheme.matches ? "dark" : "light";
return "light";
})();`;

// I know this looks messed up. I don't get really why we have to do this over a functional component either
// https://nextjs.org/docs/pages/building-your-application/routing/custom-document
class MyDocument extends Document {
static async getInitialProps(
ctx: DocumentContext
): Promise<DocumentInitialProps> {
const initialProps = await Document.getInitialProps(ctx);

return initialProps;
}

render() {
return (
<Html>
<Head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossOrigin=""
/>
<link
href="https://fonts.googleapis.com/css2?family=Martian+Mono:wght@300;400;500;600;700&family=Poppins:wght@300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<script dangerouslySetInnerHTML={{ __html: persistThemeScript }} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}

export default MyDocument;
6 changes: 3 additions & 3 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Container from "@/atoms/Container";
import { api } from "@/utils/api";

import type { NextPage } from "next";
Expand Down Expand Up @@ -43,9 +44,8 @@ const Home: NextPage = () => {
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-tl dark:from-green-900 dark:to-green-950">
<div className="cursor-pointer rounded-md px-4 py-2 font-bold text-green-50 transition-all duration-500 shade-sm-green-700 hover:shade-sm-hover-green-700 active:ring-2 active:ring-inset active:ring-green-600">
asdfasdf
</div>
<Container>This contains things</Container>
<code>test</code>
</main>
</>
);
Expand Down
11 changes: 11 additions & 0 deletions src/styles/globals.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
:root {
--font-poppins: Poppins, sans-serif;
--font-code: Martian Mono, monospace;
}

html {
@apply bg-green-50 text-green-950 dark:bg-green-950 dark:text-green-50;
}
}
9 changes: 5 additions & 4 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ const createShades = ({ colors, shadows }: ShadeProps) => {
export default {
content: ["./src/**/*.{js,ts,jsx,tsx}"],
presets: [preset],
darkMode: ["class", '[data-mode="dark"]'],
theme: {
extend: {
animation: {
Expand Down Expand Up @@ -169,10 +170,10 @@ export default {
teal: colors.teal,
indigo: colors.indigo,
},
// fontFamily: {
// sans: ["var(--font-poppins)", "sans-serif"],
// mono: ["var(--font-code)", "monospace"],
// },
fontFamily: {
sans: ["var(--font-poppins)", "sans-serif"],
mono: ["var(--font-code)", "monospace"],
},
},
},
plugins: [
Expand Down

0 comments on commit 19060d6

Please sign in to comment.