fix: toolbar carnet redesign — propre et cohérent
- Layout mode (Grid/List/Table/Kanban) déplacé à droite - Sort à droite avec icône compacte - Toutes les actions IA (Résumé, Planning, Organiser) + CSV dans un menu ⋯ - Plus de boutons éparpillés — tout est dans un seul dropdown - Layout respecte le design system existant
This commit is contained in:
@@ -20,7 +20,7 @@ import {
|
||||
|
||||
import { NotebookSuggestionToast } from '@/components/notebook-suggestion-toast'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Plus, ArrowUpDown, Search, Sparkles, FileText, FolderOpen, ChevronRight, Tag as TagIcon, X, Menu, LayoutGrid, List, Table, Columns3, CalendarDays, Wand2, Download, Upload } from 'lucide-react'
|
||||
import { Plus, ArrowUpDown, Search, Sparkles, FileText, FolderOpen, ChevronRight, Tag as TagIcon, X, Menu, LayoutGrid, List, Table, Columns3, CalendarDays, Wand2, Download, Upload, MoreHorizontal } from 'lucide-react'
|
||||
import { emitNoteChange } from '@/lib/note-change-sync'
|
||||
import { useReminderCheck } from '@/hooks/use-reminder-check'
|
||||
import { useAutoLabelSuggestion } from '@/hooks/use-auto-label-suggestion'
|
||||
@@ -34,6 +34,7 @@ import { StudyPlannerDialog } from '@/components/wizard/study-planner-dialog'
|
||||
import { NotebookOrganizerDialog } from '@/components/wizard/notebook-organizer-dialog'
|
||||
import { toast } from 'sonner'
|
||||
import { AnimatePresence, motion } from 'motion/react'
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
|
||||
|
||||
|
||||
type SortOrder = 'newest' | 'oldest' | 'alpha' | 'manual'
|
||||
@@ -849,7 +850,7 @@ export function HomeClient({
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between border-b border-foreground/5 pb-4">
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex items-center gap-5">
|
||||
<button
|
||||
onClick={handleAddNote}
|
||||
disabled={isCreating}
|
||||
@@ -869,7 +870,6 @@ export function HomeClient({
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Inline search — toggles an input within the toolbar */}
|
||||
{showInlineSearch ? (
|
||||
<div className="flex items-center gap-2">
|
||||
{isSearching ? (
|
||||
@@ -889,20 +889,13 @@ export function HomeClient({
|
||||
if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current)
|
||||
searchDebounceRef.current = setTimeout(() => {
|
||||
const params = new URLSearchParams(searchParams.toString())
|
||||
if (q.trim()) {
|
||||
params.set('search', q)
|
||||
} else {
|
||||
params.delete('search')
|
||||
}
|
||||
if (q.trim()) params.set('search', q)
|
||||
else params.delete('search')
|
||||
router.push(`/home?${params.toString()}`)
|
||||
setIsSearching(false)
|
||||
}, 300)
|
||||
}}
|
||||
onBlur={() => {
|
||||
if (!inlineSearchQuery) {
|
||||
setShowInlineSearch(false)
|
||||
}
|
||||
}}
|
||||
onBlur={() => { if (!inlineSearchQuery) setShowInlineSearch(false) }}
|
||||
onKeyDown={e => {
|
||||
if (e.key === 'Escape') {
|
||||
if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current)
|
||||
@@ -936,10 +929,7 @@ export function HomeClient({
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => {
|
||||
setShowInlineSearch(true)
|
||||
setTimeout(() => inlineSearchRef.current?.focus(), 50)
|
||||
}}
|
||||
onClick={() => { setShowInlineSearch(true); setTimeout(() => inlineSearchRef.current?.focus(), 50) }}
|
||||
className="flex items-center gap-2 text-[13px] text-foreground font-medium hover:opacity-70 transition-opacity"
|
||||
>
|
||||
<Search size={16} />
|
||||
@@ -950,83 +940,30 @@ export function HomeClient({
|
||||
{!searchParams.get('notebook') && searchParams.get('shared') !== '1' && (
|
||||
<button
|
||||
onClick={() => setBatchOrganizationOpen(true)}
|
||||
className="flex items-center gap-2 text-[13px] text-foreground font-medium hover:opacity-70 transition-opacity"
|
||||
className="flex items-center gap-2 text-[13px] text-brand-accent font-medium hover:opacity-70 transition-opacity"
|
||||
>
|
||||
<Sparkles size={16} />
|
||||
<span>{t('notes.reorganize')}</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-4 flex-wrap">
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Layout mode */}
|
||||
<div className="bg-foreground/[0.03] dark:bg-white/[0.04] p-0.5 rounded-full flex border border-border/30 items-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => selectLayoutMode('grid')}
|
||||
className={cn(
|
||||
'p-1.5 rounded-full transition-all',
|
||||
layoutMode === 'grid'
|
||||
? 'bg-foreground text-background shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground',
|
||||
)}
|
||||
title={t('notes.layoutGridTitle')}
|
||||
>
|
||||
<button type="button" onClick={() => selectLayoutMode('grid')} className={cn('p-1.5 rounded-full transition-all', layoutMode === 'grid' ? 'bg-foreground text-background shadow-sm' : 'text-muted-foreground hover:text-foreground')} title={t('notes.layoutGridTitle')}>
|
||||
<LayoutGrid size={13} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => selectLayoutMode('list')}
|
||||
className={cn(
|
||||
'p-1.5 rounded-full transition-all',
|
||||
layoutMode === 'list'
|
||||
? 'bg-foreground text-background shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground',
|
||||
)}
|
||||
title={t('notes.layoutListTitle')}
|
||||
>
|
||||
<button type="button" onClick={() => selectLayoutMode('list')} className={cn('p-1.5 rounded-full transition-all', layoutMode === 'list' ? 'bg-foreground text-background shadow-sm' : 'text-muted-foreground hover:text-foreground')} title={t('notes.layoutListTitle')}>
|
||||
<List size={13} />
|
||||
</button>
|
||||
{!notebookFilter && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => selectLayoutMode('table')}
|
||||
className={cn(
|
||||
'p-1.5 rounded-full transition-all',
|
||||
layoutMode === 'table'
|
||||
? 'bg-foreground text-background shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground',
|
||||
)}
|
||||
title={t('notes.layoutTableTitle')}
|
||||
>
|
||||
<Table size={13} />
|
||||
</button>
|
||||
)}
|
||||
{notebookFilter && (
|
||||
<>
|
||||
<span className="w-px h-4 bg-border/50 mx-0.5" aria-hidden />
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => selectLayoutMode('table')}
|
||||
className={cn(
|
||||
'p-1.5 rounded-full transition-all',
|
||||
layoutMode === 'table'
|
||||
? 'bg-foreground text-background shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground',
|
||||
)}
|
||||
title={t('structuredViews.viewTableHint')}
|
||||
>
|
||||
<button type="button" onClick={() => selectLayoutMode('table')} className={cn('p-1.5 rounded-full transition-all', layoutMode === 'table' ? 'bg-foreground text-background shadow-sm' : 'text-muted-foreground hover:text-foreground')} title={t('structuredViews.viewTableHint')}>
|
||||
<Table size={13} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => selectLayoutMode('kanban')}
|
||||
className={cn(
|
||||
'p-1.5 rounded-full transition-all',
|
||||
layoutMode === 'kanban'
|
||||
? 'bg-foreground text-background shadow-sm'
|
||||
: 'text-muted-foreground hover:text-foreground',
|
||||
)}
|
||||
title={t('structuredViews.viewKanbanHint')}
|
||||
>
|
||||
<button type="button" onClick={() => selectLayoutMode('kanban')} className={cn('p-1.5 rounded-full transition-all', layoutMode === 'kanban' ? 'bg-foreground text-background shadow-sm' : 'text-muted-foreground hover:text-foreground')} title={t('structuredViews.viewKanbanHint')}>
|
||||
<Columns3 size={13} />
|
||||
</button>
|
||||
</>
|
||||
@@ -1034,69 +971,57 @@ export function HomeClient({
|
||||
</div>
|
||||
|
||||
{currentNotebook && structuredModeActive && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAddPropertyOpen(true)}
|
||||
className="p-1.5 rounded-full text-muted-foreground hover:text-brand-accent transition-colors"
|
||||
title={t('structuredViews.addProperty')}
|
||||
>
|
||||
<button type="button" onClick={() => setAddPropertyOpen(true)} className="p-1.5 rounded-full text-muted-foreground hover:text-brand-accent transition-colors" title={t('structuredViews.addProperty')}>
|
||||
<Plus size={16} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{searchParams.get('notebook') && initialSettings.aiAssistantEnabled && (
|
||||
<div className="flex items-center gap-3">
|
||||
<button
|
||||
onClick={() => setSummaryDialogOpen(true)}
|
||||
className="flex items-center gap-1.5 text-[12px] text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<FileText size={14} />
|
||||
<span>{t('notebook.summary')}</span>
|
||||
</button>
|
||||
<span className="w-px h-3.5 bg-border/40" />
|
||||
<button
|
||||
onClick={() => setShowStudyPlanner(true)}
|
||||
className="flex items-center gap-1.5 text-[12px] text-muted-foreground hover:text-brand-accent transition-colors"
|
||||
>
|
||||
<CalendarDays size={14} />
|
||||
<span>{t('wizard.studyPlanner') || 'Planning'}</span>
|
||||
</button>
|
||||
<span className="w-px h-3.5 bg-border/40" />
|
||||
<button
|
||||
onClick={() => setOrganizeNotebookOpen(true)}
|
||||
className="flex items-center gap-1.5 text-[12px] text-muted-foreground hover:text-brand-accent transition-colors"
|
||||
title={t('notebook.organizeNotebookWithAITooltip')}
|
||||
>
|
||||
<Sparkles size={14} />
|
||||
<span>{t('batch.organize')}</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{searchParams.get('notebook') && (
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
onClick={handleImportCSV}
|
||||
className="p-1.5 rounded-full text-muted-foreground hover:text-foreground transition-colors"
|
||||
title={t('structuredViews.importCsv') || 'Importer CSV'}
|
||||
>
|
||||
<Upload size={15} />
|
||||
</button>
|
||||
<button
|
||||
onClick={handleExportCSV}
|
||||
className="p-1.5 rounded-full text-muted-foreground hover:text-foreground transition-colors"
|
||||
title={t('structuredViews.exportCsv') || 'Exporter CSV'}
|
||||
>
|
||||
<Download size={15} />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{/* Sort */}
|
||||
<button
|
||||
onClick={() => setSortOrder(s => s === 'newest' ? 'oldest' : s === 'oldest' ? 'alpha' : s === 'alpha' ? 'manual' : 'newest')}
|
||||
className="flex items-center gap-2 text-[13px] text-foreground font-medium hover:opacity-70 transition-opacity"
|
||||
className="flex items-center gap-1.5 text-[13px] text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<ArrowUpDown size={16} />
|
||||
<span>{sortLabels[sortOrder]}</span>
|
||||
<ArrowUpDown size={14} />
|
||||
<span className="hidden sm:inline">{sortLabels[sortOrder]}</span>
|
||||
</button>
|
||||
|
||||
{/* AI + utils dropdown */}
|
||||
{searchParams.get('notebook') && (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button className="p-1.5 rounded-full text-muted-foreground hover:text-foreground hover:bg-foreground/5 transition-all" title="Plus d'actions">
|
||||
<MoreHorizontal size={16} />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-56">
|
||||
{initialSettings.aiAssistantEnabled && (
|
||||
<>
|
||||
<DropdownMenuItem onClick={() => setSummaryDialogOpen(true)}>
|
||||
<FileText className="h-4 w-4 me-2" />
|
||||
{t('notebook.summary')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setShowStudyPlanner(true)}>
|
||||
<CalendarDays className="h-4 w-4 me-2" />
|
||||
{t('wizard.studyPlanner') || 'Planning'}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setOrganizeNotebookOpen(true)}>
|
||||
<Sparkles className="h-4 w-4 me-2 text-brand-accent" />
|
||||
{t('batch.organize')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
</>
|
||||
)}
|
||||
<DropdownMenuItem onClick={handleImportCSV}>
|
||||
<Upload className="h-4 w-4 me-2" />
|
||||
{t('structuredViews.importCsv') || 'Importer CSV'}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={handleExportCSV}>
|
||||
<Download className="h-4 w-4 me-2" />
|
||||
{t('structuredViews.exportCsv') || 'Exporter CSV'}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user