fix(ui): обозначить выбранные состояния и поиск трафика
This commit is contained in:
1 parent
460cf67313
commit
48b7a061c1
6 files changed
+44
-10
No files matched your search
@@ -338,7 +338,7 @@ function StatChip({ icon, label, value }: { icon: ReactNode; label: string; valu
|
||||
|
||||
function ServerCard({ s, selected, onClick }: { s: ServerTraffic; selected: boolean; onClick: () => void }) {
|
||||
return (
|
||||
<button onClick={onClick} className={cn(
|
||||
<button type="button" aria-pressed={selected} onClick={onClick} className={cn(
|
||||
"text-left w-full rounded-lg border p-3 transition-colors hover:bg-muted/50",
|
||||
selected ? "border-primary bg-primary/5" : "border-border bg-card",
|
||||
s.status === "offline" && "opacity-60",
|
||||
@@ -375,7 +375,7 @@ function ServerCard({ s, selected, onClick }: { s: ServerTraffic; selected: bool
|
||||
function UserCard({ u, selected, onClick }: { u: UserTraffic; selected: boolean; onClick: () => void }) {
|
||||
const hasClients = u.interfaces.length > 0
|
||||
return (
|
||||
<button onClick={onClick} className={cn(
|
||||
<button type="button" aria-pressed={selected} onClick={onClick} className={cn(
|
||||
"text-left w-full rounded-lg border p-3 transition-colors hover:bg-muted/50",
|
||||
selected ? "border-primary bg-primary/5" : "border-border bg-card",
|
||||
!hasClients && "opacity-60",
|
||||
@@ -417,7 +417,7 @@ function UserCard({ u, selected, onClick }: { u: UserTraffic; selected: boolean;
|
||||
|
||||
function IfaceCard({ c, selected, onClick }: { c: BoundIfaceTraffic; selected: boolean; onClick: () => void }) {
|
||||
return (
|
||||
<button onClick={onClick} className={cn(
|
||||
<button type="button" aria-pressed={selected} onClick={onClick} className={cn(
|
||||
"text-left w-full rounded-lg border p-3 transition-colors hover:bg-muted/50",
|
||||
selected ? "border-primary bg-primary/5" : "border-border bg-card",
|
||||
c.status === "offline" && "opacity-60",
|
||||
@@ -516,7 +516,7 @@ function DetailHeader({ range, setRange, children }: {
|
||||
<div className="flex items-center gap-2 flex-wrap min-w-0">{children}</div>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{TRAFFIC_RANGE_KEYS.map((r) => (
|
||||
<Button key={r} size="sm" variant={r === range ? "default" : "ghost"}
|
||||
<Button key={r} type="button" aria-pressed={range === r} size="sm" variant={r === range ? "default" : "ghost"}
|
||||
className="h-7 px-2 text-xs" onClick={() => setRange(r)}>
|
||||
{TRAFFIC_RANGE_LABELS[r]}
|
||||
</Button>
|
||||
@@ -1178,7 +1178,7 @@ export default function TrafficPage() {
|
||||
<div className="border-b bg-background shrink-0">
|
||||
<div role="group" aria-label="Разделы трафика" className="flex items-center overflow-x-auto px-3 sm:px-6">
|
||||
{GROUP_MODES.map(({ mode, icon, label }) => (
|
||||
<button key={mode} onClick={() => handleModeChange(mode)}
|
||||
<button type="button" aria-pressed={effectiveMode === mode} key={mode} onClick={() => handleModeChange(mode)}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors -mb-px",
|
||||
effectiveMode === mode
|
||||
@@ -1224,6 +1224,7 @@ export default function TrafficPage() {
|
||||
<div role="group" aria-label="Источник потоков" className="flex gap-1">
|
||||
<button
|
||||
type="button"
|
||||
aria-pressed={flowScope === "servers"}
|
||||
onClick={() => { setFlowScope("servers"); setFlowIface("__all__") }}
|
||||
className={cn(
|
||||
"text-[10px] px-2 py-0.5 rounded border transition-colors",
|
||||
@@ -1236,6 +1237,7 @@ export default function TrafficPage() {
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-pressed={flowScope === "users"}
|
||||
onClick={() => { setFlowScope("users"); setFlowIface("__all__"); if (range === "30d") setRange("1h") }}
|
||||
className={cn(
|
||||
"text-[10px] px-2 py-0.5 rounded border transition-colors",
|
||||
@@ -1253,7 +1255,7 @@ export default function TrafficPage() {
|
||||
type="text"
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
placeholder="Поиск…"
|
||||
aria-label="Поиск потоков" placeholder="Поиск…"
|
||||
className="w-full pl-8 pr-3 h-8 text-xs bg-muted/50 border border-border rounded-md outline-none focus:border-primary transition-colors"
|
||||
/>
|
||||
</div>
|
||||
@@ -1341,7 +1343,7 @@ export default function TrafficPage() {
|
||||
type="text"
|
||||
value={search}
|
||||
onChange={e => setSearch(e.target.value)}
|
||||
placeholder="Поиск…"
|
||||
aria-label="Поиск трафика" placeholder="Поиск…"
|
||||
className="w-full pl-8 pr-3 h-8 text-xs bg-muted/50 border border-border rounded-md outline-none focus:border-primary transition-colors"
|
||||
/>
|
||||
</div>
|
||||
@@ -1350,7 +1352,7 @@ export default function TrafficPage() {
|
||||
<div className="flex gap-1 flex-wrap">
|
||||
<span className="text-[10px] text-muted-foreground self-center mr-0.5">Сортировка:</span>
|
||||
{visibleSortFields.map(({ field, label }) => (
|
||||
<button key={field} onClick={() => toggleSort(field)}
|
||||
<button type="button" aria-pressed={sortField === field} key={field} onClick={() => toggleSort(field)}
|
||||
className={cn(
|
||||
"text-[10px] px-2 py-0.5 rounded border transition-colors",
|
||||
sortField === field
|
||||
@@ -1391,6 +1393,7 @@ export default function TrafficPage() {
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className="text-[11px] text-muted-foreground mr-1">Интерфейс:</span>
|
||||
<button
|
||||
type="button" aria-pressed={hideDisabledIfaces}
|
||||
onClick={() => setHideDisabledIfaces((v) => !v)}
|
||||
className={cn(
|
||||
"inline-flex items-center rounded-full border px-2 py-0.5 text-[10px] font-medium transition-all",
|
||||
@@ -1402,6 +1405,7 @@ export default function TrafficPage() {
|
||||
{hideDisabledIfaces ? "Показать отключенные" : "Скрыть отключенные"}
|
||||
</button>
|
||||
<button
|
||||
type="button" aria-pressed={selectedIface === "__all__"}
|
||||
onClick={() => setSelectedIface("__all__")}
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-[10px] font-medium transition-all",
|
||||
@@ -1417,6 +1421,7 @@ export default function TrafficPage() {
|
||||
return (
|
||||
<button
|
||||
key={`${iface.name}:${index}`}
|
||||
type="button" aria-pressed={active}
|
||||
onClick={() => setSelectedIface(iface.name)}
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-[10px] font-medium transition-all",
|
||||
|
||||
Reference in new issue
Block a user