feat: make app fully mobile-responsive

Update layout, headers, tables, kanban, comms, forms, and modals for mobile.

Co-authored-by: Moheeb Zara <1184415+virgilvox@users.noreply.github.com>
This commit is contained in:
v0
2026-03-11 07:20:17 +00:00
co-authored by Moheeb Zara
parent a6d44f2ddb
commit 1036e1ff5e
11 changed files with 181 additions and 210 deletions
+22 -15
View File
@@ -2,7 +2,7 @@
import { useState, useEffect, useRef } from 'react'
import { createClient } from '@/lib/supabase/client'
import { Hash, Users2, Send } from 'lucide-react'
import { Hash, Users2, Send, ChevronLeft } from 'lucide-react'
interface Props {
member: any
@@ -15,6 +15,7 @@ export default function CommsClient({ member, space, channels }: Props) {
const [messages, setMessages] = useState<any[]>([])
const [newMessage, setNewMessage] = useState('')
const [sending, setSending] = useState(false)
const [showChannelList, setShowChannelList] = useState(true)
const messagesEndRef = useRef<HTMLDivElement>(null)
useEffect(() => {
@@ -140,26 +141,32 @@ export default function CommsClient({ member, space, channels }: Props) {
const projectChannels = channels.filter(c => c.channel_type === 'project')
return (
<div className="h-screen bg-background flex flex-col">
<div className="bg-sidebar px-6 py-3 flex items-center justify-between border-b border-sidebar-border">
<div className="h-[calc(100vh-52px)] md:h-screen bg-background flex flex-col">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center justify-between border-b border-sidebar-border">
<div className="flex items-center gap-3">
<h1 className="text-white font-sans text-lg font-semibold">Comms</h1>
{/* Mobile back to channels */}
{!showChannelList && selectedChannel && (
<button
onClick={() => setShowChannelList(true)}
className="md:hidden text-sidebar-foreground/70 hover:text-sidebar-foreground mr-1"
>
<ChevronLeft className="w-5 h-5" />
</button>
)}
<h1 className="text-white font-sans text-lg font-semibold">
{!showChannelList && selectedChannel ? `#${selectedChannel.name}` : 'Comms'}
</h1>
</div>
<div className="flex items-center gap-2">
<button className="text-sidebar-foreground/70 hover:text-sidebar-foreground text-sm">
<Users2 className="w-4 h-4" />
</button>
<button className="text-sidebar-foreground/70 hover:text-sidebar-foreground text-sm">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</button>
</div>
</div>
<div className="flex-1 flex overflow-hidden">
{/* Channels sidebar */}
<aside className="w-[220px] bg-card border-r border-border overflow-y-auto">
{/* Channels sidebar — hidden on mobile when a channel is selected */}
<aside className={`${showChannelList ? 'flex' : 'hidden'} md:flex w-full md:w-[220px] flex-col bg-card border-r border-border overflow-y-auto`}>
<div className="p-3">
{generalChannels.length > 0 && (
<div className="mb-4">
@@ -167,7 +174,7 @@ export default function CommsClient({ member, space, channels }: Props) {
{generalChannels.map(channel => (
<button
key={channel.id}
onClick={() => setSelectedChannel(channel)}
onClick={() => { setSelectedChannel(channel); setShowChannelList(false) }}
className={`w-full flex items-center gap-2 px-2 py-1.5 rounded text-sm font-sans transition ${
selectedChannel?.id === channel.id
? 'bg-primary/10 text-primary'
@@ -192,7 +199,7 @@ export default function CommsClient({ member, space, channels }: Props) {
{areaChannels.map(channel => (
<button
key={channel.id}
onClick={() => setSelectedChannel(channel)}
onClick={() => { setSelectedChannel(channel); setShowChannelList(false) }}
className={`w-full flex items-center gap-2 px-2 py-1.5 rounded text-sm font-sans transition ${
selectedChannel?.id === channel.id
? 'bg-primary/10 text-primary'
@@ -212,7 +219,7 @@ export default function CommsClient({ member, space, channels }: Props) {
{projectChannels.map(channel => (
<button
key={channel.id}
onClick={() => setSelectedChannel(channel)}
onClick={() => { setSelectedChannel(channel); setShowChannelList(false) }}
className={`w-full flex items-center gap-2 px-2 py-1.5 rounded text-sm font-sans transition ${
selectedChannel?.id === channel.id
? 'bg-primary/10 text-primary'
@@ -232,7 +239,7 @@ export default function CommsClient({ member, space, channels }: Props) {
{/* Main chat area */}
{selectedChannel ? (
<div className="flex-1 flex flex-col overflow-hidden">
<div className={`${showChannelList ? 'hidden md:flex' : 'flex'} flex-1 flex-col overflow-hidden`}>
{/* Channel header */}
<div className="bg-card border-b border-border px-4 py-3 flex items-center gap-2">
<Hash className="w-4 h-4 text-muted-foreground" />
+5 -5
View File
@@ -114,7 +114,7 @@ export function ContactsClient({ contacts: initialContacts }: { contacts: Contac
const ContactForm = ({ onSubmit, submitLabel }: { onSubmit: (e: React.FormEvent) => void, submitLabel: string }) => (
<form onSubmit={onSubmit} className="p-6 space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Name *</label>
<input type="text" required value={form.name} onChange={e => setForm(f => ({ ...f, name: e.target.value }))}
@@ -128,7 +128,7 @@ export function ContactsClient({ contacts: initialContacts }: { contacts: Contac
</select>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Email</label>
<input type="email" value={form.email} onChange={e => setForm(f => ({ ...f, email: e.target.value }))}
@@ -145,7 +145,7 @@ export function ContactsClient({ contacts: initialContacts }: { contacts: Contac
<textarea value={form.details} onChange={e => setForm(f => ({ ...f, details: e.target.value }))}
rows={2} className="w-full bg-background border border-border rounded px-3 py-2 font-sans text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary transition resize-none" />
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Group Label</label>
<input type="text" value={form.group_label} onChange={e => setForm(f => ({ ...f, group_label: e.target.value }))}
@@ -173,7 +173,7 @@ export function ContactsClient({ contacts: initialContacts }: { contacts: Contac
return (
<div className="min-h-screen bg-background">
<div className="bg-sidebar px-6 py-3 flex items-center justify-between">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center justify-between">
<h1 className="text-white font-sans text-lg font-semibold">Contacts</h1>
<button
onClick={() => { resetForm(); setShowCreate(true) }}
@@ -183,7 +183,7 @@ export function ContactsClient({ contacts: initialContacts }: { contacts: Contac
</button>
</div>
<div className="p-6 space-y-4">
<div className="p-4 md:p-6 space-y-4">
<div className="relative">
<svg className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
+7 -6
View File
@@ -61,18 +61,19 @@ export default async function DashboardPage() {
return (
<div className="min-h-screen bg-background">
<div className="bg-sidebar px-6 py-3 flex items-center justify-between">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center justify-between">
<h1 className="text-white font-sans text-lg font-semibold">Dashboard</h1>
<Link href="/tasks" className="flex items-center gap-1.5 bg-primary text-white text-xs font-sans px-3 py-1.5 rounded hover:bg-primary/90 transition">
<IcoPlus className="w-3.5 h-3.5" />
Quick Task
<span className="hidden sm:inline">Quick Task</span>
<span className="sm:hidden">Task</span>
</Link>
</div>
<div className="p-6 space-y-6">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
<div className="p-4 md:p-6 space-y-6">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3 md:gap-4">
{stats.map(({ label, value, Ico, sub, warn }) => (
<div key={label} className="bg-card rounded border border-border p-5">
<div key={label} className="bg-card rounded border border-border p-4 md:p-5">
<p className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase mb-2 flex items-center gap-1.5">
<Ico className="w-3 h-3" /> {label}
</p>
@@ -82,7 +83,7 @@ export default async function DashboardPage() {
))}
</div>
<div className="grid lg:grid-cols-[1fr_300px] gap-6">
<div className="grid lg:grid-cols-[1fr_280px] gap-6">
<div className="space-y-6">
<div>
<div className="flex items-center justify-between mb-3">
+1 -1
View File
@@ -45,7 +45,7 @@ export default async function AppLayout({ children }: { children: React.ReactNod
taskBadge={taskCount ?? 0}
paymentBadge={paymentCount ?? 0}
/>
<main className="flex-1 overflow-y-auto">
<main className="flex-1 overflow-y-auto pt-[52px] md:pt-0">
{children}
</main>
</div>
+12 -10
View File
@@ -129,7 +129,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
const MemberFormFields = () => (
<>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Full Name *</label>
<input type="text" required value={form.display_name} onChange={e => setForm(f => ({ ...f, display_name: e.target.value }))}
@@ -141,7 +141,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
className="w-full bg-background border border-border rounded px-3 py-2 font-sans text-sm text-foreground focus:outline-none focus:border-primary transition" />
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Phone</label>
<input type="tel" value={form.phone} onChange={e => setForm(f => ({ ...f, phone: e.target.value }))}
@@ -153,7 +153,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
className="w-full bg-background border border-border rounded px-3 py-2 font-mono text-sm text-foreground focus:outline-none focus:border-primary transition" />
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Tier</label>
<select value={form.tier} onChange={e => setForm(f => ({ ...f, tier: e.target.value }))}
@@ -175,7 +175,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
</select>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Joined At</label>
<input type="date" value={form.joined_at?.slice(0, 10)} onChange={e => setForm(f => ({ ...f, joined_at: e.target.value }))}
@@ -194,7 +194,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
return (
<div className="min-h-screen bg-background">
<div className="bg-sidebar px-6 py-3 flex items-center justify-between">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center justify-between">
<div className="flex items-center gap-3">
<h1 className="text-white font-sans text-lg font-semibold">Members</h1>
<span className="font-mono text-xs text-white/50">{total} total</span>
@@ -209,7 +209,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
)}
</div>
<div className="bg-card border-b border-border px-6 flex gap-6">
<div className="bg-card border-b border-border px-4 md:px-6 flex gap-4 md:gap-6 overflow-x-auto">
{[
{ key: 'all', label: `All ${total}` },
{ key: 'payment_issues', label: `Payment Issues ${paymentIssues}` },
@@ -228,7 +228,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
))}
</div>
<div className="p-6">
<div className="p-4 md:p-6">
<div className="flex gap-3 mb-4">
<div className="flex-1 relative">
<svg className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -236,7 +236,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
</svg>
<input
type="text"
placeholder="Search by name, email, handle..."
placeholder="Search..."
value={search}
onChange={e => setSearch(e.target.value)}
className="w-full bg-card border border-border rounded pl-9 pr-4 py-2 font-sans text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary transition"
@@ -245,7 +245,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
<select
value={tierFilter}
onChange={e => setTierFilter(e.target.value)}
className="bg-card border border-border text-foreground text-sm font-sans rounded px-3 py-2 focus:outline-none focus:border-primary"
className="bg-card border border-border text-foreground text-sm font-sans rounded px-2 md:px-3 py-2 focus:outline-none focus:border-primary"
>
<option value="">All Tiers</option>
<option value="plus">Plus</option>
@@ -255,7 +255,8 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
</div>
<div className="bg-card rounded border border-border overflow-hidden">
<table className="w-full">
<div className="overflow-x-auto">
<table className="w-full min-w-[600px]">
<thead>
<tr className="border-b border-border">
<th className="px-4 py-3 text-left font-mono text-[10px] tracking-widest text-muted-foreground">MEMBER</th>
@@ -354,6 +355,7 @@ export function MembersClient({ members: initialMembers, currentRole }: Props) {
)}
</tbody>
</table>
</div>
</div>
</div>
+4 -4
View File
@@ -137,7 +137,7 @@ function KbModal({
required
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-sans text-xs font-medium text-muted-foreground block mb-1.5">Area</label>
<input
@@ -531,7 +531,7 @@ export function OpsClient({ member, spaceId, kbEntries: initial, areaLeads: init
return (
<div className="min-h-screen bg-background">
{/* Header */}
<div className="bg-sidebar px-6 py-3 flex items-center justify-between">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center justify-between">
<h1 className="text-white font-sans text-lg font-semibold">Ops & Facilities</h1>
<div className="flex items-center gap-2">
{(activeTab === 'kb' || activeTab === 'processes') && (
@@ -562,7 +562,7 @@ export function OpsClient({ member, spaceId, kbEntries: initial, areaLeads: init
</div>
{/* Tabs */}
<div className="bg-card border-b border-border px-6 flex gap-6">
<div className="bg-card border-b border-border px-4 md:px-6 flex gap-4 md:gap-6 overflow-x-auto">
{TABS.map(tab => (
<button
key={tab.id}
@@ -577,7 +577,7 @@ export function OpsClient({ member, spaceId, kbEntries: initial, areaLeads: init
))}
</div>
<div className="p-6 max-w-5xl">
<div className="p-4 md:p-6 max-w-5xl">
{/* Search */}
{(activeTab === 'kb' || activeTab === 'processes' || activeTab === 'secrets') && (
<div className="relative mb-6">
+8 -6
View File
@@ -121,9 +121,9 @@ export function PaymentsClient({ payments: initialPayments, members, integration
return (
<div className="min-h-screen bg-background">
<div className="bg-sidebar px-6 py-3 flex items-center justify-between">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center justify-between">
<div className="flex items-center gap-3">
<h1 className="text-white font-sans text-lg font-semibold">Payment Reconciliation</h1>
<h1 className="text-white font-sans text-lg font-semibold">Payments</h1>
{unlinkedCount > 0 && (
<span className="font-mono text-xs text-orange-400">{unlinkedCount} unlinked</span>
)}
@@ -140,9 +140,9 @@ export function PaymentsClient({ payments: initialPayments, members, integration
)}
</div>
<div className="p-6 space-y-6">
<div className="p-4 md:p-6 space-y-6">
{/* Platform summary cards */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3 md:gap-4">
{platforms.map(platform => {
const txs = byPlatform[platform] ?? []
const total = txs.reduce((sum, t) => sum + (t.amount ?? 0), 0)
@@ -203,7 +203,8 @@ export function PaymentsClient({ payments: initialPayments, members, integration
</div>
<div className="bg-card rounded border border-border overflow-hidden">
<table className="w-full">
<div className="overflow-x-auto">
<table className="w-full min-w-[600px]">
<thead>
<tr className="border-b border-border">
{['PLATFORM', 'AMOUNT', 'FROM / NOTE', 'DATE', 'MEMBER'].map(h => (
@@ -253,6 +254,7 @@ export function PaymentsClient({ payments: initialPayments, members, integration
)}
</tbody>
</table>
</div>
</div>
</div>
</div>
@@ -266,7 +268,7 @@ export function PaymentsClient({ payments: initialPayments, members, integration
<button onClick={() => setShowLogCash(false)} className="text-muted-foreground hover:text-foreground"><X className="w-4 h-4" /></button>
</div>
<form onSubmit={handleLogCash} className="p-6 space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Amount *</label>
<input type="number" step="0.01" min="0" required value={cashForm.amount}
+6 -4
View File
@@ -68,7 +68,7 @@ export function ProjectsClient({ projects: initialProjects, spaceId }: { project
return (
<div className="min-h-screen bg-background">
<div className="bg-sidebar px-6 py-3 flex items-center justify-between">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center justify-between">
<h1 className="text-white font-sans text-lg font-semibold">Projects</h1>
<button
onClick={() => setShowCreate(true)}
@@ -78,8 +78,9 @@ export function ProjectsClient({ projects: initialProjects, spaceId }: { project
</button>
</div>
<div className="p-6">
<div className="grid grid-cols-4 gap-4">
<div className="p-4 md:p-6">
<div className="overflow-x-auto -mx-4 md:mx-0 px-4 md:px-0">
<div className="grid grid-cols-4 gap-4 min-w-[640px]">
{STATUS_COLS.map(col => {
const items = columns[col.key] ?? []
return (
@@ -141,6 +142,7 @@ export function ProjectsClient({ projects: initialProjects, spaceId }: { project
)
})}
</div>
</div>
</div>
{showCreate && (
@@ -162,7 +164,7 @@ export function ProjectsClient({ projects: initialProjects, spaceId }: { project
<textarea value={form.description} onChange={e => setForm(f => ({ ...f, description: e.target.value }))}
rows={2} className="w-full bg-background border border-border rounded px-3 py-2 font-sans text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary transition resize-none" />
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Area</label>
<select value={form.area} onChange={e => setForm(f => ({ ...f, area: e.target.value }))}
+4 -4
View File
@@ -193,15 +193,15 @@ export default function SettingsClient({ space, isAdmin, integrations, currentRo
return (
<div className="min-h-screen bg-background">
{/* Header */}
<div className="bg-sidebar px-6 py-3 flex items-center">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center">
<h1 className="text-white font-sans text-lg font-semibold">Settings & Admin</h1>
</div>
<div className="flex">
{/* Main content */}
<div className="flex-1 p-6">
<div className="flex-1 p-4 md:p-6">
{/* Tabs */}
<div className="bg-card border-b border-border flex gap-6 px-2 mb-6 rounded-t">
<div className="bg-card border-b border-border flex gap-4 md:gap-6 px-2 mb-6 rounded-t overflow-x-auto">
{(['space', 'roles', 'integrations', 'webhooks'] as const).map(tab => (
<button
key={tab}
@@ -229,7 +229,7 @@ export default function SettingsClient({ space, isAdmin, integrations, currentRo
<p className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase mb-6">Space Settings</p>
<form onSubmit={handleSaveSpace} className="space-y-6">
<div className="grid grid-cols-2 gap-6">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div>
<label className="font-sans text-sm text-foreground block mb-1.5">Space Name</label>
<input
+7 -7
View File
@@ -122,7 +122,7 @@ export function TasksClient({ tasks: initialTasks, members, currentUserId, space
return (
<div className="min-h-screen bg-background">
<div className="bg-sidebar px-6 py-3 flex items-center justify-between">
<div className="bg-sidebar px-4 md:px-6 py-3 flex items-center justify-between">
<div className="flex items-center gap-3">
<h1 className="text-white font-sans text-lg font-semibold">Tasks & Chores</h1>
<span className="font-mono text-xs text-white/50">{tasks.filter(t => !isDone(t)).length} open</span>
@@ -131,7 +131,7 @@ export function TasksClient({ tasks: initialTasks, members, currentUserId, space
<select
value={filterArea}
onChange={e => setFilterArea(e.target.value)}
className="bg-sidebar-accent border border-sidebar-border text-sidebar-foreground text-xs font-sans rounded px-2 py-1.5"
className="hidden sm:block bg-sidebar-accent border border-sidebar-border text-sidebar-foreground text-xs font-sans rounded px-2 py-1.5"
>
<option value="">All Areas</option>
{AREAS.map(a => <option key={a}>{a}</option>)}
@@ -140,12 +140,12 @@ export function TasksClient({ tasks: initialTasks, members, currentUserId, space
onClick={() => setShowCreate(true)}
className="flex items-center gap-1.5 bg-primary text-white text-xs font-sans px-3 py-1.5 rounded hover:bg-primary/90 transition"
>
<Plus className="w-3.5 h-3.5" /> New Task
<Plus className="w-3.5 h-3.5" /> <span className="hidden sm:inline">New Task</span>
</button>
</div>
</div>
<div className="bg-card border-b border-border px-6 flex gap-6">
<div className="bg-card border-b border-border px-4 md:px-6 flex gap-4 md:gap-6 overflow-x-auto">
{(['chores', 'ongoing', 'mine', 'done'] as const).map((tab) => (
<button
key={tab}
@@ -166,7 +166,7 @@ export function TasksClient({ tasks: initialTasks, members, currentUserId, space
))}
</div>
<div className="p-6">
<div className="p-4 md:p-6">
<div className="bg-card rounded border border-border divide-y divide-border">
{currentList.length > 0 ? currentList.map(task => (
<div key={task.id} className={`flex items-center gap-3 px-4 py-3 ${
@@ -283,7 +283,7 @@ export function TasksClient({ tasks: initialTasks, members, currentUserId, space
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Type</label>
<select
@@ -308,7 +308,7 @@ export function TasksClient({ tasks: initialTasks, members, currentUserId, space
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="font-mono text-[10px] tracking-widest text-muted-foreground uppercase block mb-1">Recurrence</label>
<select