├── .eslintrc.json ├── .gitignore ├── .prettierrc ├── README.md ├── app ├── (mdx) │ ├── layout.tsx │ └── start │ │ └── page.mdx ├── api │ └── subscribe │ │ └── route.ts ├── cta │ └── page.tsx ├── faq │ └── page.tsx ├── favicon.ico ├── feature │ └── page.tsx ├── footer │ └── page.tsx ├── globals.css ├── header │ └── page.tsx ├── hero │ └── page.tsx ├── layout.tsx ├── opengraph-image.jpg ├── page.tsx ├── play │ └── page.tsx ├── pricing │ └── page.tsx ├── robots.txt ├── sitemap.ts └── twitter-image.jpg ├── components.json ├── components ├── backgrounds.tsx ├── copy-link.tsx ├── copy.tsx ├── craft.tsx ├── ctas │ ├── cta-four.tsx │ ├── cta-one.tsx │ ├── cta-three.tsx │ └── cta-two.tsx ├── email-form.tsx ├── end.tsx ├── faqs │ ├── faqs-one.tsx │ └── faqs-two.tsx ├── features │ ├── feature-eight.tsx │ ├── feature-five.tsx │ ├── feature-four.tsx │ ├── feature-nine.tsx │ ├── feature-one.tsx │ ├── feature-seven.tsx │ ├── feature-six.tsx │ ├── feature-three.tsx │ └── feature-two.tsx ├── footers │ ├── footer-five.tsx │ ├── footer-four.tsx │ ├── footer-one.tsx │ ├── footer-three.tsx │ └── footer-two.tsx ├── headers │ ├── header-one.tsx │ └── header-two.tsx ├── heros │ ├── hero-five.tsx │ ├── hero-four.tsx │ ├── hero-one.tsx │ ├── hero-six.tsx │ ├── hero-three.tsx │ └── hero-two.tsx ├── info.tsx ├── nav-links.tsx ├── nav.tsx ├── pricing │ ├── pricing-four.tsx │ ├── pricing-one.tsx │ ├── pricing-three.tsx │ └── pricing-two.tsx ├── site │ └── theme │ │ ├── theme-provider.tsx │ │ └── theme-toggle.tsx ├── type-button.tsx ├── ui │ ├── accordion.tsx │ ├── alert-dialog.tsx │ ├── alert.tsx │ ├── aspect-ratio.tsx │ ├── avatar.tsx │ ├── badge.tsx │ ├── breadcrumb.tsx │ ├── button.tsx │ ├── calendar.tsx │ ├── card.tsx │ ├── carousel.tsx │ ├── chart.tsx │ ├── checkbox.tsx │ ├── collapsible.tsx │ ├── command.tsx │ ├── context-menu.tsx │ ├── dialog.tsx │ ├── drawer.tsx │ ├── dropdown-menu.tsx │ ├── form.tsx │ ├── hover-card.tsx │ ├── input-otp.tsx │ ├── input.tsx │ ├── label.tsx │ ├── menubar.tsx │ ├── navigation-menu.tsx │ ├── pagination.tsx │ ├── popover.tsx │ ├── progress.tsx │ ├── radio-group.tsx │ ├── resizable.tsx │ ├── scroll-area.tsx │ ├── select.tsx │ ├── separator.tsx │ ├── sheet.tsx │ ├── sidebar.tsx │ ├── skeleton.tsx │ ├── slider.tsx │ ├── sonner.tsx │ ├── switch.tsx │ ├── table.tsx │ ├── tabs.tsx │ ├── textarea.tsx │ ├── toast.tsx │ ├── toaster.tsx │ ├── toggle-group.tsx │ ├── toggle.tsx │ ├── tooltip.tsx │ └── use-toast.ts ├── view-code.tsx └── wrapper.tsx ├── hooks └── use-mobile.tsx ├── lib ├── types.d.ts └── utils.ts ├── mdx-components.tsx ├── next.config.js ├── package-lock.json ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public ├── logo.svg └── placeholder.jpg ├── registry.ts ├── tailwind.config.ts ├── tsconfig.json └── webpack.config.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "prettier-plugin-tailwindcss" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # brijr/components 2 | 3 | [components.work](https://components.work) 4 | 5 | > A collection of [Next.js](https://nextjs.org) components for building websites at rapid speed using [Tailwind](https://tailwindcss.com), [React](https://react.dev), [shadcn/ui](https://ui.shadcn.com), [brijr/craft](https://github.com/brijr/craft), and [Typescript](https://www.typescriptlang.org/). 6 | 7 | ## What is it? 8 | 9 | ![components](https://github.com/brijr/components/assets/57158102/a1246578-4837-4704-94d8-1b01703a850b) 10 | 11 | Open source collection of type-safe React components styled with Tailwind for building Next.js websites. Created by [Bridger Tower](https://bridger.to). 12 | 13 | ## Setup 14 | 15 | > Want to use a starter? Go here 🔗 [brijr/starter](https://github.com/brijr/starter) 16 | 17 | ### Step 1: Create a Next.js application 18 | 19 | ``` 20 | npx create-next-app@latest my-app --typescript --tailwind --eslint 21 | ``` 22 | 23 | ### Step 2: Install [craft-ds](https://github.com/brijr/craft) (this will also install shadcn/ui) 24 | 25 | ``` 26 | npx craft-ds@latest init 27 | ``` 28 | 29 | - Add a `ThemeProvider` and `ModeToggle` (if you want dark mode) by following these steps: [Adding dark mode to your next app](https://ui.shadcn.com/docs/dark-mode/next) 30 | 31 | ### Step 3: Copy and Paste components from the [website](htpps://components.work) into your component folder to get started! 32 | 33 | ## brijr/components in use 34 | 35 | [![Watch the video](https://img.youtube.com/vi/s-cb_7Kyupg/sddefault.jpg)](https://www.youtube.com/watch?v=s-cb_7Kyupg) 36 | 37 | [![Watch the video](https://img.youtube.com/vi/PjSfcq3p2jY/sddefault.jpg)](https://www.youtube.com/watch?v=PjSfcq3p2jY) 38 | -------------------------------------------------------------------------------- /app/(mdx)/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Main, Section, Container } from "@/components/craft"; 2 | 3 | export default function Layout({ 4 | children, 5 | }: Readonly<{ 6 | children: React.ReactNode; 7 | }>) { 8 | return ( 9 |
10 |
11 | {children} 12 |
13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /app/(mdx)/start/page.mdx: -------------------------------------------------------------------------------- 1 | import { Button } from "@/components/ui/button"; 2 | import Link from "next/link"; 3 | 4 | 5 | 8 | 9 | 10 | ### How to set up brijr/components 11 | 12 | Want to use a starter? Check out the [brijr/starter](https://github.com/brijr/starter) 13 | 14 | --- 15 | 16 | #### Step 1: Create a Next.js application 17 | 18 | ``` 19 | npx create-next-app@latest my-app --typescript --tailwind --eslint 20 | ``` 21 | 22 | #### Step 2: Install [craft-ds](https://github.com/brijr/craft) (this will also install shadcn/ui) 23 | 24 | ``` 25 | npx craft-ds@latest init 26 | ``` 27 | 28 | - (if you want dark mode) Add a `ThemeProvider` and `ModeToggle` by following these steps: [Adding dark mode to your next app](https://ui.shadcn.com/docs/dark-mode/next) 29 | 30 | #### Step 3: Copy and Paste components from the [homepage](/) into your component folder to get started! 31 | -------------------------------------------------------------------------------- /app/api/subscribe/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | const LOOPS_API_KEY = process.env.LOOPS_API_KEY; 4 | 5 | export async function POST(request: Request) { 6 | try { 7 | const { email, source, userGroup } = await request.json(); 8 | 9 | if (!email) { 10 | return NextResponse.json({ error: "Email is required" }, { status: 400 }); 11 | } 12 | 13 | if (!LOOPS_API_KEY) { 14 | console.error("LOOPS_API_KEY environment variable is not set"); 15 | return NextResponse.json( 16 | { error: "API configuration error" }, 17 | { status: 500 }, 18 | ); 19 | } 20 | 21 | const response = await fetch( 22 | "https://app.loops.so/api/v1/contacts/create", 23 | { 24 | method: "POST", 25 | headers: { 26 | Authorization: `Bearer ${LOOPS_API_KEY}`, 27 | "Content-Type": "application/json", 28 | }, 29 | body: JSON.stringify({ email, source, userGroup }), 30 | }, 31 | ); 32 | 33 | if (!response.ok) { 34 | const errorData = await response.text(); 35 | console.error("Loops API error:", errorData); 36 | throw new Error(`Failed to create contact in Loops: ${errorData}`); 37 | } 38 | 39 | const data = await response.json(); 40 | 41 | return NextResponse.json({ success: true, id: data.id }, { status: 201 }); 42 | } catch (error) { 43 | console.error("Error in subscribe API:", error); 44 | return NextResponse.json( 45 | { error: "Internal Server Error" }, 46 | { status: 500 }, 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/cta/page.tsx: -------------------------------------------------------------------------------- 1 | // Layout Imports 2 | import { Main } from "@/components/craft"; 3 | import { End } from "@/components/end"; 4 | import { Wrapper } from "@/components/wrapper"; 5 | import { Info } from "@/components/info"; 6 | import * as Craft from "@/components/craft"; 7 | 8 | // Component Config 9 | import { components, types } from "@/registry"; 10 | 11 | export default function Home() { 12 | return ( 13 |
14 | 15 | 16 | {components 17 | .filter((component) => component.type === "cta") 18 | .map((component) => ( 19 | 25 | 26 | 27 | ))} 28 | 29 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /app/faq/page.tsx: -------------------------------------------------------------------------------- 1 | // Layout Imports 2 | import { Main } from "@/components/craft"; 3 | import { End } from "@/components/end"; 4 | import { Wrapper } from "@/components/wrapper"; 5 | import { Info } from "@/components/info"; 6 | import * as Craft from "@/components/craft"; 7 | 8 | // Component Config 9 | import { components, types } from "@/registry"; 10 | 11 | export default function Home() { 12 | return ( 13 |
14 | 15 | 16 | {components 17 | .filter((component) => component.type === "faq") 18 | .map((component) => ( 19 | 25 | 26 | 27 | ))} 28 | 29 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brijr/components/df5867169b8d746b622b20aa50f0a64bfc7df826/app/favicon.ico -------------------------------------------------------------------------------- /app/feature/page.tsx: -------------------------------------------------------------------------------- 1 | // Layout Imports 2 | import { Main } from "@/components/craft"; 3 | import { End } from "@/components/end"; 4 | import { Wrapper } from "@/components/wrapper"; 5 | import { Info } from "@/components/info"; 6 | import * as Craft from "@/components/craft"; 7 | 8 | // Component Config 9 | import { components, types } from "@/registry"; 10 | 11 | export default function Home() { 12 | return ( 13 |
14 | 15 | 16 | {components 17 | .filter((component) => component.type === "feature") 18 | .map((component) => ( 19 | 25 | 26 | 27 | ))} 28 | 29 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /app/footer/page.tsx: -------------------------------------------------------------------------------- 1 | // Layout Imports 2 | import { Main } from "@/components/craft"; 3 | import { End } from "@/components/end"; 4 | import { Wrapper } from "@/components/wrapper"; 5 | import { Info } from "@/components/info"; 6 | import * as Craft from "@/components/craft"; 7 | 8 | // Component Config 9 | import { components, types } from "@/registry"; 10 | 11 | export default function Home() { 12 | return ( 13 |
14 | 15 | 16 | {components 17 | .filter((component) => component.type === "footer") 18 | .map((component) => ( 19 | 25 | 26 | 27 | ))} 28 | 29 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | :root { 7 | --background: 0 0% 100%; 8 | --foreground: 0 0% 3.9%; 9 | 10 | --card: 0 0% 100%; 11 | --card-foreground: 0 0% 3.9%; 12 | 13 | --popover: 0 0% 100%; 14 | --popover-foreground: 0 0% 3.9%; 15 | 16 | --primary: 0 0% 9%; 17 | --primary-foreground: 0 0% 98%; 18 | 19 | --secondary: 0 0% 96.1%; 20 | --secondary-foreground: 0 0% 9%; 21 | 22 | --muted: 0 0% 96.1%; 23 | --muted-foreground: 0 0% 45.1%; 24 | 25 | --accent: 0 0% 96.1%; 26 | --accent-foreground: 0 0% 9%; 27 | 28 | --destructive: 0 84.2% 60.2%; 29 | --destructive-foreground: 0 0% 98%; 30 | 31 | --border: 0 0% 89.8%; 32 | --input: 0 0% 89.8%; 33 | --ring: 0 0% 3.9%; 34 | 35 | --radius: 0.5rem; 36 | 37 | --sidebar-background: 0 0% 98%; 38 | 39 | --sidebar-foreground: 240 5.3% 26.1%; 40 | 41 | --sidebar-primary: 240 5.9% 10%; 42 | 43 | --sidebar-primary-foreground: 0 0% 98%; 44 | 45 | --sidebar-accent: 240 4.8% 95.9%; 46 | 47 | --sidebar-accent-foreground: 240 5.9% 10%; 48 | 49 | --sidebar-border: 220 13% 91%; 50 | 51 | --sidebar-ring: 217.2 91.2% 59.8%; 52 | } 53 | 54 | .dark { 55 | --background: 0 0% 3.9%; 56 | --foreground: 0 0% 98%; 57 | 58 | --card: 0 0% 3.9%; 59 | --card-foreground: 0 0% 98%; 60 | 61 | --popover: 0 0% 3.9%; 62 | --popover-foreground: 0 0% 98%; 63 | 64 | --primary: 0 0% 98%; 65 | --primary-foreground: 0 0% 9%; 66 | 67 | --secondary: 0 0% 14.9%; 68 | --secondary-foreground: 0 0% 98%; 69 | 70 | --muted: 0 0% 14.9%; 71 | --muted-foreground: 0 0% 63.9%; 72 | 73 | --accent: 0 0% 14.9%; 74 | --accent-foreground: 0 0% 98%; 75 | 76 | --destructive: 0 62.8% 30.6%; 77 | --destructive-foreground: 0 0% 98%; 78 | 79 | --border: 0 0% 14.9%; 80 | --input: 0 0% 14.9%; 81 | --ring: 0 0% 83.1%; 82 | --sidebar-background: 240 5.9% 10%; 83 | --sidebar-foreground: 240 4.8% 95.9%; 84 | --sidebar-primary: 224.3 76.3% 48%; 85 | --sidebar-primary-foreground: 0 0% 100%; 86 | --sidebar-accent: 240 3.7% 15.9%; 87 | --sidebar-accent-foreground: 240 4.8% 95.9%; 88 | --sidebar-border: 240 3.7% 15.9%; 89 | --sidebar-ring: 217.2 91.2% 59.8%; 90 | } 91 | } 92 | 93 | @layer base { 94 | * { 95 | @apply border-border; 96 | } 97 | 98 | body { 99 | @apply bg-background text-foreground; 100 | } 101 | } 102 | 103 | @layer utilities { 104 | 105 | /* Hide scrollbar for Chrome, Safari and Opera */ 106 | .no-scrollbar::-webkit-scrollbar { 107 | display: none; 108 | } 109 | 110 | /* Hide scrollbar for IE, Edge and Firefox */ 111 | .no-scrollbar { 112 | -ms-overflow-style: none; 113 | /* IE and Edge */ 114 | scrollbar-width: none; 115 | /* Firefox */ 116 | } 117 | } 118 | 119 | .fade-in { 120 | -webkit-animation: fade-in-up 1000ms cubic-bezier(0.39, 0.575, 0.565, 1) 200ms both; 121 | animation: fade-in-up 1000ms cubic-bezier(0.39, 0.575, 0.565, 1) 200ms both; 122 | } 123 | 124 | @-webkit-keyframes fade-in-up { 125 | 0% { 126 | opacity: 0; 127 | -webkit-transform: translateY(20px); 128 | transform: translateY(20px); 129 | } 130 | 131 | 100% { 132 | opacity: 1; 133 | -webkit-transform: translateY(0); 134 | transform: translateY(0); 135 | } 136 | } 137 | 138 | @keyframes fade-in-up { 139 | 0% { 140 | opacity: 0; 141 | -webkit-transform: translateY(20px); 142 | transform: translateY(20px); 143 | } 144 | 145 | 100% { 146 | opacity: 1; 147 | -webkit-transform: translateY(0); 148 | transform: translateY(0); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /app/header/page.tsx: -------------------------------------------------------------------------------- 1 | // Layout Imports 2 | import { Main } from "@/components/craft"; 3 | import { End } from "@/components/end"; 4 | import { Wrapper } from "@/components/wrapper"; 5 | import { Info } from "@/components/info"; 6 | import * as Craft from "@/components/craft"; 7 | 8 | // Component Config 9 | import { components, types } from "@/registry"; 10 | 11 | export default function Home() { 12 | return ( 13 |
14 | 15 | 16 | {components 17 | .filter((component) => component.type === "header") 18 | .map((component) => ( 19 | 25 | 26 | 27 | ))} 28 | 29 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /app/hero/page.tsx: -------------------------------------------------------------------------------- 1 | // Layout Imports 2 | import { Main } from "@/components/craft"; 3 | import { End } from "@/components/end"; 4 | import { Wrapper } from "@/components/wrapper"; 5 | import { Info } from "@/components/info"; 6 | import * as Craft from "@/components/craft"; 7 | 8 | // Component Config 9 | import { components, types } from "@/registry"; 10 | 11 | export default function Home() { 12 | return ( 13 |
14 | 15 | 16 | {components 17 | .filter((component) => component.type === "hero") 18 | .map((component) => ( 19 | 25 | 26 | 27 | ))} 28 | 29 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "./globals.css"; 2 | import type { Metadata } from "next"; 3 | import { Manrope } from "next/font/google"; 4 | import { Layout } from "@/components/craft"; 5 | import { Toaster } from "@/components/ui/sonner"; 6 | import { Background } from "@/components/backgrounds"; 7 | import { Analytics } from "@vercel/analytics/react"; 8 | import { ThemeProvider } from "@/components/site/theme/theme-provider"; 9 | import { Nav } from "@/components/nav"; 10 | 11 | const font = Manrope({ subsets: ["latin"] }); 12 | 13 | export const metadata: Metadata = { 14 | metadataBase: new URL("https://components.work"), 15 | title: "Next JS Components for building websites created by Bridger Tower", 16 | description: 17 | "Collection of Typescript React components for Next JS built using Tailwind and shadcn/ui. Created by Bridger Tower.", 18 | }; 19 | 20 | export default function RootLayout({ 21 | children, 22 | }: Readonly<{ 23 | children: React.ReactNode; 24 | }>) { 25 | return ( 26 | 27 | 28 | 34 |