fix: move breakdown button to the start of the row, swap chevron for SquareDivide

Резерв под стрелку справа от суммы отъедал место у самой суммы даже
когда у категории нет подкатегорий — суммы во всей колонке смотрелись
сдвинутыми от правого края. Кнопка перенесена в начало строки, где
резерв под неё не мешает колонке сумм. Иконка заменена на SquareDivide
(та же, что уже используется для сплит-транзакций в списке).
This commit is contained in:
ZProger
2026-08-30 19:20:00 +03:00
parent 84dc8e9721
commit 87b37a10ff
2 changed files with 35 additions and 33 deletions

View File

@@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { ChevronRight } from "lucide-react"; import { SquareDivide } from "lucide-react";
import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from "recharts"; import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from "recharts";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card";
import { CategoryBreakdownModal } from "@/components/categories/CategoryBreakdownModal"; import { CategoryBreakdownModal } from "@/components/categories/CategoryBreakdownModal";
@@ -76,7 +76,23 @@ export function SpendingByCategoryCard({ items }: SpendingByCategoryCardProps) {
const Icon = getCategoryIcon(item.icon); const Icon = getCategoryIcon(item.icon);
const hasChildren = item.children.length > 0; const hasChildren = item.children.length > 0;
return ( return (
<li key={item.category_id ?? "other"} className="flex items-center gap-3 py-2 first:pt-0 last:pb-0"> <li key={item.category_id ?? "other"} className="flex items-center gap-2 py-2 first:pt-0 last:pb-0">
{/* Fixed-width slot on every row, populated or not — the
amount column at the row's end must stay flush right
the same way whether or not this row has a
breakdown to open. */}
<span className="flex h-6 w-6 shrink-0 items-center justify-center">
{hasChildren && (
<button
type="button"
aria-label={t("common.expand")}
onClick={() => setBreakdownItem(item)}
className="rounded-md p-0.5 text-text-muted hover:bg-surface-2 hover:text-text-primary"
>
<SquareDivide size={15} />
</button>
)}
</span>
<span <span
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full" className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full"
style={{ backgroundColor: `${item.color}26` }} style={{ backgroundColor: `${item.color}26` }}
@@ -89,21 +105,6 @@ export function SpendingByCategoryCard({ items }: SpendingByCategoryCardProps) {
<span className="shrink-0 text-sm font-medium tabular-nums text-text-primary"> <span className="shrink-0 text-sm font-medium tabular-nums text-text-primary">
{formatCurrency(item.amount)} {formatCurrency(item.amount)}
</span> </span>
{/* Fixed-width slot on every row, populated or not — a
chevron shown only on rows with children would shift
their amount left relative to every other row's. */}
<span className="flex h-6 w-5 shrink-0 items-center justify-center">
{hasChildren && (
<button
type="button"
aria-label={t("common.expand")}
onClick={() => setBreakdownItem(item)}
className="rounded-md p-0.5 text-text-muted hover:bg-surface-2 hover:text-text-primary"
>
<ChevronRight size={15} />
</button>
)}
</span>
</li> </li>
); );
})} })}

View File

@@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { ChevronRight } from "lucide-react"; import { SquareDivide } from "lucide-react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card";
import { CategoryBreakdownModal } from "@/components/categories/CategoryBreakdownModal"; import { CategoryBreakdownModal } from "@/components/categories/CategoryBreakdownModal";
import { getCategoryIcon } from "@/lib/icons"; import { getCategoryIcon } from "@/lib/icons";
@@ -50,6 +50,22 @@ export function CategoryRankingCard({ items, isLoading, selectedCategoryId, onSe
isSelected ? "bg-surface-2" : "" isSelected ? "bg-surface-2" : ""
}`} }`}
> >
{/* Fixed-width slot on every row, populated or not — the
amount column at the row's end must stay flush right
the same way whether or not this row has a
breakdown to open. */}
<span className="ml-1 flex h-8 w-7 shrink-0 items-center justify-center">
{hasChildren && (
<button
type="button"
aria-label={t("common.expand")}
onClick={() => setBreakdownItem(item)}
className="rounded-md p-1.5 text-text-muted hover:text-text-primary"
>
<SquareDivide size={14} />
</button>
)}
</span>
<button <button
type="button" type="button"
onClick={() => onSelectCategory(item.category_id)} onClick={() => onSelectCategory(item.category_id)}
@@ -80,21 +96,6 @@ export function CategoryRankingCard({ items, isLoading, selectedCategoryId, onSe
{formatCurrency(item.amount)} {formatCurrency(item.amount)}
</span> </span>
</button> </button>
{/* Fixed-width slot on every row, populated or not — a
chevron shown only on rows with children would shift
their amount left relative to every other row's. */}
<span className="mr-1 flex h-8 w-7 shrink-0 items-center justify-center">
{hasChildren && (
<button
type="button"
aria-label={t("common.expand")}
onClick={() => setBreakdownItem(item)}
className="rounded-md p-1.5 text-text-muted hover:text-text-primary"
>
<ChevronRight size={14} />
</button>
)}
</span>
</div> </div>
</li> </li>
); );