Skip to content

Commit 27e8a78

Browse files
committed
install Next.js app with Tailwind and Typescript
0 parents  commit 27e8a78

19 files changed

Lines changed: 9196 additions & 0 deletions

.eslintrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "next/core-web-vitals"
3+
}

.prettierrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"arrowParens": "avoid",
3+
"singleQuote": true,
4+
"jsxSingleQuote": true,
5+
"tabWidth": 2,
6+
"trailingComma": "none",
7+
"semi": false,
8+
"proseWrap": "always",
9+
"printWidth": 80,
10+
"plugins": ["prettier-plugin-tailwindcss"]
11+
}

app/globals.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;

app/layout.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { Metadata } from 'next'
2+
import { Inter } from 'next/font/google'
3+
import './globals.css'
4+
import Providers from '@/components/Providers'
5+
6+
const inter = Inter({ subsets: ['latin'] })
7+
8+
export const metadata: Metadata = {
9+
title: 'Create Next App',
10+
description: 'Generated by create next app'
11+
}
12+
13+
export default function RootLayout({
14+
children
15+
}: {
16+
children: React.ReactNode
17+
}) {
18+
return (
19+
<html lang='en' suppressHydrationWarning>
20+
<body className={inter.className}>
21+
<Providers>{children}</Providers>
22+
</body>
23+
</html>
24+
)
25+
}

app/page.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Home() {
2+
return <main></main>
3+
}

components.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "default",
4+
"rsc": true,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "tailwind.config.js",
8+
"css": "app/globals.css",
9+
"baseColor": "slate",
10+
"cssVariables": false
11+
},
12+
"aliases": {
13+
"components": "@/components",
14+
"utils": "@/lib/utils"
15+
}
16+
}

components/Navbar.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use client'
2+
import { moon, sun } from '@/public'
3+
import { useTheme } from 'next-themes'
4+
import Image from 'next/image'
5+
import Link from 'next/link'
6+
7+
const Navbar = ({}) => {
8+
const { setTheme, resolvedTheme } = useTheme()
9+
function handleTheming() {
10+
setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')
11+
}
12+
13+
return (
14+
<nav className='sticky top-0 z-10 w-full backdrop-blur-lg backdrop-filter'>
15+
<div className=' mx-auto border-b-[0.3px] border-slate-400 bg-slate-200 bg-opacity-30 p-5 shadow-lg backdrop-blur-lg backdrop-filter dark:bg-slate-950 dark:bg-opacity-50 md:justify-around md:p-10'>
16+
<div className='flex items-center justify-between'>
17+
<h1 className='text-lg font-black tracking-wider md:text-2xl lg:text-4xl'>
18+
<Link href='/'>Where In the World ?</Link>
19+
</h1>
20+
{resolvedTheme === 'light' ? (
21+
<Image
22+
onClick={handleTheming}
23+
className='rotate-0 cursor-pointer transition-all duration-300 md:h-9 md:w-9'
24+
src={moon}
25+
width={20}
26+
height={20}
27+
alt='icons'
28+
/>
29+
) : (
30+
<Image
31+
onClick={handleTheming}
32+
className='rotate-180 cursor-pointer transition-all duration-300 md:h-9 md:w-9'
33+
width={20}
34+
height={20}
35+
src={sun}
36+
alt='icons'
37+
/>
38+
)}
39+
</div>
40+
</div>
41+
</nav>
42+
)
43+
}
44+
45+
export default Navbar

components/ui/button.tsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const buttonVariants = cva(
8+
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:ring-offset-slate-950 dark:focus-visible:ring-slate-300",
9+
{
10+
variants: {
11+
variant: {
12+
default: "bg-slate-900 text-slate-50 hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90",
13+
destructive:
14+
"bg-red-500 text-slate-50 hover:bg-red-500/90 dark:bg-red-900 dark:text-slate-50 dark:hover:bg-red-900/90",
15+
outline:
16+
"border border-slate-200 bg-white hover:bg-slate-100 hover:text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50",
17+
secondary:
18+
"bg-slate-100 text-slate-900 hover:bg-slate-100/80 dark:bg-slate-800 dark:text-slate-50 dark:hover:bg-slate-800/80",
19+
ghost: "hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-slate-800 dark:hover:text-slate-50",
20+
link: "text-slate-900 underline-offset-4 hover:underline dark:text-slate-50",
21+
},
22+
size: {
23+
default: "h-10 px-4 py-2",
24+
sm: "h-9 rounded-md px-3",
25+
lg: "h-11 rounded-md px-8",
26+
icon: "h-10 w-10",
27+
},
28+
},
29+
defaultVariants: {
30+
variant: "default",
31+
size: "default",
32+
},
33+
}
34+
)
35+
36+
export interface ButtonProps
37+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38+
VariantProps<typeof buttonVariants> {
39+
asChild?: boolean
40+
}
41+
42+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43+
({ className, variant, size, asChild = false, ...props }, ref) => {
44+
const Comp = asChild ? Slot : "button"
45+
return (
46+
<Comp
47+
className={cn(buttonVariants({ variant, size, className }))}
48+
ref={ref}
49+
{...props}
50+
/>
51+
)
52+
}
53+
)
54+
Button.displayName = "Button"
55+
56+
export { Button, buttonVariants }

components/ui/form.tsx

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import * as React from "react"
2+
import * as LabelPrimitive from "@radix-ui/react-label"
3+
import { Slot } from "@radix-ui/react-slot"
4+
import {
5+
Controller,
6+
ControllerProps,
7+
FieldPath,
8+
FieldValues,
9+
FormProvider,
10+
useFormContext,
11+
} from "react-hook-form"
12+
13+
import { cn } from "@/lib/utils"
14+
import { Label } from "@/components/ui/label"
15+
16+
const Form = FormProvider
17+
18+
type FormFieldContextValue<
19+
TFieldValues extends FieldValues = FieldValues,
20+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
21+
> = {
22+
name: TName
23+
}
24+
25+
const FormFieldContext = React.createContext<FormFieldContextValue>(
26+
{} as FormFieldContextValue
27+
)
28+
29+
const FormField = <
30+
TFieldValues extends FieldValues = FieldValues,
31+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
32+
>({
33+
...props
34+
}: ControllerProps<TFieldValues, TName>) => {
35+
return (
36+
<FormFieldContext.Provider value={{ name: props.name }}>
37+
<Controller {...props} />
38+
</FormFieldContext.Provider>
39+
)
40+
}
41+
42+
const useFormField = () => {
43+
const fieldContext = React.useContext(FormFieldContext)
44+
const itemContext = React.useContext(FormItemContext)
45+
const { getFieldState, formState } = useFormContext()
46+
47+
const fieldState = getFieldState(fieldContext.name, formState)
48+
49+
if (!fieldContext) {
50+
throw new Error("useFormField should be used within <FormField>")
51+
}
52+
53+
const { id } = itemContext
54+
55+
return {
56+
id,
57+
name: fieldContext.name,
58+
formItemId: `${id}-form-item`,
59+
formDescriptionId: `${id}-form-item-description`,
60+
formMessageId: `${id}-form-item-message`,
61+
...fieldState,
62+
}
63+
}
64+
65+
type FormItemContextValue = {
66+
id: string
67+
}
68+
69+
const FormItemContext = React.createContext<FormItemContextValue>(
70+
{} as FormItemContextValue
71+
)
72+
73+
const FormItem = React.forwardRef<
74+
HTMLDivElement,
75+
React.HTMLAttributes<HTMLDivElement>
76+
>(({ className, ...props }, ref) => {
77+
const id = React.useId()
78+
79+
return (
80+
<FormItemContext.Provider value={{ id }}>
81+
<div ref={ref} className={cn("space-y-2", className)} {...props} />
82+
</FormItemContext.Provider>
83+
)
84+
})
85+
FormItem.displayName = "FormItem"
86+
87+
const FormLabel = React.forwardRef<
88+
React.ElementRef<typeof LabelPrimitive.Root>,
89+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
90+
>(({ className, ...props }, ref) => {
91+
const { error, formItemId } = useFormField()
92+
93+
return (
94+
<Label
95+
ref={ref}
96+
className={cn(error && "text-red-500 dark:text-red-900", className)}
97+
htmlFor={formItemId}
98+
{...props}
99+
/>
100+
)
101+
})
102+
FormLabel.displayName = "FormLabel"
103+
104+
const FormControl = React.forwardRef<
105+
React.ElementRef<typeof Slot>,
106+
React.ComponentPropsWithoutRef<typeof Slot>
107+
>(({ ...props }, ref) => {
108+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
109+
110+
return (
111+
<Slot
112+
ref={ref}
113+
id={formItemId}
114+
aria-describedby={
115+
!error
116+
? `${formDescriptionId}`
117+
: `${formDescriptionId} ${formMessageId}`
118+
}
119+
aria-invalid={!!error}
120+
{...props}
121+
/>
122+
)
123+
})
124+
FormControl.displayName = "FormControl"
125+
126+
const FormDescription = React.forwardRef<
127+
HTMLParagraphElement,
128+
React.HTMLAttributes<HTMLParagraphElement>
129+
>(({ className, ...props }, ref) => {
130+
const { formDescriptionId } = useFormField()
131+
132+
return (
133+
<p
134+
ref={ref}
135+
id={formDescriptionId}
136+
className={cn("text-sm text-slate-500 dark:text-slate-400", className)}
137+
{...props}
138+
/>
139+
)
140+
})
141+
FormDescription.displayName = "FormDescription"
142+
143+
const FormMessage = React.forwardRef<
144+
HTMLParagraphElement,
145+
React.HTMLAttributes<HTMLParagraphElement>
146+
>(({ className, children, ...props }, ref) => {
147+
const { error, formMessageId } = useFormField()
148+
const body = error ? String(error?.message) : children
149+
150+
if (!body) {
151+
return null
152+
}
153+
154+
return (
155+
<p
156+
ref={ref}
157+
id={formMessageId}
158+
className={cn("text-sm font-medium text-red-500 dark:text-red-900", className)}
159+
{...props}
160+
>
161+
{body}
162+
</p>
163+
)
164+
})
165+
FormMessage.displayName = "FormMessage"
166+
167+
export {
168+
useFormField,
169+
Form,
170+
FormItem,
171+
FormLabel,
172+
FormControl,
173+
FormDescription,
174+
FormMessage,
175+
FormField,
176+
}

components/ui/input.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as React from 'react'
2+
3+
import { cn } from '@/lib/utils'
4+
5+
export interface InputProps
6+
extends React.InputHTMLAttributes<HTMLInputElement> {}
7+
8+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
9+
({ className, type, ...props }, ref) => {
10+
return (
11+
<input
12+
type={type}
13+
className={cn(
14+
'flex h-10 w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-500 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-800 dark:bg-slate-950 dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus-visible:ring-slate-300',
15+
className
16+
)}
17+
ref={ref}
18+
{...props}
19+
/>
20+
)
21+
}
22+
)
23+
Input.displayName = 'Input'
24+
25+
export { Input }

0 commit comments

Comments
 (0)