UI redesign: compact header, group dropdown, slim task cards
- Removed logo/brand from header - Group selector as dropdown (not horizontal scroll) - Compact task cards (single line, less padding) - Status filter pills smaller - Sticky header 44px Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,7 +63,7 @@ export default function TasksPage() {
|
||||
loadData();
|
||||
}, [token, router, loadData]);
|
||||
|
||||
// Navigate to next/previous group
|
||||
// Navigate to next/previous group via swipe
|
||||
const navigateGroup = useCallback(
|
||||
(direction: "left" | "right") => {
|
||||
if (groupOrder.length <= 1) return;
|
||||
@@ -73,7 +73,6 @@ export default function TasksPage() {
|
||||
: (currentGroupIndex - 1 + groupOrder.length) % groupOrder.length;
|
||||
const newGroupId = groupOrder[newIndex];
|
||||
|
||||
// Show overlay
|
||||
if (newGroupId === null) {
|
||||
setSwipeOverlay({ name: t("tasks.all"), icon: null });
|
||||
} else {
|
||||
@@ -83,7 +82,6 @@ export default function TasksPage() {
|
||||
setSwipeDirection(direction);
|
||||
setSelectedGroup(newGroupId);
|
||||
|
||||
// Hide overlay after animation
|
||||
setTimeout(() => {
|
||||
setSwipeOverlay(null);
|
||||
setSwipeDirection(null);
|
||||
@@ -131,21 +129,23 @@ export default function TasksPage() {
|
||||
if (!token) return null;
|
||||
|
||||
return (
|
||||
<div className="space-y-3 pb-24 sm:pb-8 px-4 sm:px-0">
|
||||
{/* Group tabs */}
|
||||
<GroupSelector
|
||||
groups={groups}
|
||||
selected={selectedGroup}
|
||||
onSelect={setSelectedGroup}
|
||||
/>
|
||||
<div className="space-y-2 pb-24 sm:pb-8 px-4 sm:px-0">
|
||||
{/* Group dropdown + Status pills row */}
|
||||
<div className="flex items-center gap-3 flex-wrap">
|
||||
<GroupSelector
|
||||
groups={groups}
|
||||
selected={selectedGroup}
|
||||
onSelect={setSelectedGroup}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Status filter */}
|
||||
<div className="flex gap-1.5 overflow-x-auto scrollbar-hide pb-1">
|
||||
{/* Status filter pills - compact */}
|
||||
<div className="flex gap-1 overflow-x-auto scrollbar-hide px-4">
|
||||
{statusOptions.map((opt) => (
|
||||
<button
|
||||
key={opt.value}
|
||||
onClick={() => setStatusFilter(opt.value)}
|
||||
className={`flex-shrink-0 px-3 py-2 rounded-lg text-xs font-medium transition-all min-h-[44px] ${
|
||||
className={`flex-shrink-0 px-2.5 py-1 rounded-full text-[11px] font-medium transition-all ${
|
||||
statusFilter === opt.value
|
||||
? "bg-gray-800 text-white dark:bg-white dark:text-gray-900"
|
||||
: "bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||
@@ -174,7 +174,7 @@ export default function TasksPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Task list with transition animation */}
|
||||
{/* Task list */}
|
||||
<div
|
||||
className={`transition-all duration-300 ease-out ${
|
||||
swipeDirection === "left"
|
||||
@@ -185,19 +185,19 @@ export default function TasksPage() {
|
||||
}`}
|
||||
>
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
|
||||
<div className="flex justify-center py-8">
|
||||
<div className="animate-spin rounded-full h-7 w-7 border-b-2 border-blue-600" />
|
||||
</div>
|
||||
) : tasks.length === 0 ? (
|
||||
<div className="text-center py-16">
|
||||
<div className="text-5xl mb-4 opacity-50">☐</div>
|
||||
<p className="text-muted text-lg font-medium">{t("tasks.noTasks")}</p>
|
||||
<div className="text-center py-12">
|
||||
<div className="text-4xl mb-3 opacity-50">☐</div>
|
||||
<p className="text-muted text-base font-medium">{t("tasks.noTasks")}</p>
|
||||
<p className="text-muted text-sm mt-1">
|
||||
{t("tasks.createFirst")}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
<div className="space-y-1">
|
||||
{tasks.map((task) => (
|
||||
<TaskCard
|
||||
key={task.id}
|
||||
@@ -210,7 +210,7 @@ export default function TasksPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Floating action button - positioned for thumb reach */}
|
||||
{/* Floating action button */}
|
||||
<button
|
||||
onClick={() => setShowForm(true)}
|
||||
className="fixed bottom-20 sm:bottom-6 right-4 sm:right-6 w-14 h-14 bg-blue-600 hover:bg-blue-700 active:bg-blue-800 text-white rounded-full shadow-lg hover:shadow-xl active:shadow-md transition-all duration-200 flex items-center justify-center z-40 hover:scale-105 active:scale-95"
|
||||
|
||||
Reference in New Issue
Block a user