Skip to content

Commit f3fe7bf

Browse files
authored
Upgrade to Next.js 16, Tailwind CSS 4, Headless UI 2 (#35)
Signed-off-by: Joe Karow <58997957+JoeKarow@users.noreply.github.com>
1 parent eee6b89 commit f3fe7bf

50 files changed

Lines changed: 2173 additions & 1695 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,6 @@ dist
108108
.env.local
109109

110110
.DS_Store
111+
112+
# Next.js generated TypeScript declarations
113+
next-env.d.ts

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
18
1+
24

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ This repo requires `node`, `pnpm`, and the [Netlify CLI](https://www.netlify.com
2222

2323
#### Installing `node`:
2424

25-
The best way to install `node` is to [download the installer](https://nodejs.org/en/) from their site. This repo requires `node` version `18.16`, which is the latest [LTS version](https://nodejs.dev/en/about/releases/).
25+
The best way to install `node` is to [download the installer](https://nodejs.org/en/) from their site. This repo requires `node` version `24` or newer (see `.nvmrc`), which is the current [LTS version](https://nodejs.org/en/about/previous-releases).
2626

2727
If you already have a different version of `node` installed, but don't want to update globally, you can install [a package called `nvm`](https://github.com/nvm-sh/nvm), which will allow you to easily switch `node` versions. Once you have `nvm` installed (or if you already have it installed), you can run `nvm use` in the main directory and it will install the proper version of `node`.
2828

@@ -43,10 +43,10 @@ corepack prepare
4343

4444
#### Setting up your .env
4545

46-
Use the following command to create a local `.env` file. Then open the new file (`.env`) and adjust any settings that are needed.
46+
Use the following command to create a local `.env.local` file. Then open the new file (`.env.local`) and adjust any settings that are needed.
4747

4848
```shell
49-
cp .env.example .env
49+
cp .env.local.example .env.local
5050
```
5151

5252
#### Installing package dependencies
@@ -88,5 +88,6 @@ Use ctrl-c to quit the server when you're done.
8888
## Uses:
8989

9090
- [NextJS](https://nextjs.org/docs/)
91+
- [TypeScript](https://www.typescriptlang.org/)
9192
- [Tailwind UI](https://tailwindui.com)
9293
- Hosted on [Netlify](https://www.netlify.com/)
Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,25 @@ import {
44
CheckCircleIcon,
55
InformationCircleIcon,
66
} from '@heroicons/react/24/solid'
7-
import classNames from '../util/classNames'
7+
import type { ReactNode } from 'react'
8+
import type { AlertType } from '@/data/forms'
9+
import classNames from '@/util/classNames'
810

9-
const alertTypes = {
11+
type AlertStyle = {
12+
bodyBg: string
13+
Icon: typeof XCircleIcon
14+
iconColor: string
15+
titleColor: string
16+
bodyColor?: string
17+
}
18+
19+
type AlertProps = {
20+
title?: ReactNode
21+
alertType?: AlertType
22+
children?: ReactNode
23+
}
24+
25+
const alertTypes: Record<AlertType, AlertStyle> = {
1026
error: {
1127
bodyBg: 'bg-red-50',
1228
Icon: XCircleIcon,
@@ -36,12 +52,16 @@ const alertTypes = {
3652
},
3753
}
3854

39-
export default function Alert({ title, alertType = 'info', children }) {
55+
export default function Alert({
56+
title,
57+
alertType = 'info',
58+
children,
59+
}: AlertProps) {
4060
const typeStyles = alertTypes[alertType]
4161
return (
4262
<div className={classNames('rounded-md p-4 mt-8', typeStyles.bodyBg)}>
4363
<div className="flex">
44-
<div className="flex-shrink-0">
64+
<div className="shrink-0">
4565
<typeStyles.Icon
4666
className={classNames('h-5 w-5', typeStyles.iconColor)}
4767
aria-hidden="true"
@@ -73,31 +93,35 @@ export default function Alert({ title, alertType = 'info', children }) {
7393
)
7494
}
7595

76-
export function InfoAlert({ title, children }) {
96+
export function InfoAlert({ title, children }: AlertProps) {
7797
return (
7898
<Alert title={title} alertType="info">
7999
{children}
80100
</Alert>
81101
)
82102
}
83103

84-
export function SuccessAlert({ title, children }) {
104+
export function SuccessAlert({ title, children }: AlertProps) {
85105
return (
86106
<Alert title={title} alertType="success">
87107
{children}
88108
</Alert>
89109
)
90110
}
91111

92-
export function WarningAlert({ title, children }) {
112+
export function WarningAlert({ title, children }: AlertProps) {
93113
return (
94114
<Alert title={title} alertType="warning">
95115
{children}
96116
</Alert>
97117
)
98118
}
99119

100-
export function ErrorAlert({ title, errors, children }) {
120+
export function ErrorAlert({
121+
title,
122+
errors,
123+
children,
124+
}: AlertProps & { errors?: string[] }) {
101125
return (
102126
<Alert title={title} alertType="error">
103127
<>
Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import Link from 'next/link'
2-
import classNames from '../util/classNames'
2+
import type { MouseEventHandler, ReactNode } from 'react'
3+
import classNames from '@/util/classNames'
34

45
const defaultClassName =
5-
'inline-block border border-transparent leading-6 font-medium rounded-md focus:outline-none focus:shadow-outline transition duration-150 ease-in-out'
6+
'inline-block border border-transparent leading-6 font-medium rounded-md focus:outline-hidden focus:shadow-outline transition duration-150 ease-in-out'
67

78
const colors = {
89
primary: 'text-orange-50 hover:text-white bg-orange-600 hover:bg-orange-500',
@@ -15,15 +16,26 @@ const sizes = {
1516
lg: 'text-lg px-7 py-5',
1617
}
1718

19+
type ButtonProps = {
20+
href?: string
21+
external?: boolean
22+
size?: keyof typeof sizes
23+
color?: keyof typeof colors
24+
className?: string
25+
children?: ReactNode
26+
type?: 'button' | 'submit' | 'reset'
27+
onClick?: MouseEventHandler<HTMLElement>
28+
}
29+
1830
export default function Button({
1931
external,
2032
href,
2133
size = 'md',
2234
color = 'primary',
2335
className: providedClassname = '',
2436
...props
25-
}) {
26-
props.className = classNames(
37+
}: ButtonProps) {
38+
const className = classNames(
2739
defaultClassName,
2840
sizes[size],
2941
colors[color],
@@ -32,10 +44,10 @@ export default function Button({
3244

3345
if (href) {
3446
if (external) {
35-
return <a href={href} {...props} />
47+
return <a href={href} className={className} {...props} />
3648
}
37-
return <Link href={href} {...props} />
49+
return <Link href={href} className={className} {...props} />
3850
}
3951

40-
return <button {...props} />
52+
return <button className={className} {...props} />
4153
}
Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,47 @@
11
/* This example requires Tailwind CSS v2.0+ */
22
import { PaperClipIcon } from '@heroicons/react/24/solid'
33
import Button from './Button'
4+
import type { ReactNode } from 'react'
45

5-
export function CardListItem({ children }) {
6+
type ChildrenProps = { children: ReactNode }
7+
8+
export function CardListItem({ children }: ChildrenProps) {
69
return (
710
<div className="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
811
{children}
912
</div>
1013
)
1114
}
1215

13-
export function CardListItemKey({ children }) {
16+
export function CardListItemKey({ children }: ChildrenProps) {
1417
return <dt className="text-sm font-medium text-gray-500">{children}</dt>
1518
}
1619

17-
export function CardListItemValue({ children }) {
20+
export function CardListItemValue({ children }: ChildrenProps) {
1821
return (
1922
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
2023
{children}
2124
</dd>
2225
)
2326
}
2427

25-
export function CardList({ children }) {
28+
export function CardList({ children }: ChildrenProps) {
2629
return (
2730
<div className="border-t border-gray-200 px-4 py-5 sm:p-0">
2831
<dl className="sm:divide-y sm:divide-gray-200">{children}</dl>
2932
</div>
3033
)
3134
}
3235

33-
export function Card({ children }) {
36+
export function Card({ children }: ChildrenProps) {
3437
return (
35-
<div className="bg-white shadow overflow-hidden sm:rounded-lg">
38+
<div className="bg-white shadow-sm overflow-hidden sm:rounded-lg">
3639
{children}
3740
</div>
3841
)
3942
}
4043

41-
export function CardHeader({ children }) {
44+
export function CardHeader({ children }: ChildrenProps) {
4245
return (
4346
<div className="bg-white px-4 py-5 border-b border-gray-200 sm:px-6">
4447
<div className="-ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-nowrap">
@@ -48,7 +51,13 @@ export function CardHeader({ children }) {
4851
)
4952
}
5053

51-
export function CardHeaderHeader({ title, description }) {
54+
export function CardHeaderHeader({
55+
title,
56+
description,
57+
}: {
58+
title: string
59+
description: string
60+
}) {
5261
return (
5362
<div className="ml-4 mt-4">
5463
<h3 className="text-lg leading-6 font-medium text-gray-900">{title}</h3>
@@ -57,6 +66,6 @@ export function CardHeaderHeader({ title, description }) {
5766
)
5867
}
5968

60-
export function CardHeaderActions({ children }) {
61-
return <div className="ml-4 mt-4 flex-shrink-0">{children}</div>
69+
export function CardHeaderActions({ children }: ChildrenProps) {
70+
return <div className="ml-4 mt-4 shrink-0">{children}</div>
6271
}
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
import Link from 'next/link'
22

3-
export default function ChoiceCard({ choice }) {
3+
export type Choice = {
4+
header: string
5+
intro: string
6+
items: string[]
7+
button: {
8+
text: string
9+
link: string
10+
disabled?: boolean
11+
}
12+
}
13+
14+
export default function ChoiceCard({ choice }: { choice: Choice }) {
415
return (
516
<div className="flex flex-col rounded-lg shadow-lg overflow-hidden">
617
<div className="flex-1 px-6 py-8 bg-white sm:p-10 sm:pb-6">
@@ -13,7 +24,7 @@ export default function ChoiceCard({ choice }) {
1324
<ul className="space-y-4">
1425
{choice.items.map((item) => (
1526
<li className="flex items-start" key={item}>
16-
<div className="flex-shrink-0">
27+
<div className="shrink-0">
1728
<svg
1829
className="h-6 w-6 text-green-500"
1930
fill="none"
@@ -32,15 +43,15 @@ export default function ChoiceCard({ choice }) {
3243
</li>
3344
))}
3445
</ul>
35-
<div className="rounded-md shadow">
46+
<div className="rounded-md shadow-sm">
3647
{choice.button.disabled ? (
37-
<span className="flex items-center justify-center px-5 py-3 border border-transparent text-base leading-6 font-medium rounded-md focus:outline-none focus:shadow-outline transition duration-150 ease-in-out text-gray-50 bg-gray-500">
48+
<span className="flex items-center justify-center px-5 py-3 border border-transparent text-base leading-6 font-medium rounded-md focus:outline-hidden focus:shadow-outline transition duration-150 ease-in-out text-gray-50 bg-gray-500">
3849
{choice.button.text}
3950
</span>
4051
) : (
4152
<Link
4253
href={choice.button.link}
43-
className={`flex items-center justify-center px-5 py-3 border border-transparent text-base leading-6 font-medium rounded-md focus:outline-none focus:shadow-outline transition duration-150 ease-in-out text-orange-50 hover:text-white bg-orange-600 hover:bg-orange-500`}
54+
className={`flex items-center justify-center px-5 py-3 border border-transparent text-base leading-6 font-medium rounded-md focus:outline-hidden focus:shadow-outline transition duration-150 ease-in-out text-orange-50 hover:text-white bg-orange-600 hover:bg-orange-500`}
4455
aria-describedby="tier-standard"
4556
>
4657
{choice.button.text}

components/Container.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

components/Container.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { ReactNode } from 'react'
2+
3+
export default function Container({ children }: { children: ReactNode }) {
4+
return (
5+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">{children}</div>
6+
)
7+
}

0 commit comments

Comments
 (0)