Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: css-in-js integration for styled-jsx and styled-components #14

Merged
merged 17 commits into from Aug 16, 2022
35 changes: 19 additions & 16 deletions app/layout.server.tsx
@@ -1,5 +1,6 @@
import '@/styles/globals.css';
import AddressBar from '@/ui/AddressBar.client';
import RootStyleRegistry from '@/ui/RootStyleRegistry.client';
import nextPackageJson from 'next/package.json';
import React from 'react';
import GlobalNav from './GlobalNav.client';
Expand All @@ -10,28 +11,30 @@ export default function RootLayout({ children }: { children: any }) {
<head>
<title>Next.js Layouts and Routing Playground</title>
</head>
<body className="overflow-y-scroll bg-zinc-900">
<div className="grid grid-cols-[1fr,minmax(auto,240px),min(800px,100%),1fr] gap-x-8 py-12">
<div className="col-start-2">
<GlobalNav />
</div>
<RootStyleRegistry>
huozhi marked this conversation as resolved.
Show resolved Hide resolved
<body className="overflow-y-scroll bg-zinc-900">
<div className="grid grid-cols-[1fr,minmax(auto,240px),min(800px,100%),1fr] gap-x-8 py-8">
<div className="col-start-2">
<GlobalNav />
</div>

<div className="col-start-3 space-y-6">
<AddressBar />
<div className="col-start-3 space-y-6">
<AddressBar />

<div className="rounded-xl border border-zinc-800 bg-black p-8">
{children}
<div className="rounded-xl border border-zinc-800 bg-black p-8">
{children}
</div>
</div>
</div>

<div className="col-start-3 col-end-4 mt-28">
<div className="flex space-x-6 text-sm text-zinc-600">
<div>React: {React.version}</div>
<div>Next: {nextPackageJson.version}</div>
<div className="col-start-3 col-end-4 mt-28 flex items-center justify-between">
<div className="flex space-x-6 text-sm text-zinc-600">
<div>React: {React.version}</div>
<div>Next: {nextPackageJson.version}</div>
</div>
</div>
</div>
</div>
</body>
</body>
</RootStyleRegistry>
</html>
);
}
49 changes: 49 additions & 0 deletions app/styling/StylingNav.client.tsx
@@ -0,0 +1,49 @@
import { TabNavItem } from '@/ui/TabNavItem';
import { useSelectedLayoutSegment } from 'next/dist/client/components/hooks-client';

const items = [
{
name: 'Home',
slug: '',
},
{
name: 'Global CSS',
slug: 'global-css',
},
{
name: 'CSS Modules',
slug: 'css-modules',
},
{
name: 'Styled Components',
slug: 'styled-components',
},
{
name: 'Styled JSX',
slug: 'styled-jsx',
},
{
name: 'Tailwind CSS',
slug: 'tailwind',
},
];

const StylingNav = () => {
const selectedLayoutSegment = useSelectedLayoutSegment();

return (
<div className="flex items-center space-x-4">
{items.map((item) => (
<TabNavItem
key={item.slug}
href={`/styling/${item.slug}`}
isActive={item.slug === selectedLayoutSegment}
>
{item.name}
</TabNavItem>
))}
</div>
);
};

export default StylingNav;
23 changes: 23 additions & 0 deletions app/styling/css-modules/page.client.tsx
@@ -0,0 +1,23 @@
import { Boundary } from '@/ui/Boundary.server';
import styles from './styles.module.css';

const SkeletonCard = () => (
<div className={styles.skeleton}>
<div className={styles['skeleton-img']} />
<div className={styles['skeleton-btn']} />
<div className={styles['skeleton-line-one']} />
<div className={styles['skeleton-line-two']} />
</div>
);

export default function Page() {
return (
<Boundary labels={['Styled with CSS Modules']}>
<div className={styles.container}>
<SkeletonCard />
<SkeletonCard />
<SkeletonCard />
</div>
</Boundary>
);
}
48 changes: 48 additions & 0 deletions app/styling/css-modules/styles.module.css
@@ -0,0 +1,48 @@
.container {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1.5rem /* 24px */;
}

.skeleton {
padding: 1rem /* 16px */;
border-radius: 1rem /* 16px */;
background-color: rgb(24 24 27 / 0.8);
}

.skeleton-img,
.skeleton-btn,
.skeleton-line-one,
.skeleton-line-two {
border-radius: 0.5rem /* 8px */;
}

.skeleton-img {
height: 3.5rem /* 56px */;
background-color: rgb(63 63 70 / 1);
}

.skeleton-btn,
.skeleton-line-one,
.skeleton-line-two {
margin-top: 0.75rem /* 12px */;
height: 0.75rem /* 12px */;
}

.skeleton-btn {
background-color: rgb(121 40 202 / 1);
width: 25%;
}

