refactor(ui): unify button usage in settings, admin, and doclist components

Replace native button elements with shared Button, ChoiceTile, and IconButton
components for consistent UI behavior and styling. Update classNames and
props to match new component APIs. Adjust FinderSidebar to use utility
function for conditional class merging.
This commit is contained in:
Richard R 2026-06-01 11:58:30 -06:00
parent 4f1d8feda5
commit d4afa43abf
4 changed files with 17 additions and 14 deletions

View file

@ -1168,20 +1168,20 @@ export function SettingsModal({
{/* Export Data */} {/* Export Data */}
{session?.user && ( {session?.user && (
<button <ChoiceTile
onClick={() => { onClick={() => {
window.open('/api/user/export', '_blank'); window.open('/api/user/export', '_blank');
}} }}
className="w-full rounded-lg border border-line bg-background p-4 flex items-center gap-4 hover:bg-accent-wash transition-colors text-left group" className="w-full rounded-lg bg-background p-4 text-left hover:bg-accent-wash"
> >
<div className="flex-shrink-0 w-10 h-10 rounded-lg bg-surface-sunken flex items-center justify-center group-hover:bg-background transition-colors"> <div className="flex-shrink-0 w-10 h-10 rounded-lg bg-surface-sunken flex items-center justify-center">
<DownloadIcon className="w-5 h-5 text-accent" /> <DownloadIcon className="w-5 h-5 text-accent" />
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<p className="text-sm font-medium text-foreground">Export My Data</p> <p className="text-sm font-medium text-foreground">Export My Data</p>
<p className="text-xs text-soft">Download all your data as a ZIP file</p> <p className="text-xs text-soft">Download all your data as a ZIP file</p>
</div> </div>
</button> </ChoiceTile>
)} )}
{/* Actions */} {/* Actions */}
@ -1438,7 +1438,7 @@ function SettingsChangelogPanel({
<button <button
type="button" type="button"
onClick={() => setExpanded((prev) => ({ ...prev, [entry.tag_name]: !isExpanded }))} onClick={() => setExpanded((prev) => ({ ...prev, [entry.tag_name]: !isExpanded }))}
className="w-full text-left py-2 flex items-center gap-2 hover:bg-surface transition duration-base ease-standard transform" className="w-full rounded-md border border-transparent px-2 py-2 text-left flex items-center gap-2 transition duration-base ease-standard hover:border-accent-line hover:bg-accent-wash"
> >
<ChevronRightIcon <ChevronRightIcon
className={`w-3.5 h-3.5 shrink-0 text-soft transition-transform ${ className={`w-3.5 h-3.5 shrink-0 text-soft transition-transform ${

View file

@ -656,14 +656,16 @@ function SourceBadge({
return ( return (
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
{canReset && !dirty && ( {canReset && !dirty && (
<button <Button
type="button" type="button"
variant="ghost"
size="xs"
onClick={onReset} onClick={onReset}
disabled={saving} disabled={saving}
className="text-[11px] font-medium text-muted hover:text-accent transition-colors disabled:opacity-50" className="h-auto px-1 py-0 text-[11px] font-medium text-muted hover:text-accent"
> >
Reset Reset
</button> </Button>
)} )}
{dirty ? ( {dirty ? (
<Badge tone="accent">Modified</Badge> <Badge tone="accent">Modified</Badge>

View file

@ -22,6 +22,7 @@ import { ConfirmDialog } from '@/components/ConfirmDialog';
import { CreateFolderDialog } from '@/components/doclist/CreateFolderDialog'; import { CreateFolderDialog } from '@/components/doclist/CreateFolderDialog';
import { DocumentListSkeleton } from '@/components/doclist/DocumentListSkeleton'; import { DocumentListSkeleton } from '@/components/doclist/DocumentListSkeleton';
import { DocumentUploader, type UploadBatchState } from '@/components/documents/DocumentUploader'; import { DocumentUploader, type UploadBatchState } from '@/components/documents/DocumentUploader';
import { IconButton } from '@/components/ui';
import { DocumentDndProvider } from './dnd/DocumentDndProvider'; import { DocumentDndProvider } from './dnd/DocumentDndProvider';
import { import {
DocumentSelectionProvider, DocumentSelectionProvider,
@ -664,16 +665,16 @@ function DocumentListInner({ brand, appActions }: DocumentListInnerProps) {
<p className="text-foreground"> <p className="text-foreground">
Drag files onto each other to make folders. Drop into the sidebar to move. Drag files onto each other to make folders. Drop into the sidebar to move.
</p> </p>
<button <IconButton
type="button"
onClick={() => setShowHint(false)} onClick={() => setShowHint(false)}
className="h-6 w-6 inline-flex items-center justify-center text-soft hover:text-accent hover:bg-surface rounded transition duration-base ease-standard" size="xs"
className="h-6 w-6"
aria-label="Dismiss hint" aria-label="Dismiss hint"
> >
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
</svg> </svg>
</button> </IconButton>
</div> </div>
</div> </div>
)} )}

View file

@ -7,7 +7,7 @@ import type { Folder, SidebarFilter } from '@/types/documents';
import { PDFIcon, EPUBIcon, FileIcon, DotsHorizontalIcon } from '@/components/icons/Icons'; import { PDFIcon, EPUBIcon, FileIcon, DotsHorizontalIcon } from '@/components/icons/Icons';
import { FolderIcon, HomeIcon, ClockIcon, FolderPlusIcon } from './finderIcons'; import { FolderIcon, HomeIcon, ClockIcon, FolderPlusIcon } from './finderIcons';
import { DND_DOCUMENT, type DocumentDragItem } from '../dnd/dndTypes'; import { DND_DOCUMENT, type DocumentDragItem } from '../dnd/dndTypes';
import { IconButton, MenuItemClass, Sidebar as SidebarShell, SidebarNav, SidebarNavGroup, SidebarNavItem, menuPanelClass } from '@/components/ui'; import { IconButton, MenuItemClass, Sidebar as SidebarShell, SidebarNav, SidebarNavGroup, SidebarNavItem, cn, menuPanelClass } from '@/components/ui';
interface FinderSidebarProps { interface FinderSidebarProps {
filter: SidebarFilter; filter: SidebarFilter;
@ -248,7 +248,7 @@ export function FinderSidebar({
onRowAction?.(); onRowAction?.();
}} }}
disabled={disabled} disabled={disabled}
className={disabled ? 'flex w-full cursor-not-allowed items-center gap-2 rounded-md px-2 py-2 text-xs text-faint' : MenuItemClass(active)} className={cn(MenuItemClass(active), disabled && 'cursor-not-allowed text-faint')}
> >
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />