From 3573879b885773bae0fc80147f12d89e6c3a3a0d Mon Sep 17 00:00:00 2001 From: Ben Orloff <99829882+benorloff@users.noreply.github.com> Date: Fri, 19 Apr 2024 19:16:22 -0700 Subject: [PATCH] hover grid --- README.md | 37 +---- app/blocks/hover-grid/page.tsx | 196 ++++++++++++++++++++++++ app/layout.tsx | 20 ++- components/grid.tsx | 58 +++++++ components/hover-grid.tsx | 136 ++++++++++++++++ components/providers/theme-provider.tsx | 9 ++ components/site-header.tsx | 12 ++ components/theme-toggle.tsx | 23 +++ package-lock.json | 29 ++++ package.json | 1 + styles/globals.css | 105 ++++++------- tailwind.config.cjs | 4 +- 12 files changed, 533 insertions(+), 97 deletions(-) create mode 100644 app/blocks/hover-grid/page.tsx create mode 100644 components/grid.tsx create mode 100644 components/hover-grid.tsx create mode 100644 components/providers/theme-provider.tsx create mode 100644 components/site-header.tsx create mode 100644 components/theme-toggle.tsx diff --git a/README.md b/README.md index c403366..dfb2532 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,7 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +## UI Component Library -## Getting Started +This is a component library built on top of shadcn/ui, which utilizes radix ui primitives and TailwindCSS. It includes all of the available components from shadcn/ui, as well as several ready-made "block" components that are extensible and composable. -First, run the development server: +This repository is intended to serve as a centralized source for components that I use across my projects and I will be adding new "blocks" over time as they are developed. -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +Storybook is used for component testing and documentation. diff --git a/app/blocks/hover-grid/page.tsx b/app/blocks/hover-grid/page.tsx new file mode 100644 index 0000000..c204a9a --- /dev/null +++ b/app/blocks/hover-grid/page.tsx @@ -0,0 +1,196 @@ +import { Grid, GridCell } from "@/components/grid"; +import { HoverGrid, HoverGridCell, HoverGridContent, HoverGridDescription, HoverGridFooter, HoverGridHeader, HoverGridLeader, HoverGridTitle } from "@/components/hover-grid"; +import { ArrowUpRight } from "lucide-react"; +import { Code } from "bright"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator } from "@/components/ui/breadcrumb"; + +const HoverGridCode = +`import { + HoverGrid, + HoverGridCell, + HoverGridContent, + HoverGridDescription, + HoverGridFooter, + HoverGridHeader, + HoverGridLeader, + HoverGridTitle +} from "@/components/hover-grid"; + +export const HoverGridDemo = () => { + return ( + + + + + Leader1 + + + + + Lorem ipsum. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam. + + + Footer 1 + + + + + Leader1 + + + + + Lorem ipsum. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam. + + + Footer 1 + + + + + Leader1 + + + + + Lorem ipsum. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam. + + + Footer 1 + + + ) +}` + +const HoverGridPage = () => { + return ( +
+
+ + + + Docs + + + + Components + + + +

HoverGrid

