mirror of
https://github.com/luxfi/market.git
synced 2026-09-24 00:25:57 +00:00
refactor(market): one chrome — a wallet is not an account
lux.market had a header of its own: its own sticky bar, its own link styling, a nav with no phone presentation at all, and a Connect button standing in for an account menu the surface did not have. Two identities meet here and they are not the same thing — the WALLET signs a listing, the ACCOUNT is who you are and which org you act in — and only the first existed. The chrome is now `AppNav` from @luxfi/ui: brand, org switcher, links, settings and the user menu, identical to the MPC dashboard and the bootnode console, with the links collapsing into the same gui Sheet the switchers use. The chain selector and the wallet button stay, in the nav's free slot, because those are this surface's own controls and not chrome. Identity comes from IdentityProvider (IAM); brand, theme, issuer and IAM client come from the Host header, so lux.market and a zoo-branded market are one image. The gui engine's bundler wiring comes from `withLuxUi`, not a hand-rolled transpile list. `next build` passes: 6 static routes exported. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
+7
-1
@@ -1,6 +1,12 @@
|
||||
import path from 'path'
|
||||
import type { NextConfig } from 'next'
|
||||
import { withLuxUi } from '@luxfi/ui/next'
|
||||
|
||||
// `withLuxUi` is the ONE place the gui engine's bundler wiring lives — transpile
|
||||
// list, react-native → react-native-web alias in both bundlers, platform
|
||||
// defines. Every Next surface needed the identical incantation; the ones that
|
||||
// hand-rolled it each transpiled a different subset, which is how one app
|
||||
// renders a Sheet and the next throws on the same component.
|
||||
const nextConfig: NextConfig = {
|
||||
output: 'export',
|
||||
outputFileTracingRoot: path.resolve(import.meta.dirname ?? __dirname),
|
||||
@@ -24,4 +30,4 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
}
|
||||
|
||||
export default nextConfig
|
||||
export default withLuxUi(nextConfig as never) as NextConfig
|
||||
|
||||
+9
-6
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@luxfi/market",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"description": "Lux NFT Marketplace - Genesis NFTs, trading, and NFT AMM",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
@@ -12,7 +12,9 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@luxfi/ui": "7.4.0",
|
||||
"@hanzo/gui": "^7.3.0",
|
||||
"@hanzo/iam": "^0.13.8",
|
||||
"@luxfi/ui": "7.4.3",
|
||||
"@radix-ui/react-dialog": "^1.1.0",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.0",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
@@ -22,8 +24,9 @@
|
||||
"lucide-react": "^1.27.0",
|
||||
"next": "15.5.0",
|
||||
"next-themes": "^0.4.0",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-native-web": "^0.21.0",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"viem": "2.43.3",
|
||||
"wagmi": "2.15.5"
|
||||
@@ -31,8 +34,8 @@
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.2.1",
|
||||
"@types/node": "22.13.1",
|
||||
"@types/react": "19.1.5",
|
||||
"@types/react-dom": "19.1.5",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"tailwindcss": "4.1.18",
|
||||
"typescript": "5.8.3"
|
||||
},
|
||||
|
||||
Generated
+1683
-1539
File diff suppressed because it is too large
Load Diff
+54
-105
@@ -1,111 +1,60 @@
|
||||
/*
|
||||
* lux.market rides the canonical Lux token set.
|
||||
*
|
||||
* What it replaced: a hand-rolled shadcn block whose neutrals all carried hue
|
||||
* 240 at up to 10% saturation (--foreground 240 10% 3.9%, --muted 240 3.7%
|
||||
* 15.9%, --ring 240 4.9% 83.9%) — the same cool cast the MPC dashboard had, and
|
||||
* nothing like explore or the bootnode console next to it — plus a literal tan
|
||||
* in BOTH modes: --chart-4 and --warning at hsl(38.3 95.8% 56.7%) = #F9B03D.
|
||||
*
|
||||
* Tokens are hex now, so `hsl(var(--x))` became `var(--x)` and
|
||||
* `hsl(var(--x) / 0.8)` became a color-mix().
|
||||
*/
|
||||
@import "tailwindcss";
|
||||
@import "@luxfi/ui/tokens.css";
|
||||
|
||||
:root {
|
||||
/* Radius is the one non-colour value this app owns. */
|
||||
--radius: 0.75rem;
|
||||
}
|
||||
|
||||
/* Default to dark mode */
|
||||
html {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
/* CSS Variables - Light theme */
|
||||
:root {
|
||||
--radius: 0.75rem;
|
||||
--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 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 5.9% 90%;
|
||||
--input: 240 5.9% 90%;
|
||||
--ring: 240 5.9% 10%;
|
||||
--chart-1: 142.1 76.2% 36.3%;
|
||||
--chart-2: 217.2 91.2% 59.8%;
|
||||
--chart-3: 316.6 73.3% 69.4%;
|
||||
--chart-4: 38.3 95.8% 56.7%;
|
||||
--chart-5: 0 84.2% 60.2%;
|
||||
--success: 142.1 76.2% 36.3%;
|
||||
--success-foreground: 0 0% 98%;
|
||||
--warning: 38.3 95.8% 56.7%;
|
||||
--warning-foreground: 0 0% 0%;
|
||||
--info: 217.2 91.2% 59.8%;
|
||||
--info-foreground: 0 0% 98%;
|
||||
}
|
||||
|
||||
/* Dark theme - Primary for Lux apps */
|
||||
.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 0% 98%;
|
||||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 240 4.9% 83.9%;
|
||||
--chart-1: 142.1 70.6% 45.3%;
|
||||
--chart-2: 217.2 91.2% 59.8%;
|
||||
--chart-3: 316.6 73.3% 52%;
|
||||
--chart-4: 38.3 95.8% 56.7%;
|
||||
--chart-5: 0 84.2% 60.2%;
|
||||
--success: 142.1 70.6% 45.3%;
|
||||
--success-foreground: 0 0% 98%;
|
||||
--warning: 38.3 95.8% 56.7%;
|
||||
--warning-foreground: 0 0% 0%;
|
||||
--info: 217.2 91.2% 59.8%;
|
||||
--info-foreground: 0 0% 98%;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--radius: 0.75rem;
|
||||
--color-background: hsl(var(--background));
|
||||
--color-foreground: hsl(var(--foreground));
|
||||
--color-card: hsl(var(--card));
|
||||
--color-card-foreground: hsl(var(--card-foreground));
|
||||
--color-popover: hsl(var(--popover));
|
||||
--color-popover-foreground: hsl(var(--popover-foreground));
|
||||
--color-primary: hsl(var(--primary));
|
||||
--color-primary-foreground: hsl(var(--primary-foreground));
|
||||
--color-secondary: hsl(var(--secondary));
|
||||
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
||||
--color-muted: hsl(var(--muted));
|
||||
--color-muted-foreground: hsl(var(--muted-foreground));
|
||||
--color-accent: hsl(var(--accent));
|
||||
--color-accent-foreground: hsl(var(--accent-foreground));
|
||||
--color-destructive: hsl(var(--destructive));
|
||||
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
||||
--color-border: hsl(var(--border));
|
||||
--color-input: hsl(var(--input));
|
||||
--color-ring: hsl(var(--ring));
|
||||
--color-success: hsl(var(--success));
|
||||
--color-success-foreground: hsl(var(--success-foreground));
|
||||
--color-warning: hsl(var(--warning));
|
||||
--color-warning-foreground: hsl(var(--warning-foreground));
|
||||
--color-info: hsl(var(--info));
|
||||
--color-info-foreground: hsl(var(--info-foreground));
|
||||
--color-chart-1: hsl(var(--chart-1));
|
||||
--color-chart-2: hsl(var(--chart-2));
|
||||
--color-chart-3: hsl(var(--chart-3));
|
||||
--color-chart-4: hsl(var(--chart-4));
|
||||
--color-chart-5: hsl(var(--chart-5));
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-success: var(--success);
|
||||
--color-success-foreground: var(--success-foreground);
|
||||
--color-warning: var(--warning);
|
||||
--color-warning-foreground: var(--warning-foreground);
|
||||
--color-info: var(--info);
|
||||
--color-info-foreground: var(--info-foreground);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
|
||||
--font-sans: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
|
||||
--font-mono: var(--font-mono, ui-monospace, monospace);
|
||||
@@ -124,7 +73,7 @@ html {
|
||||
}
|
||||
|
||||
* {
|
||||
border-color: hsl(var(--border));
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
html {
|
||||
@@ -133,13 +82,13 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: hsl(var(--background));
|
||||
color: hsl(var(--foreground));
|
||||
background-color: var(--background);
|
||||
color: var(--foreground);
|
||||
font-feature-settings: "rlig" 1, "calt" 1;
|
||||
}
|
||||
|
||||
.glass {
|
||||
background-color: hsl(var(--background) / 0.8);
|
||||
background-color: color-mix(in srgb, var(--background) 80%, transparent);
|
||||
backdrop-filter: blur(24px);
|
||||
}
|
||||
|
||||
@@ -174,5 +123,5 @@ body {
|
||||
|
||||
::-webkit-scrollbar { width: 8px; height: 8px; }
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
::-webkit-scrollbar-thumb { background: hsl(var(--muted)); border-radius: 9999px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: hsl(var(--muted-foreground) / 0.5); }
|
||||
::-webkit-scrollbar-thumb { background: var(--muted); border-radius: 9999px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted-foreground) 50%, transparent); }
|
||||
|
||||
+46
-9
@@ -1,12 +1,26 @@
|
||||
'use client'
|
||||
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { useState, type ReactNode } from 'react'
|
||||
import { configureIam, logout, startLogin } from '@hanzo/iam/browser'
|
||||
import { AppProvider, IdentityProvider } from '@luxfi/ui'
|
||||
import { resolveWhiteLabel } from '@luxfi/ui/white-label'
|
||||
import { QueryClient } from '@tanstack/react-query'
|
||||
import { useEffect, useState, type ReactNode } from 'react'
|
||||
import { WagmiProvider, createConfig, http } from 'wagmi'
|
||||
import { injected } from 'wagmi/connectors'
|
||||
import { ChainContext } from '@/hooks/useChain'
|
||||
import { supportedChains } from '@/lib/chains'
|
||||
|
||||
// Two identities meet on this surface and they are NOT the same thing:
|
||||
//
|
||||
// the WALLET — wagmi, an address, what signs a listing;
|
||||
// the ACCOUNT — IAM, who you are, which org you act in.
|
||||
//
|
||||
// The market had only the first, so its header was a Connect button and there
|
||||
// was no way to tell lux.market from zoo.market except the copy. `AppProvider`
|
||||
// carries the white-label (brand, gui theme, OIDC issuer, IAM client — all from
|
||||
// the Host header) and `IdentityProvider` the account, exactly as every other
|
||||
// Lux surface does. Wallet state stays where it was.
|
||||
|
||||
function createWagmiConfig() {
|
||||
return createConfig({
|
||||
chains: supportedChains,
|
||||
@@ -16,20 +30,43 @@ function createWagmiConfig() {
|
||||
})
|
||||
}
|
||||
|
||||
// Local dev has no brand to resolve from `localhost` — name the host the surface
|
||||
// stands in for. Unset in every deployment, where the real Host header answers.
|
||||
const DEV_HOST = process.env.NEXT_PUBLIC_HOST
|
||||
|
||||
export function Providers({ children }: { children: ReactNode }) {
|
||||
const [chainId, setChainId] = useState(96369)
|
||||
const [config] = useState(() => createWagmiConfig())
|
||||
// ONE query cache for the surface: AppProvider owns the provider, so wagmi
|
||||
// and the chrome share a client instead of running two.
|
||||
const [queryClient] = useState(() => new QueryClient({
|
||||
defaultOptions: { queries: { refetchOnWindowFocus: false, retry: 2, staleTime: 60_000 } },
|
||||
}))
|
||||
const [host, setHost] = useState<string | undefined>(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
const real = window.location.host
|
||||
const local = /^(localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/.test(real)
|
||||
const resolved = local && DEV_HOST ? DEV_HOST : real
|
||||
setHost(resolved)
|
||||
const wl = resolveWhiteLabel(resolved)
|
||||
configureIam({ issuer: wl.issuer, clientId: wl.clientId })
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<WagmiProvider config={config}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ChainContext.Provider value={{ chainId, setChainId }}>
|
||||
{children}
|
||||
</ChainContext.Provider>
|
||||
</QueryClientProvider>
|
||||
</WagmiProvider>
|
||||
<AppProvider host={host} queryClient={queryClient}>
|
||||
<IdentityProvider
|
||||
auth={{
|
||||
signIn: () => void startLogin({ redirect: '/' }),
|
||||
signOut: () => void logout(),
|
||||
}}
|
||||
>
|
||||
<WagmiProvider config={config}>
|
||||
<ChainContext.Provider value={{ chainId, setChainId }}>
|
||||
{children}
|
||||
</ChainContext.Provider>
|
||||
</WagmiProvider>
|
||||
</IdentityProvider>
|
||||
</AppProvider>
|
||||
)
|
||||
}
|
||||
|
||||
+69
-91
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import Link from 'next/link'
|
||||
import { AppNav } from '@luxfi/ui'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { useAccount, useConnect, useDisconnect } from 'wagmi'
|
||||
import { injected } from 'wagmi/connectors'
|
||||
@@ -11,6 +11,15 @@ import { Wallet, LogOut } from 'lucide-react'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { shortenAddress } from '@/lib/utils'
|
||||
|
||||
// The chrome is `AppNav` from @luxfi/ui — brand, org switcher, links, settings
|
||||
// and the user menu, identical to every other Lux surface. What used to be here
|
||||
// was a second header: its own sticky bar, its own link styling, a `flex` nav
|
||||
// with no phone presentation at all, and a wallet control standing in for an
|
||||
// account menu it did not have.
|
||||
//
|
||||
// The chain selector and the wallet button stay, in the nav's free slot: they
|
||||
// are this surface's own controls, not chrome. A wallet is not an account.
|
||||
|
||||
const NAV_LINKS = [
|
||||
{ href: '/', label: 'Explore' },
|
||||
{ href: '/collections', label: 'Collections' },
|
||||
@@ -21,102 +30,71 @@ const NAV_LINKS = [
|
||||
|
||||
const CHAIN_IDS = [96369, 200200, 36963, 36911, 494949]
|
||||
|
||||
export function Header() {
|
||||
const pathname = usePathname()
|
||||
/** Which chain the marketplace reads — a market control, not chrome. */
|
||||
function ChainSelector() {
|
||||
const { chainId, setChainId } = useChainContext()
|
||||
return (
|
||||
<div className="hidden gap-0.5 rounded-lg bg-card p-0.5 sm:flex">
|
||||
{CHAIN_IDS.map((id) => {
|
||||
const info = CHAIN_INFO[id]
|
||||
const isActive = chainId === id
|
||||
return (
|
||||
<button
|
||||
key={id}
|
||||
onClick={() => setChainId(id)}
|
||||
title={info.name}
|
||||
className={cn(
|
||||
'cursor-pointer rounded-md border-none px-2.5 py-1.5 text-xs font-semibold transition-colors',
|
||||
isActive ? 'text-black' : 'bg-transparent text-muted-foreground hover:text-foreground',
|
||||
)}
|
||||
style={isActive ? { background: info.color } : undefined}
|
||||
>
|
||||
{info.name}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/** The wallet that signs listings — distinct from the IAM account above it. */
|
||||
function WalletButton() {
|
||||
const { address, isConnected } = useAccount()
|
||||
const { connect } = useConnect()
|
||||
const { disconnect } = useDisconnect()
|
||||
|
||||
if (!isConnected) {
|
||||
return (
|
||||
<Button variant="connect" size="sm" onClick={() => connect({ connector: injected() })}>
|
||||
<Wallet className="h-4 w-4" />
|
||||
Connect
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<header className="sticky top-0 z-50 flex items-center justify-between px-6 py-3 border-b border-border bg-background/80 backdrop-blur-xl">
|
||||
<div className="flex items-center gap-8">
|
||||
<Link
|
||||
href="/"
|
||||
className="text-lg font-bold tracking-tight text-foreground no-underline"
|
||||
>
|
||||
Lux Market
|
||||
</Link>
|
||||
<nav className="flex gap-1">
|
||||
{NAV_LINKS.map((link) => {
|
||||
const isActive = link.href === '/' ? pathname === '/' : pathname.startsWith(link.href)
|
||||
return (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className={cn(
|
||||
'px-3 py-1.5 rounded-lg text-sm no-underline transition-colors',
|
||||
isActive
|
||||
? 'text-foreground bg-card'
|
||||
: 'text-muted-foreground hover:text-foreground'
|
||||
)}
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono text-sm text-muted-foreground">
|
||||
{address ? shortenAddress(address) : ''}
|
||||
</span>
|
||||
<Button variant="ghost" size="icon" onClick={() => disconnect()} title="Disconnect wallet">
|
||||
<LogOut className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Chain selector */}
|
||||
<div className="flex gap-0.5 bg-card rounded-lg p-0.5">
|
||||
{CHAIN_IDS.map((id) => {
|
||||
const info = CHAIN_INFO[id]
|
||||
const isActive = chainId === id
|
||||
return (
|
||||
<button
|
||||
key={id}
|
||||
onClick={() => setChainId(id)}
|
||||
title={info.name}
|
||||
className={cn(
|
||||
'px-2.5 py-1.5 text-xs font-semibold rounded-md cursor-pointer transition-colors border-none',
|
||||
isActive
|
||||
? 'text-black'
|
||||
: 'text-muted-foreground bg-transparent hover:text-foreground'
|
||||
)}
|
||||
style={isActive ? { background: info.color } : undefined}
|
||||
>
|
||||
{info.name}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<a
|
||||
href="https://exchange.lux.network"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="px-3 py-1.5 text-[13px] text-muted-foreground no-underline border border-border rounded-lg hover:text-foreground transition-colors"
|
||||
>
|
||||
Exchange
|
||||
</a>
|
||||
|
||||
{isConnected ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-mono text-muted-foreground">
|
||||
{address ? shortenAddress(address) : ''}
|
||||
</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => disconnect()}
|
||||
title="Disconnect"
|
||||
>
|
||||
<LogOut className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<Button
|
||||
variant="connect"
|
||||
size="sm"
|
||||
onClick={() => connect({ connector: injected() })}
|
||||
>
|
||||
<Wallet className="h-4 w-4" />
|
||||
Connect
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
export function Header() {
|
||||
const pathname = usePathname()
|
||||
return (
|
||||
<AppNav
|
||||
brand="Lux Market"
|
||||
links={NAV_LINKS.map((l) => ({
|
||||
...l,
|
||||
active: l.href === '/' ? pathname === '/' : pathname.startsWith(l.href),
|
||||
}))}
|
||||
>
|
||||
<ChainSelector />
|
||||
<WalletButton />
|
||||
</AppNav>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user