Run the init command to create a new Next.js project or to setup an existing one:
npx shadcn init https://hq-ui.vercel.app/r/default
First, add the HQ UI in your components.json:
...
"registries": {
"@hq": "https://hq-ui.vercel.app/r/{name}"
}You can now start adding components to your project.
npx shadcn add @hq/button
Or if you don't wan't to modify components.json, you can use this command
npx shadcn add https://hq-ui.vercel.app/r/button
React Aria components such as Link, Menu, Tabs, and Table transform elements into clickable links that navigate when clicked. These components utilize the href prop to render as an <a> tag, supporting attributes like target and download.
To integrate with Next.js (App Router), ensure the locale on the server matches the client, and configure React Aria links to use the Next.js router.
"use client"
import { useRouter } from 'next/navigation'
import { RouterProvider } from 'react-aria-components'
declare module 'react-aria-components' {
interface RouterConfig {
routerOptions: NonNullable<Parameters<ReturnType<typeof useRouter>['push']>[1]>
}
}
export function ClientProviders({ children }: { children: React.ReactNode }) {
const router = useRouter()
return (
<RouterProvider navigate={router.push}>
{children}
</RouterProvider>
)
}Then use in your root layout
import { Geist, Geist_Mono } from "next/font/google"
import "./globals.css"
import { ThemeProvider } from "@/components/theme-provider"
import { ClientProvider } from '@/components/client-provider'
const fontSans = Geist({
subsets: ["latin"],
variable: "--font-sans",
})
const fontMono = Geist_Mono({
subsets: ["latin"],
variable: "--font-mono",
})
export default async function RootLayout({
children
}: Readonly<{
children: React.ReactNode
}>){
return (
<html
lang='en'
suppressHydrationWarning
className={`${fontSans.variable} ${fontMono.variable} font-sans antialiased`}
>
<body>
<ThemeProvider>
<ClientProvider>
{children}
</ClientProvider>
</ThemeProvider>
</body>
</html>
)
}If you are using the New Shadcn CLI, Theme Provider is already added. You can skip this step
'use client'
import { useTheme } from 'next-themes'
import { IconMoon, IconSun } from '@tabler/icons-react'
import { Button } from '@/components/ui/button'
export function ThemeSwitcher({ variant = 'outline' }: { variant?: 'outline' | 'ghost' }) {
const { resolvedTheme, setTheme } = useTheme()
return (
<Button
aria-label={`Switch to ${resolvedTheme}` === 'light' ? 'dark' : 'light' + 'mode'}
onPress={() => setTheme(resolvedTheme === 'light' ? 'dark' : 'light')}
size='icon'
variant={variant}
>
<IconSun aria-hidden className='rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0' />
<IconMoon aria-hidden className='absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100' />
</Button>
)
}