Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shadcn inital version #936

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- [ ] Get basic configuration working
- [ ] Update pages
- [ ] Header/footer
- [ ] Home
- [ ] Debug (can be broken down into subtask)
- [ ] Blockexplorer (can be broken down into subtask)
- [ ] Migrate all the main components
- [ ] Address
- [ ] AddressInput (this will require updating InputBase etc)
- [ ] Balance
- [ ] Update meta things like
- [ ] Remove heroicons and use lucide react(comes default with shadcn)
- [ ] transaction toast with shadcn toast
- [ ] modals
2 changes: 1 addition & 1 deletion packages/nextjs/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const ScaffoldEthApp = ({ children }: { children: React.ReactNode }) => {
return (
<html suppressHydrationWarning>
<body>
<ThemeProvider enableSystem>
<ThemeProvider attribute="data-theme" enableSystem>
<ScaffoldEthAppWithProviders>{children}</ScaffoldEthAppWithProviders>
</ThemeProvider>
</body>
Expand Down
21 changes: 21 additions & 0 deletions packages/nextjs/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "styles/globals.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "~~/components",
"utils": "~~/lib/utils",
"ui": "~~/components/ui",
"lib": "~~/lib",
"hooks": "~~/hooks"
}
}

5 changes: 3 additions & 2 deletions packages/nextjs/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const Footer = () => {
return (
<div className="min-h-0 py-5 px-1 mb-11 lg:mb-0">
<div>
<div className="fixed flex justify-between items-center w-full z-10 p-4 bottom-0 left-0 pointer-events-none">
<div className="fixed flex justify-between items-center w-full z-10 p-4 bottom-0 left-0">
<div className="flex flex-col md:flex-row gap-2 pointer-events-auto">
{nativeCurrencyPrice > 0 && (
<div>
Expand All @@ -40,7 +40,8 @@ export const Footer = () => {
</>
)}
</div>
<SwitchTheme className={`pointer-events-auto ${isLocalNetwork ? "self-end md:self-auto" : ""}`} />
{/* Broken switch theme */}
<SwitchTheme />
</div>
</div>
<div className="w-full">
Expand Down
93 changes: 45 additions & 48 deletions packages/nextjs/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
"use client";

import React, { useCallback, useRef, useState } from "react";
import { ReactNode, forwardRef } from "react";
import Image from "next/image";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "./ui/dropdown-menu";
import { Bars3Icon, BugAntIcon } from "@heroicons/react/24/outline";
import { FaucetButton, RainbowKitCustomConnectButton } from "~~/components/scaffold-eth";
import { useOutsideClick } from "~~/hooks/scaffold-eth";

type HeaderMenuLink = {
label: string;
href: string;
icon?: React.ReactNode;
icon?: ReactNode;
};

export const menuLinks: HeaderMenuLink[] = [
Expand All @@ -26,26 +26,40 @@ export const menuLinks: HeaderMenuLink[] = [
},
];

export const HeaderMenuLinks = () => {
type MenuLinkProps = HeaderMenuLink & {
isActive: boolean;
};

const MenuLink = forwardRef<HTMLAnchorElement, MenuLinkProps>(({ href, label, icon, isActive }, ref) => (
<Link
href={href}
passHref
ref={ref}
className={`${
isActive ? "bg-secondary shadow-md" : ""
} hover:bg-secondary hover:shadow-md py-1.5 px-3 text-sm rounded-md grid grid-flow-col`}
>
{icon}
<span>{label}</span>
</Link>
));

MenuLink.displayName = "MenuLink";

export const HeaderMenuLinks = ({ withDropDownMenu }: { withDropDownMenu?: boolean }) => {
const pathname = usePathname();

return (
<>
{menuLinks.map(({ label, href, icon }) => {
const isActive = pathname === href;
return (
<li key={href}>
<Link
href={href}
passHref
className={`${
isActive ? "bg-secondary shadow-md" : ""
} hover:bg-secondary hover:shadow-md focus:!bg-secondary active:!text-neutral py-1.5 px-3 text-sm rounded-full gap-2 grid grid-flow-col`}
>
{icon}
<span>{label}</span>
</Link>
</li>

return withDropDownMenu ? (
<DropdownMenuItem key={href} asChild>
<MenuLink key={href} href={href} label={label} icon={icon} isActive={isActive} />
</DropdownMenuItem>
) : (
<MenuLink key={href} href={href} label={label} icon={icon} isActive={isActive} />
);
})}
</>
Expand All @@ -56,37 +70,20 @@ export const HeaderMenuLinks = () => {
* Site header
*/
export const Header = () => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
const burgerMenuRef = useRef<HTMLDivElement>(null);
useOutsideClick(
burgerMenuRef,
useCallback(() => setIsDrawerOpen(false), []),
);

return (
<div className="sticky lg:static top-0 navbar bg-base-100 min-h-0 flex-shrink-0 justify-between z-20 shadow-md shadow-secondary px-0 sm:px-2">
<div className="navbar-start w-auto lg:w-1/2">
<div className="lg:hidden dropdown" ref={burgerMenuRef}>
<label
tabIndex={0}
className={`ml-1 btn btn-ghost ${isDrawerOpen ? "hover:bg-secondary" : "hover:bg-transparent"}`}
onClick={() => {
setIsDrawerOpen(prevIsOpenState => !prevIsOpenState);
}}
>
<Bars3Icon className="h-1/2" />
</label>
{isDrawerOpen && (
<ul
tabIndex={0}
className="menu menu-compact dropdown-content mt-3 p-2 shadow bg-base-100 rounded-box w-52"
onClick={() => {
setIsDrawerOpen(false);
}}
>
<HeaderMenuLinks />
</ul>
)}
<div className="sticky lg:static top-0 flex items-center p-2 bg-base-100 min-h-0 flex-shrink-0 justify-between z-20 shadow-md shadow-secondary px-0 sm:px-2">
<div className="inline-flex items-start w-auto lg:w-1/2">
<div className="lg:hidden">
<DropdownMenu>
<DropdownMenuTrigger>
<label tabIndex={0} className={`ml-1 btn btn-ghost`}>
<Bars3Icon className="h-1/2" />
</label>
</DropdownMenuTrigger>
<DropdownMenuContent className="m-3 p-2 shadow bg-base-100 rounded-box w-52">
<HeaderMenuLinks withDropDownMenu />
</DropdownMenuContent>
</DropdownMenu>
</div>
<Link href="/" passHref className="hidden lg:flex items-center gap-2 ml-4 mr-6 shrink-0">
<div className="flex relative w-10 h-10">
Expand All @@ -101,7 +98,7 @@ export const Header = () => {
<HeaderMenuLinks />
</ul>
</div>
<div className="navbar-end flex-grow mr-4">
<div className="inline-flex justify-end w-1/2 flex-grow mr-4 space-x-1">
<RainbowKitCustomConnectButton />
<FaucetButton />
</div>
Expand Down
53 changes: 32 additions & 21 deletions packages/nextjs/components/SwitchTheme.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
"use client";

import { useEffect, useState } from "react";
import * as React from "react";
import { Moon, Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { MoonIcon, SunIcon } from "@heroicons/react/24/outline";
import { Button } from "~~/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "~~/components/ui/dropdown-menu";

export const SwitchTheme = ({ className }: { className?: string }) => {
const { setTheme, resolvedTheme } = useTheme();
export function SwitchTheme() {
const { setTheme } = useTheme();

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme("light")}>Light</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}>Dark</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>System</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

/* const { setTheme, resolvedTheme } = useTheme();
const [mounted, setMounted] = useState(false);

const isDarkMode = resolvedTheme === "dark";
Expand All @@ -23,20 +50,4 @@ export const SwitchTheme = ({ className }: { className?: string }) => {
}, []);

if (!mounted) return null;

return (
<div className={`flex space-x-2 h-8 items-center justify-center text-sm ${className}`}>
<input
id="theme-toggle"
type="checkbox"
className="toggle toggle-primary bg-primary hover:bg-primary border-primary"
onChange={handleToggle}
checked={isDarkMode}
/>
<label htmlFor="theme-toggle" className={`swap swap-rotate ${!isDarkMode ? "swap-active" : ""}`}>
<SunIcon className="swap-on h-5 w-5" />
<MoonIcon className="swap-off h-5 w-5" />
</label>
</div>
);
};
*/
34 changes: 17 additions & 17 deletions packages/nextjs/components/scaffold-eth/FaucetButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { createWalletClient, http, parseEther } from "viem";
import { hardhat } from "viem/chains";
import { useAccount } from "wagmi";
import { BanknotesIcon } from "@heroicons/react/24/outline";
import { Button } from "~~/components/ui/button";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~~/components/ui/tooltip";
import { useTransactor } from "~~/hooks/scaffold-eth";
import { useWatchBalance } from "~~/hooks/scaffold-eth/useWatchBalance";

Expand Down Expand Up @@ -50,24 +52,22 @@ export const FaucetButton = () => {
return null;
}

const isBalanceZero = balance && balance.value === 0n;
const isBalanceZero = Boolean(balance && balance.value === 0n);

return (
<div
className={
!isBalanceZero
? "ml-1"
: "ml-1 tooltip tooltip-bottom tooltip-secondary tooltip-open font-bold before:left-auto before:transform-none before:content-[attr(data-tip)] before:right-0"
}
data-tip="Grab funds from faucet"
>
<button className="btn btn-secondary btn-sm px-2 rounded-full" onClick={sendETH} disabled={loading}>
{!loading ? (
<BanknotesIcon className="h-4 w-4" />
) : (
<span className="loading loading-spinner loading-xs"></span>
)}
</button>
</div>
<TooltipProvider delayDuration={0}>
<Tooltip open={isBalanceZero}>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" className="h-8" onClick={sendETH} disabled={loading}>
{!loading ? (
<BanknotesIcon className="h-4 w-4" />
) : (
<span className="loading loading-spinner loading-xs"></span>
)}
</Button>
</TooltipTrigger>
<TooltipContent align="end">Grab funds from faucet</TooltipContent>
</Tooltip>
</TooltipProvider>
);
};
Loading
Loading