Skip to content

Commit 7db125f

Browse files
committed
new template version
1 parent 19457d6 commit 7db125f

Some content is hidden

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

86 files changed

+18919
-0
lines changed

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
node_modules
2+
3+
/.cache
4+
/public/build
5+
/build
6+
.env
7+
8+
# Local Netlify folder
9+
.netlify
10+
.DS_Store

app/components/container.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function Container({ children }: { children: React.ReactNode }) {
2+
return <div className="mx-auto max-w-7xl px-4 sm:px-6">{children}</div>
3+
}

app/components/header.tsx

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use client'
2+
3+
import { Container } from '@/components/container'
4+
import { CardHeader, CardTitle, CardDescription } from './ui/card'
5+
6+
interface HeaderProps {
7+
title: string
8+
description: string
9+
}
10+
11+
export function Header({ title, description }: HeaderProps) {
12+
return (
13+
<header className="border-b py-6 sm:py-12 mb-12 -mt-6">
14+
<Container>
15+
<CardHeader className="p-0 max-w-xl">
16+
<CardTitle level={1} className="sm:text-2xl text-xl">
17+
{title}
18+
</CardTitle>
19+
<CardDescription className="sm:text-base text-sm">{description}</CardDescription>
20+
</CardHeader>
21+
</Container>
22+
</header>
23+
)
24+
}

app/components/nav.tsx

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
'use client'
2+
3+
import React, { useEffect } from 'react'
4+
5+
import { Container } from '@/components/container'
6+
import { ThemeSwitcher } from '@/components/theme-switcher'
7+
import { IconBrandGithub, IconBrandJustd } from '@irsyadadl/paranoid'
8+
import { LayoutGroup, motion } from 'framer-motion'
9+
import { Button, Link, ListBox, ListBoxItem, ListBoxItemProps } from 'react-aria-components'
10+
import { tv } from 'tailwind-variants'
11+
import { buttonStyles } from './ui/button'
12+
import { useMediaQuery } from './ui/primitive'
13+
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetBody } from './ui/sheet'
14+
import { Outlet, useLocation } from '@remix-run/react'
15+
16+
const navigations = [
17+
{
18+
name: 'Home',
19+
url: '/'
20+
},
21+
{
22+
name: 'About',
23+
url: '/about'
24+
},
25+
{
26+
name: 'Contact',
27+
url: '/contact'
28+
},
29+
{
30+
name: 'Login',
31+
url: '/login'
32+
},
33+
{
34+
name: 'Components',
35+
url: 'https://justd.co/components'
36+
},
37+
{
38+
name: 'Colors',
39+
url: 'https://justd.co/colors'
40+
},
41+
{
42+
name: 'Icons',
43+
url: 'https://paranoid.irsyad.co'
44+
}
45+
]
46+
47+
export function Nav() {
48+
const isMobile = useMediaQuery('(max-width: 640px)')
49+
return (
50+
<main>
51+
<nav className="sm:py-1 py-2.5 border-b bg-background">
52+
<Container>
53+
<div className="flex items-center justify-between">
54+
<div className="flex gap-x-8 items-center">
55+
<Link href="/" className="">
56+
<IconBrandJustd className="size-5" />
57+
</Link>
58+
{!isMobile && (
59+
<span className="sm:inline hidden">
60+
<NavContent />
61+
</span>
62+
)}
63+
</div>
64+
<div className="flex items-center gap-2 justify-end">
65+
<ThemeSwitcher />
66+
<Link
67+
className={buttonStyles({ appearance: 'outline', size: 'square-petite' })}
68+
href="https://github.com/irsyadadl/next-starter-kit"
69+
>
70+
<IconBrandGithub />
71+
</Link>
72+
<Link className={buttonStyles({ appearance: 'outline', size: 'square-petite' })} href="https://justd.co">
73+
<IconBrandJustd />
74+
</Link>
75+
{isMobile && <NavResponsive />}
76+
</div>
77+
</div>
78+
</Container>
79+
</nav>
80+
<Outlet />
81+
</main>
82+
)
83+
}
84+
85+
const navStyles = tv({
86+
base: 'text-sm relative py-0 sm:py-4 inline-flex focus:outline-none focus-visible:text-fg font-medium',
87+
variants: {
88+
isCurrent: {
89+
true: 'text-fg',
90+
false: 'text-muted-fg'
91+
}
92+
}
93+
})
94+
95+
function NavResponsive() {
96+
const [isOpen, setOpen] = React.useState(false)
97+
const pathname = useLocation()
98+
useEffect(() => {
99+
setOpen(false)
100+
}, [pathname.pathname])
101+
return (
102+
<Sheet onOpenChange={setOpen} isOpen={isOpen}>
103+
<Button size="small" appearance="outline">
104+
Menu
105+
</Button>
106+
<SheetContent>
107+
<SheetHeader className="text-left p-4 border-b">
108+
<SheetTitle className="text-sm flex items-center gap-2">
109+
<IconBrandJustd />
110+
Starter Kit
111+
</SheetTitle>
112+
</SheetHeader>
113+
<SheetBody className="-mx-2 pt-4">
114+
<NavContent />
115+
</SheetBody>
116+
</SheetContent>
117+
</Sheet>
118+
)
119+
}
120+
121+
function NavContent() {
122+
const isMobile = useMediaQuery('(max-width: 640px)')
123+
const id = React.useId()
124+
return (
125+
<LayoutGroup id={id}>
126+
<ListBox
127+
orientation={isMobile ? 'vertical' : 'horizontal'}
128+
layout={isMobile ? 'stack' : 'grid'}
129+
className="flex relative sm:flex-row flex-col sm:items-center gap-3 sm:gap-6"
130+
items={navigations}
131+
>
132+
{(item) => (
133+
<NavLink
134+
target={['Components', 'Colors', 'Icons'].includes(item.name) ? '_blank' : undefined}
135+
href={item.url}
136+
id={item.url}
137+
>
138+
{item.name}
139+
</NavLink>
140+
)}
141+
</ListBox>
142+
</LayoutGroup>
143+
)
144+
}
145+
146+
interface LinkProps extends ListBoxItemProps {
147+
isCurrent?: boolean
148+
className?: string
149+
children: React.ReactNode
150+
}
151+
152+
function NavLink({ children, className, ...props }: LinkProps) {
153+
const isCurrent = useLocation().pathname === props.href
154+
return (
155+
<ListBoxItem className={navStyles({ isCurrent, className })} {...props}>
156+
{children}
157+
{isCurrent && <CurrentIndicator />}
158+
</ListBoxItem>
159+
)
160+
}
161+
162+
function CurrentIndicator() {
163+
return (
164+
<motion.span
165+
className="h-full inset-y-0 sm:inset-auto sm:h-0.5 w-0.5 sm:w-full rounded-full bg-fg -left-4 sm:bottom-[-5px] sm:inset-x block absolute"
166+
layoutId="current"
167+
/>
168+
)
169+
}

