mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-24 06:17:54 +00:00
fix(mobile): comprehensive mobile UI redesign for better UX
- Header: icon-only wallet button on mobile, fix hamburger overflow - Dashboard: responsive tabs with flex-wrap and smaller text - Citizens: responsive ID card layout, stack NFT badges on mobile - BeCitizen: stack header buttons vertically on mobile - GovernanceInterface: add scrollable tabs - DEXDashboard: responsive admin buttons grid (2 cols on mobile) - P2PDashboard: responsive header and scrollable tabs - Dialog: mobile-first sizing with proper padding and max-height - Tabs UI: base responsive classes for all tab components - Add xs:480px breakpoint and scrollbar-hide utility - Fix vite polyfills config to prevent initialization errors
This commit is contained in:
@@ -72,11 +72,11 @@ const AppLayout: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{/* Mobile: Wallet + Hamburger */}
|
||||
<div className="flex lg:hidden items-center gap-2 w-full justify-end">
|
||||
<div className="flex lg:hidden items-center gap-2 ml-auto">
|
||||
<PezkuwiWalletButton />
|
||||
<button
|
||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||
className="p-2 rounded-lg text-gray-400 hover:text-white hover:bg-gray-800 transition-colors"
|
||||
className="p-2 rounded-lg text-gray-400 hover:text-white hover:bg-gray-800 transition-colors flex-shrink-0"
|
||||
>
|
||||
{mobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
||||
</button>
|
||||
|
||||
@@ -26,7 +26,7 @@ const GovernanceInterface: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
||||
<TabsList className="grid grid-cols-3 lg:grid-cols-6 gap-2 bg-gray-900/50 p-1 rounded-lg">
|
||||
<TabsList className="grid grid-cols-3 lg:grid-cols-6 gap-2 bg-gray-900/50 p-1 rounded-lg overflow-x-auto scrollbar-hide">
|
||||
<TabsTrigger value="overview" className="flex items-center space-x-2">
|
||||
<TrendingUp className="w-4 h-4" />
|
||||
<span>Overview</span>
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from '@/components/ui/dialog';
|
||||
import { Wallet, Check, ExternalLink, Copy, LogOut } from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { useIsMobile } from '@/hooks/use-mobile';
|
||||
|
||||
export const PezkuwiWalletButton: React.FC = () => {
|
||||
const {
|
||||
@@ -24,6 +25,7 @@ export const PezkuwiWalletButton: React.FC = () => {
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { toast } = useToast();
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const handleConnect = async () => {
|
||||
await connectWallet();
|
||||
@@ -70,12 +72,17 @@ export const PezkuwiWalletButton: React.FC = () => {
|
||||
variant="outline"
|
||||
className="bg-green-500/20 border-green-500/50 text-green-400 hover:bg-green-500/30"
|
||||
onClick={() => setIsOpen(true)}
|
||||
size={isMobile ? "icon" : "default"}
|
||||
>
|
||||
<Wallet className="w-4 h-4 mr-2" />
|
||||
{selectedAccount.meta.name || 'Account'}
|
||||
<Badge className="ml-2 bg-green-500/30 text-green-300 border-0">
|
||||
{formatAddress(selectedAccount.address)}
|
||||
</Badge>
|
||||
<Wallet className={isMobile ? "w-4 h-4" : "w-4 h-4 mr-2"} />
|
||||
{!isMobile && (
|
||||
<>
|
||||
{selectedAccount.meta.name || 'Account'}
|
||||
<Badge className="ml-2 bg-green-500/30 text-green-300 border-0">
|
||||
{formatAddress(selectedAccount.address)}
|
||||
</Badge>
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -169,9 +176,10 @@ export const PezkuwiWalletButton: React.FC = () => {
|
||||
<Button
|
||||
onClick={handleConnect}
|
||||
className="bg-gradient-to-r from-green-600 to-yellow-400 hover:from-green-700 hover:to-yellow-500 text-white"
|
||||
size={isMobile ? "icon" : "default"}
|
||||
>
|
||||
<Wallet className="w-4 h-4 mr-2" />
|
||||
Connect Wallet
|
||||
<Wallet className={isMobile ? "w-4 h-4" : "w-4 h-4 mr-2"} />
|
||||
{!isMobile && "Connect Wallet"}
|
||||
</Button>
|
||||
|
||||
{error && error.includes('not found') && (
|
||||
|
||||
@@ -137,7 +137,7 @@ export const DEXDashboard: React.FC = () => {
|
||||
<p className="text-gray-400 mb-6">
|
||||
Mint wrapped tokens for testing and liquidity provision
|
||||
</p>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
|
||||
<button
|
||||
onClick={() => setShowInitializeUsdtModal(true)}
|
||||
className="flex items-center justify-center gap-2 px-4 py-3 bg-green-600 hover:bg-green-700 text-white rounded-lg transition-colors font-medium"
|
||||
|
||||
@@ -82,7 +82,7 @@ export function P2PDashboard() {
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8 max-w-7xl">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 mb-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => navigate('/')}
|
||||
@@ -91,7 +91,7 @@ export function P2PDashboard() {
|
||||
<Home className="w-4 h-4 mr-2" />
|
||||
Back to Home
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<NotificationBell />
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -168,12 +168,12 @@ export function P2PDashboard() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-8">
|
||||
<div>
|
||||
<h1 className="text-4xl font-bold text-white">P2P Trading</h1>
|
||||
<p className="text-gray-400">Buy and sell crypto with your local currency.</p>
|
||||
<h1 className="text-3xl sm:text-4xl font-bold text-white">P2P Trading</h1>
|
||||
<p className="text-gray-400 text-sm sm:text-base">Buy and sell crypto with your local currency.</p>
|
||||
</div>
|
||||
<Button onClick={() => setShowCreateAd(true)}>
|
||||
<Button onClick={() => setShowCreateAd(true)} className="w-full sm:w-auto">
|
||||
<PlusCircle className="w-4 h-4 mr-2" />
|
||||
Post a New Ad
|
||||
</Button>
|
||||
@@ -187,17 +187,17 @@ export function P2PDashboard() {
|
||||
<QuickFilterBar filters={filters} onFiltersChange={setFilters} />
|
||||
|
||||
<Tabs defaultValue="buy">
|
||||
<TabsList className="grid w-full grid-cols-5">
|
||||
<TabsTrigger value="express" className="flex items-center gap-1">
|
||||
<TabsList className="grid w-full grid-cols-5 overflow-x-auto scrollbar-hide">
|
||||
<TabsTrigger value="express" className="flex items-center gap-1 text-xs sm:text-sm px-1 sm:px-3">
|
||||
<Zap className="w-3 h-3" />
|
||||
Express
|
||||
<span className="hidden xs:inline">Express</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="buy">Buy</TabsTrigger>
|
||||
<TabsTrigger value="sell">Sell</TabsTrigger>
|
||||
<TabsTrigger value="my-ads">My Ads</TabsTrigger>
|
||||
<TabsTrigger value="otc" className="flex items-center gap-1">
|
||||
<TabsTrigger value="buy" className="text-xs sm:text-sm px-1 sm:px-3">Buy</TabsTrigger>
|
||||
<TabsTrigger value="sell" className="text-xs sm:text-sm px-1 sm:px-3">Sell</TabsTrigger>
|
||||
<TabsTrigger value="my-ads" className="text-xs sm:text-sm px-1 sm:px-3">My Ads</TabsTrigger>
|
||||
<TabsTrigger value="otc" className="flex items-center gap-1 text-xs sm:text-sm px-1 sm:px-3">
|
||||
<Blocks className="w-3 h-3" />
|
||||
OTC
|
||||
<span className="hidden xs:inline">OTC</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="express">
|
||||
|
||||
@@ -36,7 +36,7 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border/40 bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-[calc(100vw-2rem)] sm:w-full max-w-lg max-h-[90vh] overflow-y-auto translate-x-[-50%] translate-y-[-50%] gap-4 border border-border/40 bg-background p-4 sm:p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-lg sm:rounded-lg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -12,7 +12,7 @@ const TabsList = React.forwardRef<
|
||||
<TabsPrimitive.List
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex h-10 items-center justify-center rounded-md bg-muted/50 p-1 text-muted-foreground",
|
||||
"inline-flex h-auto min-h-10 items-center justify-center rounded-md bg-muted/50 p-1 text-muted-foreground flex-wrap gap-1",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -27,7 +27,7 @@ const TabsTrigger = React.forwardRef<
|
||||
<TabsPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-primary data-[state=active]:shadow-sm hover:text-foreground",
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-primary data-[state=active]:shadow-sm hover:text-foreground",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
Reference in New Issue
Block a user