+
+
+ + + Preview + Code + + + + + + + Leader1 + + + + + Lorem ipsum. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam. + + + Footer 1 + + + + + Leader1 + + + + + Lorem ipsum. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam. + + + Footer 1 + + + + + Leader1 + + + + + Lorem ipsum. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam. + + + Footer 1 + + + + + + {HoverGridCode} + + + +
+
+ ) +} + +export default HoverGridPage; \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 70c60b2..7e4b7be 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,6 +1,9 @@ import type { Metadata } from "next"; import { Inter } from "next/font/google"; import "@/styles/globals.css"; +import { cn } from "@/lib/utils"; +import { ThemeProvider } from "@/components/providers/theme-provider"; +import { SiteHeader } from "@/components/site-header"; const inter = Inter({ subsets: ["latin"] }); @@ -16,7 +19,22 @@ export default function RootLayout({ }>) { return ( - {children} + + + + {children} + + ); } diff --git a/components/grid.tsx b/components/grid.tsx new file mode 100644 index 0000000..97ec9bc --- /dev/null +++ b/components/grid.tsx @@ -0,0 +1,58 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; +import { cva } from "class-variance-authority"; + +const gridVariants = cva( + "grid divide-x divide-y w-full", + { + variants: { + columns: { + 1: "grid-cols-1", + 2: "grid-cols-2", + 3: "grid-cols-3", + 4: "grid-cols-4", + 5: "grid-cols-5", + 6: "grid-cols-6", + 7: "grid-cols-7", + 8: "grid-cols-8", + 9: "grid-cols-9", + 10: "grid-cols-10", + }, + }, + defaultVariants: { + columns: 3, + }, + } +); + +const Grid = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+
+
+)); +Grid.displayName = "Grid"; + +const GridCell = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +GridCell.displayName = "GridCell"; + +export { + Grid, + GridCell, +}; \ No newline at end of file diff --git a/components/hover-grid.tsx b/components/hover-grid.tsx new file mode 100644 index 0000000..d5c4ce4 --- /dev/null +++ b/components/hover-grid.tsx @@ -0,0 +1,136 @@ +import { cn } from "@/lib/utils"; +import { ArrowUpRight } from "lucide-react" +import React from "react"; + +interface HoverCardProp { + href?: string; + icon?: React.ReactNode; + leader?: string; + title?: string; + description?: string; + className?: string; +} + +interface HoverCardsProps { + columns?: number; + serializedLeaders?: boolean; + +} + +const HoverGrid = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props}, ref) => ( +
+ +)); +HoverGrid.displayName = "HoverGrid"; + +const HoverGridCell = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +HoverGridCell.displayName = "HoverGridCell"; + +const HoverGridHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +HoverGridHeader.displayName = "HoverGridHeader"; + +const HoverGridLeader = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, children, ...props }, ref) => ( +
+ {children} +
+)); +HoverGridLeader.displayName = "HoverGridLeader"; + +const HoverGridContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +HoverGridContent.displayName = "HoverGridContent"; + +const HoverGridTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +HoverGridTitle.displayName = "HoverGridTitle"; + +const HoverGridDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +HoverGridDescription.displayName = "HoverGridDescription"; + +const HoverGridFooter = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +HoverGridFooter.displayName = "HoverGridFooter"; + + +export { + HoverGrid, + HoverGridCell, + HoverGridHeader, + HoverGridLeader, + HoverGridContent, + HoverGridTitle, + HoverGridDescription, + HoverGridFooter, +}; \ No newline at end of file diff --git a/components/providers/theme-provider.tsx b/components/providers/theme-provider.tsx new file mode 100644 index 0000000..8c90fbc --- /dev/null +++ b/components/providers/theme-provider.tsx @@ -0,0 +1,9 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider } from "next-themes" +import { type ThemeProviderProps } from "next-themes/dist/types" + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children} +} diff --git a/components/site-header.tsx b/components/site-header.tsx new file mode 100644 index 0000000..01a7f4a --- /dev/null +++ b/components/site-header.tsx @@ -0,0 +1,12 @@ +import { ThemeToggle } from "@/components/theme-toggle" + +export const SiteHeader = () => { + return ( +

+
+
UI Library
+ +
+
+ ) +} \ No newline at end of file diff --git a/components/theme-toggle.tsx b/components/theme-toggle.tsx new file mode 100644 index 0000000..b37177c --- /dev/null +++ b/components/theme-toggle.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Moon, Sun } from "lucide-react" +import { useTheme } from "next-themes" + +import { Button } from "@/components/ui/button" + +export function ThemeToggle() { + const { setTheme, theme } = useTheme() + + return ( + + ) +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 34b4258..0b6617f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toggle-group": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", + "bright": "^0.8.5", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "cmdk": "^1.0.0", @@ -2391,6 +2392,14 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/@code-hike/lighter": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@code-hike/lighter/-/lighter-0.8.1.tgz", + "integrity": "sha512-St4rPmB7C2EWmAK1sAbvD3lZeM7UDInVDMjQDzEDsu4Q3B3AqF25vXedQK51U0UO0MCOASgBBdTiNwvJAfIqMQ==", + "funding": { + "url": "https://github.com/code-hike/lighter?sponsor=1" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -8092,6 +8101,21 @@ "node": ">=8" } }, + "node_modules/bright": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/bright/-/bright-0.8.5.tgz", + "integrity": "sha512-LOhh3jk8KLFMqhX67TSGP1kCb3qGXbiRLbyBToVOfrrrEa3omXHT44r0/L4/OOlKluaFcO7+11KLOM5xI50XvA==", + "dependencies": { + "@code-hike/lighter": "0.8.1", + "server-only": "^0.0.1" + }, + "funding": { + "url": "https://github.com/code-hike/bright?sponsor=1" + }, + "peerDependencies": { + "react": "^18" + } + }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -16098,6 +16122,11 @@ "node": ">= 0.8.0" } }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", diff --git a/package.json b/package.json index a5d5306..dd191ce 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toggle-group": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", + "bright": "^0.8.5", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "cmdk": "^1.0.0", diff --git a/styles/globals.css b/styles/globals.css index c51c2ba..0f07efd 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -2,69 +2,52 @@ @tailwind components; @tailwind utilities; - @layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; - - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; - - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; - - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; - - --radius: 0.5rem; - } - - .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; - - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; - - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; - - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; - - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; - - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; - - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; - - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 72.22% 50.59%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 5% 64.9%; + --radius: 0.5rem; + } - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 212.7 26.8% 83.9%; - } + .dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 85.7% 97.3%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; } +} @layer base { * { diff --git a/tailwind.config.cjs b/tailwind.config.cjs index 2e7ea94..95f6194 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -3,10 +3,10 @@ module.exports = { darkMode: ["class"], content: [ - './pages/**/*.{ts,tsx}', './components/**/*.{ts,tsx}', './app/**/*.{ts,tsx}', - './src/**/*.{ts,tsx}', + './stories/**/*.{ts,tsx}', + './storybook/**/*.{ts,tsx}', ], prefix: "", theme: {