.skeleton-line-one,
.skeleton-line-two {
background-color: rgb(63 63 70 / 1);
}

.skeleton-line-one {
width: 91.666667%;
}

.skeleton-line-two {
width: 66.666667%;
}
23 changes: 23 additions & 0 deletions app/styling/global-css/page.server.tsx
@@ -0,0 +1,23 @@
import { Boundary } from '@/ui/Boundary.server';
import './styles.css';

const SkeletonCard = () => (
<div className="skeleton">
<div className="skeleton-img" />
<div className="skeleton-btn" />
<div className="skeleton-line-one" />
<div className="skeleton-line-two" />
</div>
);

export default function Page() {
return (
<Boundary labels={['Styled with a global css stylesheet']}>
<div className="container">
<SkeletonCard />
<SkeletonCard />
<SkeletonCard />
</div>
</Boundary>
);
}
48 changes: 48 additions & 0 deletions app/styling/global-css/styles.css
@@ -0,0 +1,48 @@
.container {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1.5rem /* 24px */;
}

.skeleton {
padding: 1rem /* 16px */;
border-radius: 1rem /* 16px */;
background-color: rgb(24 24 27 / 0.8);
}

.skeleton-img,
.skeleton-btn,
.skeleton-line-one,
.skeleton-line-two {
border-radius: 0.5rem /* 8px */;
}

.skeleton-img {
height: 3.5rem /* 56px */;
background-color: rgb(63 63 70 / 1);
}

.skeleton-btn,
.skeleton-line-one,
.skeleton-line-two {
margin-top: 0.75rem /* 12px */;
height: 0.75rem /* 12px */;
}

.skeleton-btn {
background-color: rgb(245 166 35 / 1);
width: 25%;
}

.skeleton-line-one,
.skeleton-line-two {
background-color: rgb(63 63 70 / 1);
}

.skeleton-line-one {
width: 91.666667%;
}

.skeleton-line-two {
width: 66.666667%;
}
11 changes: 11 additions & 0 deletions app/styling/layout.server.tsx
@@ -0,0 +1,11 @@
import React from 'react';
import StylingNav from './StylingNav.client';

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="space-y-9">
<StylingNav />
<div>{children}</div>
</div>
);
}
27 changes: 27 additions & 0 deletions app/styling/page.server.tsx
@@ -0,0 +1,27 @@
export default function Page() {
return (
<div className="space-y-4">
<div className="text-white">Notes</div>

<ul className="list-disc space-y-2 pl-4 text-sm text-zinc-300">
<li>
Supporting CSS-in-JS (Styled Components and Styled JSX) is a
three-step opt-in process that involves:
</li>
<ul className="list-disc space-y-2 pl-4 text-sm text-zinc-300">
<li>
Creating a "style registry" to collect all CSS rules in a render.
</li>
<li>
Using the new `useFlushEffects` hook to inject rules before any
content that might use them.
</li>
<li>
Creating a client component that wraps your top-level container containing
those styles usage with the style registry during initial server-side rendering.
</li>
</ul>
</ul>
</div>
);
}
65 changes: 65 additions & 0 deletions app/styling/styled-components/page.client.tsx
@@ -0,0 +1,65 @@
import { Boundary } from '@/ui/Boundary.server';
import styled from 'styled-components';

const Container = styled.div`
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1.5rem /* 24px */;
`;

const SkeletonInner = styled.div`
padding: 1rem /* 16px */;
background-color: rgb(24 24 27 / 0.8);
border-radius: 1rem /* 16px */;
`;

const SkeletonImg = styled.div`
height: 3.5rem /* 56px */;
border-radius: 0.5rem /* 8px */;
background-color: rgb(63 63 70 / 1);
`;

const SkeletonBtn = styled.div`
margin-top: 0.75rem /* 12px */;
width: 25%;
height: 0.75rem /* 12px */;
border-radius: 0.5rem /* 8px */;
background-color: rgb(255 0 128 / 1);
`;

const SkeletonLineOne = styled.div`
margin-top: 0.75rem /* 12px */;
height: 0.75rem /* 12px */;
width: 91.666667%;
border-radius: 0.5rem /* 8px */;
background-color: rgb(63 63 70 / 1);
`;

const SkeletonLineTwo = styled.div`
margin-top: 0.75rem /* 12px */;
height: 0.75rem /* 12px */;
width: 66.666667%;
border-radius: 0.5rem /* 8px */;
background-color: rgb(63 63 70 / 1);
`;

const Skeleton = () => (
<SkeletonInner>
<SkeletonImg />
<SkeletonBtn />
<SkeletonLineOne />
<SkeletonLineTwo />
</SkeletonInner>
);

export default function Page() {
return (
<Boundary labels={['Styled with styled-components']}>
<Container>
<Skeleton />
<Skeleton />
<Skeleton />
</Container>
</Boundary>
);
}