diff --git a/frontend/src/ASNsNewManager.jsx b/frontend/src/ASNsNewManager.jsx index 6ca2894..5de97a2 100644 --- a/frontend/src/ASNsNewManager.jsx +++ b/frontend/src/ASNsNewManager.jsx @@ -674,27 +674,29 @@ function ASNsNewManager() {
- {/* Мета-информация будет показана внизу карточки */} - {loading ? ( - - ) : paginatedItems.length === 0 ? ( - - Импорт} - secondaryAction={} - /> - - ) : ( + + + {/* Таблица без карточной подложки */} + {loading ? ( + + ) : paginatedItems.length === 0 ? ( + + Импорт} + secondaryAction={} + /> + + ) : (
- +
@@ -824,7 +826,6 @@ function ASNsNewManager() { onPageChange={setCurrentPage} /> - diff --git a/frontend/src/DomainsNewManager.jsx b/frontend/src/DomainsNewManager.jsx index e73e635..6380f24 100644 --- a/frontend/src/DomainsNewManager.jsx +++ b/frontend/src/DomainsNewManager.jsx @@ -684,27 +684,29 @@ function DomainsNewManager() { - {/* Мета-информация будет показана внизу карточки */} - {loading ? ( - - ) : paginatedItems.length === 0 ? ( - - Импорт} - secondaryAction={} - /> - - ) : ( + + + {/* Таблица без карточной подложки (только горизонтальные разделители) */} + {loading ? ( + + ) : paginatedItems.length === 0 ? ( + + Импорт} + secondaryAction={} + /> + + ) : (
- +
@@ -854,9 +856,9 @@ function DomainsNewManager() {
- )} - {/* Пагинация */} - - {/* Мета-информация будет показана внизу карточки */} - {loading ? ( - - ) : paginatedItems.length === 0 ? ( - - Импорт} - secondaryAction={} - /> - - ) : ( + + + {/* Таблица без карточной подложки */} + {loading ? ( + + ) : paginatedItems.length === 0 ? ( + + Импорт} + secondaryAction={} + /> + + ) : (
- +
{hasCheckbox && ( @@ -18,7 +22,7 @@ export default function TableSkeleton({ rows = 10, cols = 3, hasCheckbox = false ); return (
-
@@ -1057,7 +1059,6 @@ function IPRangesManager() { onPageChange={setCurrentPage} /> - diff --git a/frontend/src/components/DataTable.jsx b/frontend/src/components/DataTable.jsx index a4ad188..c8e88c2 100644 --- a/frontend/src/components/DataTable.jsx +++ b/frontend/src/components/DataTable.jsx @@ -36,6 +36,7 @@ import Tooltip from './Tooltip.jsx'; * @param {number} props.skeletonRows - Количество строк скелетона (default: 10) * @param {boolean} props.striped - Чередование фона строк (Tabler UX, default: true) * @param {boolean} props.compact - Уменьшенные отступы ячеек (default: false) + * @param {boolean} props.flat - Таблица без карточной подложки: только горизонтальные разделители (default: false) */ function DataTable({ columns = [], @@ -60,6 +61,7 @@ function DataTable({ skeletonRows = 10, striped = true, compact = false, + flat = false, }) { const hasActions = onEdit || onDelete || onCopy || actions.length > 0; const isEditing = (item) => inlineEdit && item[itemKey] === inlineEdit.editingKey; @@ -220,8 +222,9 @@ function DataTable({ const allSelected = items.length > 0 && items.every(i => selectedItems.has(i[itemKey])); const tableClass = [ - 'table card-table table-vcenter table-nowrap mb-0', - striped && 'table-striped', + 'table table-vcenter table-nowrap mb-0', + flat ? 'table-flat' : 'card-table', + !flat && striped && 'table-striped', compact && 'table-sm', ].filter(Boolean).join(' '); diff --git a/frontend/src/components/TableSkeleton.jsx b/frontend/src/components/TableSkeleton.jsx index f52f5b4..e5d1397 100644 --- a/frontend/src/components/TableSkeleton.jsx +++ b/frontend/src/components/TableSkeleton.jsx @@ -1,7 +1,11 @@ /** * Skeleton loader для таблиц с анимацией pulse + * @param {boolean} flat - без карточной подложки (table-flat) */ -export default function TableSkeleton({ rows = 10, cols = 3, hasCheckbox = false }) { +export default function TableSkeleton({ rows = 10, cols = 3, hasCheckbox = false, flat = false }) { + const tableClass = flat + ? 'table table-flat table-vcenter table-nowrap mb-0' + : 'table card-table table-vcenter table-nowrap mb-0'; const Row = () => (
+
{hasCheckbox && } @@ -35,10 +39,13 @@ export default function TableSkeleton({ rows = 10, cols = 3, hasCheckbox = false ); } -export function TableEmpty({ cols = 3, children }) { +export function TableEmpty({ cols = 3, flat = false, children }) { + const tableClass = flat + ? 'table table-flat table-vcenter table-nowrap mb-0' + : 'table card-table table-vcenter table-nowrap mb-0'; return (
-
+
diff --git a/frontend/src/index.css b/frontend/src/index.css index c356da9..156004e 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -332,6 +332,55 @@ button:focus-visible, --tblr-table-bg-type: rgba(32, 107, 196, 0.12); } +/* ===== Table flat (без карточной подложки, как UniFi) ===== */ +/* Только горизонтальные разделители, thead темнее, без вертикальных границ */ +.table-flat { + --tblr-table-border-color: var(--tblr-border-color); + background: transparent; +} +.table-flat thead th { + font-weight: 600; + border-top: none; + border-left: none; + border-right: none; + border-bottom: 1px solid var(--tblr-table-border-color); + background: var(--tblr-bg-surface-secondary, rgba(0, 0, 0, 0.03)); + color: var(--tblr-body-color); + padding: 0.75rem 1rem; + white-space: nowrap; +} +.table-flat tbody td { + border-top: none; + border-left: none; + border-right: none; + border-bottom: 1px solid var(--tblr-table-border-color); + background: transparent; + padding: 0.75rem 1rem; + vertical-align: middle; +} +.table-flat tbody tr:hover td { + background: var(--tblr-bg-surface-tertiary, rgba(0, 0, 0, 0.02)); +} +.table-flat tbody tr.table-selected td, +.table-flat tbody tr.table-active td { + background: rgba(32, 107, 196, 0.08); +} +.table-flat tbody tr.table-selected:hover td, +.table-flat tbody tr.table-active:hover td { + background: rgba(32, 107, 196, 0.12); +} +/* В тёмной теме — чуть другие оттенки для thead */ +[data-bs-theme="dark"] .table-flat thead th { + background: rgba(255, 255, 255, 0.06); +} +[data-bs-theme="dark"] .table-flat tbody tr:hover td { + background: rgba(255, 255, 255, 0.04); +} +[data-bs-theme="dark"] .table-flat tbody tr.table-selected td, +[data-bs-theme="dark"] .table-flat tbody tr.table-active td { + background: rgba(32, 107, 196, 0.15); +} + .user-select-none { user-select: none; -webkit-user-select: none;