feat: Добавить новые компоненты и улучшения UX/UI, включая Breadcrumbs с динамическими фильтрами, ToastContainer для уведомлений и CommandPalette для глобального поиска. Обновить TableSkeleton с анимацией и добавить новые skeleton компоненты для карточек, списков и форм. Обновить документацию по новым компонентам и улучшениям.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m38s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m38s
This commit is contained in:
@@ -1,25 +1,80 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import { IconArrowLeft, IconFilter } from '@tabler/icons-react'
|
||||
|
||||
function Breadcrumbs({ items = [] }) {
|
||||
/**
|
||||
* Улучшенный компонент Breadcrumbs с поддержкой:
|
||||
* - Динамических фильтров
|
||||
* - Счетчиков результатов
|
||||
* - Кнопки "Назад" с сохранением состояния
|
||||
*/
|
||||
function Breadcrumbs({ items = [], showBack = false, filterInfo = null, count = null }) {
|
||||
const navigate = useNavigate()
|
||||
|
||||
if (!Array.isArray(items) || items.length === 0) return null
|
||||
|
||||
const handleBack = () => {
|
||||
navigate(-1)
|
||||
}
|
||||
|
||||
return (
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol className="breadcrumb">
|
||||
{items.map((it, idx) => (
|
||||
<li key={idx} className={`breadcrumb-item${idx === items.length - 1 ? ' active' : ''}`} aria-current={idx === items.length - 1 ? 'page' : undefined}>
|
||||
{it.to && idx !== items.length - 1 ? (
|
||||
<Link to={it.to}>{it.label}</Link>
|
||||
) : (
|
||||
<span>{it.label}</span>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</nav>
|
||||
<div className="d-flex align-items-center gap-2 flex-wrap">
|
||||
{/* Кнопка "Назад" */}
|
||||
{showBack && (
|
||||
<button
|
||||
className="btn btn-ghost-secondary btn-sm btn-icon"
|
||||
onClick={handleBack}
|
||||
title="Назад"
|
||||
aria-label="Назад"
|
||||
>
|
||||
<IconArrowLeft size={18} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Breadcrumbs */}
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol className="breadcrumb mb-0">
|
||||
{items.map((it, idx) => {
|
||||
const isLast = idx === items.length - 1
|
||||
return (
|
||||
<li key={idx} className={`breadcrumb-item${isLast ? ' active' : ''}`} aria-current={isLast ? 'page' : undefined}>
|
||||
{it.to && !isLast ? (
|
||||
<Link to={it.to} className="text-decoration-none">
|
||||
{it.label}
|
||||
{it.count !== undefined && (
|
||||
<span className="badge bg-blue-lt text-blue ms-1">{it.count}</span>
|
||||
)}
|
||||
</Link>
|
||||
) : (
|
||||
<span>
|
||||
{it.label}
|
||||
{it.count !== undefined && (
|
||||
<span className="badge bg-blue-lt text-blue ms-1">{it.count}</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
{/* Информация о фильтрах */}
|
||||
{filterInfo && (
|
||||
<span className="badge bg-azure-lt text-azure d-inline-flex align-items-center">
|
||||
<IconFilter size={14} className="me-1" />
|
||||
{filterInfo}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* Общий счетчик */}
|
||||
{count !== null && count !== undefined && (
|
||||
<span className="text-muted small">
|
||||
({count} {count === 1 ? 'запись' : count < 5 ? 'записи' : 'записей'})
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Breadcrumbs
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user