feat(design): cyan accent, dialog overflow fixes, unified delete buttons, nav polish

This commit is contained in:
opencode
2026-08-06 23:03:14 +02:00
parent e65daea8dd
commit 54364d7a88
49 changed files with 4776 additions and 31 deletions
+6 -6
View File
@@ -361,7 +361,7 @@ export default function Admin() {
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
<DialogContent className="sm:max-w-md">
<DialogHeader className="flex flex-row items-center justify-between gap-2">
<DialogTitle>{t("admin.createNewUser")}</DialogTitle>
<DialogTitle className="min-w-0 truncate">{t("admin.createNewUser")}</DialogTitle>
<GuideHelp guide="administration" label={t("admin.createNewUser")} />
</DialogHeader>
<div className="space-y-4 py-2">
@@ -403,7 +403,7 @@ export default function Admin() {
</Select>
</div>
</div>
<DialogFooter>
<DialogFooter className="flex-col-reverse sm:flex-row sm:flex-wrap sm:justify-end gap-2">
<Button variant="outline" onClick={() => setCreateOpen(false)}>{t("common.cancel")}</Button>
<Button onClick={handleCreateUser} disabled={createUser.isPending || !newUsername || !newPassword}>
{createUser.isPending ? t("admin.creating") : t("admin.createUser")}
@@ -413,9 +413,9 @@ export default function Admin() {
</Dialog>
<Dialog open={!!editUser} onOpenChange={(open) => { if (!open) { setEditUser(null); setEditPassword(""); } }}>
<DialogContent className="sm:max-w-sm">
<DialogContent className="sm:max-w-md">
<DialogHeader className="flex flex-row items-center justify-between gap-2">
<DialogTitle>{t("admin.editUser", { username: editUser?.username })}</DialogTitle>
<DialogTitle className="min-w-0 truncate">{t("admin.editUser", { username: editUser?.username })}</DialogTitle>
<GuideHelp guide="administration" label={t("admin.editUser", { username: editUser?.username })} />
</DialogHeader>
<div className="space-y-4 py-2">
@@ -467,7 +467,7 @@ export default function Admin() {
</div>
)}
</div>
<DialogFooter className="flex-col sm:flex-row sm:justify-end gap-2">
<DialogFooter className="flex-col-reverse sm:flex-row sm:flex-wrap sm:justify-end gap-2">
<Button variant="outline" onClick={() => { setEditUser(null); setEditPassword(""); }}>{t("common.cancel")}</Button>
<Button
onClick={handleUpdateUser}
@@ -498,7 +498,7 @@ export default function Admin() {
</p>
<DialogFooter>
<Button variant="outline" onClick={() => setDeleteConfirm(null)}>{t("common.cancel")}</Button>
<Button variant="destructive" onClick={handleDeleteUser} disabled={deleteUser.isPending}>
<Button variant="outline" className="text-destructive hover:bg-destructive hover:text-destructive-foreground" onClick={handleDeleteUser} disabled={deleteUser.isPending}>
{deleteUser.isPending ? t("detail.deleting") : t("common.delete")}
</Button>
</DialogFooter>
+25 -7
View File
@@ -127,9 +127,15 @@ export default function Analytics() {
<YAxis domain={[0, 5]} tickLine={false} axisLine={false} tickFormatter={(v) => `${v}`} tick={{ fill: 'hsl(var(--foreground))', fontSize: 12 }} />
<RechartsTooltip
cursor={{ fill: 'hsl(var(--muted))' }}
contentStyle={{ borderRadius: '8px', border: '1px solid hsl(var(--border))' }}
contentStyle={{ backgroundColor: 'hsl(var(--popover))', borderRadius: '8px', border: '1px solid hsl(var(--border))', color: 'hsl(var(--foreground))' }}
/>
<Bar dataKey="score" fill="hsl(var(--primary))" radius={[4, 4, 0, 0]} maxBarSize={50} />
<defs>
<linearGradient id="neonBarFillA" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stopColor="hsl(var(--glow-1))" />
<stop offset="100%" stopColor="hsl(var(--glow-2))" />
</linearGradient>
</defs>
<Bar dataKey="score" fill="url(#neonBarFillA)" radius={[4, 4, 0, 0]} maxBarSize={50} />
</BarChart>
</ResponsiveContainer>
</div>
@@ -154,7 +160,7 @@ export default function Analytics() {
<PolarAngleAxis dataKey="category" tick={{ fill: 'hsl(var(--foreground))', fontSize: 12 }} />
<PolarRadiusAxis angle={30} domain={[0, 'auto']} tick={false} axisLine={false} />
<Radar name={t("analytics.radarTools")} dataKey="tools" stroke="hsl(var(--primary))" fill="hsl(var(--primary))" fillOpacity={0.3} />
<RechartsTooltip />
<RechartsTooltip contentStyle={{ backgroundColor: 'hsl(var(--popover))', borderRadius: '8px', border: '1px solid hsl(var(--border))', color: 'hsl(var(--foreground))' }} />
</RadarChart>
</ResponsiveContainer>
</div>
@@ -181,8 +187,14 @@ export default function Analytics() {
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="hsl(var(--border))" />
<XAxis dataKey="score" tickLine={false} axisLine={false} tick={{ fill: 'hsl(var(--foreground))', fontSize: 12 }} />
<YAxis hide />
<RechartsTooltip cursor={{ fill: 'hsl(var(--muted))' }} contentStyle={{ borderRadius: '6px', border: '1px solid hsl(var(--border))' }} />
<Bar dataKey="count" fill="hsl(var(--primary))" radius={[4, 4, 0, 0]} maxBarSize={40} />
<RechartsTooltip cursor={{ fill: 'hsl(var(--muted))' }} contentStyle={{ backgroundColor: 'hsl(var(--popover))', borderRadius: '6px', border: '1px solid hsl(var(--border))', color: 'hsl(var(--foreground))' }} />
<defs>
<linearGradient id="neonBarFillB" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stopColor="hsl(var(--glow-1))" />
<stop offset="100%" stopColor="hsl(var(--glow-2))" />
</linearGradient>
</defs>
<Bar dataKey="count" fill="url(#neonBarFillB)" radius={[4, 4, 0, 0]} maxBarSize={40} />
</BarChart>
</ResponsiveContainer>
</div>
@@ -195,8 +207,14 @@ export default function Analytics() {
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="hsl(var(--border))" />
<XAxis dataKey="score" tickLine={false} axisLine={false} tick={{ fill: 'hsl(var(--foreground))', fontSize: 12 }} />
<YAxis hide />
<RechartsTooltip cursor={{ fill: 'hsl(var(--muted))' }} contentStyle={{ borderRadius: '6px', border: '1px solid hsl(var(--border))' }} />
<Bar dataKey="count" fill="hsl(var(--chart-3))" radius={[4, 4, 0, 0]} maxBarSize={40} />
<RechartsTooltip cursor={{ fill: 'hsl(var(--muted))' }} contentStyle={{ backgroundColor: 'hsl(var(--popover))', borderRadius: '6px', border: '1px solid hsl(var(--border))', color: 'hsl(var(--foreground))' }} />
<defs>
<linearGradient id="neonBarFillC" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stopColor="hsl(var(--glow-1))" />
<stop offset="100%" stopColor="hsl(var(--glow-2))" />
</linearGradient>
</defs>
<Bar dataKey="count" fill="url(#neonBarFillC)" radius={[4, 4, 0, 0]} maxBarSize={40} />
</BarChart>
</ResponsiveContainer>
</div>
+9 -3
View File
@@ -717,8 +717,14 @@ export default function ToolDetail() {
<BarChart data={usefulnessData} layout="vertical" margin={{ top: 0, right: 0, bottom: 0, left: -20 }}>
<XAxis type="number" hide />
<YAxis dataKey="score" type="category" axisLine={false} tickLine={false} tickFormatter={(val) => `${val}`} tick={{ fill: 'hsl(var(--foreground))', fontSize: 12 }} />
<Tooltip cursor={{ fill: 'transparent' }} />
<Bar dataKey="count" fill="hsl(var(--primary))" radius={[0, 4, 4, 0]} barSize={12} />
<Tooltip cursor={{ fill: 'transparent' }} contentStyle={{ backgroundColor: 'hsl(var(--popover))', border: '1px solid hsl(var(--border))', borderRadius: '8px', color: 'hsl(var(--foreground))' }} />
<defs>
<linearGradient id="neonBarFill" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stopColor="hsl(var(--glow-1))" />
<stop offset="100%" stopColor="hsl(var(--glow-2))" />
</linearGradient>
</defs>
<Bar dataKey="count" fill="url(#neonBarFill)" radius={[0, 4, 4, 0]} barSize={12} />
</BarChart>
</ResponsiveContainer>
</div>
@@ -740,7 +746,7 @@ export default function ToolDetail() {
<CartesianGrid strokeDasharray="3 3" opacity={0.2} />
<XAxis dataKey="date" hide />
<YAxis domain={[0, 5]} tick={{ fill: 'hsl(var(--foreground))', fontSize: 12 }} axisLine={false} tickLine={false} />
<Tooltip labelFormatter={(_, payload) => (payload?.[0] ? format(new Date(payload[0].payload.date), "dd.MM.yyyy HH:mm") : "")} />
<Tooltip labelFormatter={(_, payload) => (payload?.[0] ? format(new Date(payload[0].payload.date), "dd.MM.yyyy HH:mm") : "")} contentStyle={{ backgroundColor: 'hsl(var(--popover))', border: '1px solid hsl(var(--border))', borderRadius: '8px', color: 'hsl(var(--foreground))' }} />
<Legend wrapperStyle={{ fontSize: 12 }} />
<Line type="monotone" dataKey="combined" name={t("detail.score")} stroke="hsl(var(--primary))" strokeWidth={2} dot={false} />
<Line type="monotone" dataKey="usefulness" name={t("detail.usefulness")} stroke="hsl(var(--success))" strokeWidth={1.5} dot={false} strokeDasharray="4 3" />
+2 -1
View File
@@ -192,7 +192,8 @@ export default function Trash() {
<>
<Button
size="sm"
variant="destructive"
variant="outline"
className="text-destructive hover:bg-destructive hover:text-destructive-foreground"
disabled={selectedIds.length === 0 || deletePermanent.isPending}
onClick={() => setConfirmDelete(true)}
>