app/components/provider.tsx

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use client'
2+
3+
import { ThemeProvider } from 'next-themes'
4+
import { useRouter } from 'next/navigation'
5+
import { RouterProvider } from 'react-aria-components'
6+
7+
declare module 'react-aria-components' {
8+
interface RouterConfig {
9+
routerOptions: NonNullable<Parameters<ReturnType<typeof useRouter>['push']>[1]>
10+
}
11+
}
12+
13+
export function Providers({ children }: { children: React.ReactNode }) {
14+
const router = useRouter()
15+
16+
return (
17+
<RouterProvider navigate={router.push}>
18+
<ThemeProvider attribute="class">{children}</ThemeProvider>
19+
</RouterProvider>
20+
)
21+
}

app/components/theme-provider.tsx

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use client'
2+
3+
import * as React from 'react'
4+
5+
import { ThemeProvider as NextThemesProvider, useTheme } from 'next-themes'
6+
import { type ThemeProviderProps } from 'next-themes/dist/types'
7+
8+
const ThemeProvider = ({ children, ...props }: ThemeProviderProps) => {
9+
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
10+
}
11+
12+
export { ThemeProvider, useTheme }

app/components/theme-switcher.tsx

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { IconMoon, IconSun } from '@irsyadadl/paranoid'
2+
import { Theme, useTheme } from "remix-themes"
3+
import { Button } from '@/components/ui/button'
4+
5+
export function ThemeSwitcher() {
6+
const [theme, setTheme] = useTheme()
7+
console.log(theme)
8+
const switchTheme = () => {
9+
setTheme((prevTheme) => (prevTheme === Theme.LIGHT ? Theme.DARK : Theme.LIGHT));
10+
};
11+
12+
return (
13+
<Button
14+
appearance="outline"
15+
size="square-petite"
16+
aria-label='Switch theme'
17+
onPress={switchTheme}
18+
>
19+
<IconSun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
20+
<IconMoon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
21+
</Button>
22+
)
23+
}

0 commit comments

Comments
 (0)