diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 25a1e88..ff62c5a 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,6 +8,7 @@
"name": "frontend",
"version": "0.0.0",
"dependencies": {
+ "@tabler/core": "^1.3.2",
"@tabler/icons-react": "^3.34.0",
"axios": "^1.10.0",
"bootstrap": "^5.3.7",
@@ -642,6 +643,42 @@
"tslib": "^2.8.0"
}
},
+ "node_modules/@tabler/core": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@tabler/core/-/core-1.3.2.tgz",
+ "integrity": "sha512-QDVJbv48YJrahBLdxYkLi6NutQv4jGbkUWyzxE2NcNJ3s3GGpRx98JmbAoN92NZKNmf26vZdW6k2Q5haVKlS4A==",
+ "license": "MIT",
+ "dependencies": {
+ "@popperjs/core": "^2.11.8",
+ "bootstrap": "5.3.6"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/codecalm"
+ }
+ },
+ "node_modules/@tabler/core/node_modules/bootstrap": {
+ "version": "5.3.6",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.6.tgz",
+ "integrity": "sha512-jX0GAcRzvdwISuvArXn3m7KZscWWFAf1MKBcnzaN02qWMb3jpMoUX4/qgeiGzqyIb4ojulRzs89UCUmGcFSzTA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/twbs"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/bootstrap"
+ }
+ ],
+ "license": "MIT",
+ "peerDependencies": {
+ "@popperjs/core": "^2.11.8"
+ }
+ },
"node_modules/@tabler/icons": {
"version": "3.34.0",
"resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.34.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 8093a2c..ed7ac8b 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "@tabler/core": "^1.3.2",
"@tabler/icons-react": "^3.34.0",
"axios": "^1.10.0",
"bootstrap": "^5.3.7",
diff --git a/frontend/src/App.css b/frontend/src/App.css
index 2e8e033..5ceeec8 100644
--- a/frontend/src/App.css
+++ b/frontend/src/App.css
@@ -1,696 +1,16 @@
-#root {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
-}
+/* Custom styles for S3 Lists Manager */
+/* Most styles are now provided by @tabler/core */
-.logo {
- height: 6em;
- padding: 1.5em;
- will-change: filter;
- transition: filter 300ms;
-}
-.logo:hover {
- filter: drop-shadow(0 0 2em #646cffaa);
-}
-.logo.react:hover {
- filter: drop-shadow(0 0 2em #61dafbaa);
-}
-
-@keyframes logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
-
-@media (prefers-reduced-motion: no-preference) {
- a:nth-of-type(2) .logo {
- animation: logo-spin infinite 20s linear;
- }
-}
-
-.card {
- padding: 2em;
-}
-
-.read-the-docs {
- color: #888;
-}
-
-/* Tabler CSS Variables */
-:root {
- --tblr-primary: #206bc4;
- --tblr-primary-rgb: 32, 107, 196;
- --tblr-secondary: #6c757d;
- --tblr-secondary-rgb: 108, 117, 125;
- --tblr-success: #2fb344;
- --tblr-success-rgb: 47, 179, 68;
- --tblr-info: #467fd0;
- --tblr-info-rgb: 70, 127, 208;
- --tblr-warning: #f59f00;
- --tblr-warning-rgb: 245, 159, 0;
- --tblr-danger: #d63939;
- --tblr-danger-rgb: 214, 57, 57;
- --tblr-light: #f8f9fa;
- --tblr-light-rgb: 248, 249, 250;
- --tblr-dark: #1e293b;
- --tblr-dark-rgb: 30, 41, 59;
- --tblr-body-bg: #f5f6f7;
- --tblr-body-color: #1e293b;
- --tblr-border-color: #e9ecef;
- --tblr-border-radius: 0.375rem;
- --tblr-border-radius-sm: 0.25rem;
- --tblr-border-radius-lg: 0.5rem;
- --tblr-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
- --tblr-box-shadow-sm: 0 0.0625rem 0.125rem rgba(0, 0, 0, 0.075);
- --tblr-box-shadow-lg: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
- --tblr-font-family-sans-serif: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
- --tblr-font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
- --tblr-font-size-base: 0.875rem;
- --tblr-line-height-base: 1.5;
- --tblr-heading-font-weight: 600;
- --tblr-btn-font-weight: 500;
- --tblr-btn-border-radius: 0.375rem;
- --tblr-btn-padding-x: 0.75rem;
- --tblr-btn-padding-y: 0.375rem;
- --tblr-input-border-radius: 0.375rem;
- --tblr-input-padding-x: 0.75rem;
- --tblr-input-padding-y: 0.375rem;
- --tblr-card-border-radius: 0.5rem;
- --tblr-card-border-width: 0;
- --tblr-card-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
- --tblr-navbar-height: 3.5rem;
- --tblr-sidebar-width: 16rem;
- --tblr-sidebar-width-md: 12rem;
- --tblr-sidebar-width-sm: 4rem;
-}
-
-/* Base Styles */
-* {
- box-sizing: border-box;
-}
-
-body {
- font-family: var(--tblr-font-family-sans-serif);
- font-size: var(--tblr-font-size-base);
- line-height: var(--tblr-line-height-base);
- color: var(--tblr-body-color);
- background-color: var(--tblr-body-bg);
- margin: 0;
- padding: 0;
-}
-
-/* Page Layout */
-.page {
- min-height: 100vh;
- display: flex;
- flex-direction: column;
-}
-
-.page-wrapper {
- flex: 1;
- display: flex;
- flex-direction: column;
-}
-
-.page-body {
- flex: 1;
- padding: 1.5rem 0;
-}
-
-.page-header {
- padding: 1.5rem 0;
- border-bottom: 1px solid var(--tblr-border-color);
- margin-bottom: 1.5rem;
-}
-
-.page-title {
- font-size: 1.5rem;
- font-weight: var(--tblr-heading-font-weight);
- margin: 0;
- color: var(--tblr-dark);
-}
-
-/* Navbar */
-.navbar {
- background-color: #fff;
- border-bottom: 1px solid var(--tblr-border-color);
- box-shadow: var(--tblr-box-shadow-sm);
- height: var(--tblr-navbar-height);
- padding: 0;
-}
-
-.navbar-brand {
- font-weight: var(--tblr-heading-font-weight);
- font-size: 1.25rem;
- color: var(--tblr-dark);
- text-decoration: none;
- display: flex;
- align-items: center;
-}
-
-.navbar-brand:hover {
- color: var(--tblr-primary);
-}
-
-.navbar-brand-icon {
- width: 1.5rem;
- height: 1.5rem;
-}
-
-.navbar-toggler {
- border: none;
- background: none;
- padding: 0.5rem;
- color: var(--tblr-secondary);
- cursor: pointer;
-}
-
-.navbar-toggler:hover {
- color: var(--tblr-dark);
-}
-
-.navbar-nav {
- list-style: none;
- margin: 0;
- padding: 0;
- display: flex;
- align-items: center;
-}
-
-.nav-item {
- margin: 0;
-}
-
-.nav-link {
- display: flex;
- align-items: center;
- padding: 0.75rem 1rem;
- color: var(--tblr-secondary);
- text-decoration: none;
- border-radius: var(--tblr-border-radius);
- transition: all 0.15s ease-in-out;
-}
-
-.nav-link:hover {
- color: var(--tblr-dark);
- background-color: var(--tblr-light);
-}
-
-.nav-link.active {
- color: var(--tblr-primary);
- background-color: rgba(var(--tblr-primary-rgb), 0.1);
-}
-
-.nav-link-icon {
- width: 1.25rem;
- height: 1.25rem;
- margin-right: 0.5rem;
-}
-
-.nav-link-title {
- font-weight: 500;
-}
-
-/* Avatar */
+/* Custom avatar background */
.avatar {
- display: inline-block;
- width: 2rem;
- height: 2rem;
- border-radius: 50%;
- background-size: cover;
- background-position: center;
- background-repeat: no-repeat;
+ background-image: url('data:image/svg+xml,');
}
-.avatar-sm {
- width: 1.5rem;
- height: 1.5rem;
-}
-
-/* Cards */
-.card {
- background-color: #fff;
- border: var(--tblr-card-border-width) solid var(--tblr-border-color);
- border-radius: var(--tblr-card-border-radius);
- box-shadow: var(--tblr-card-box-shadow);
- margin-bottom: 1.5rem;
- transition: box-shadow 0.15s ease-in-out;
-}
-
-.card:hover {
- box-shadow: var(--tblr-box-shadow-lg);
-}
-
-.card-md {
- max-width: 28rem;
-}
-
-.card-header {
- padding: 1rem 1.5rem;
- border-bottom: 1px solid var(--tblr-border-color);
- background-color: transparent;
-}
-
-.card-title {
- font-size: 1.125rem;
- font-weight: var(--tblr-heading-font-weight);
- margin: 0;
- color: var(--tblr-dark);
- display: flex;
- align-items: center;
-}
-
-.card-body {
- padding: 1.5rem;
-}
-
-.card-actions {
- display: flex;
- align-items: center;
- gap: 0.5rem;
-}
-
-/* Stats Cards */
-.h3 {
- font-size: 1.75rem;
- font-weight: var(--tblr-heading-font-weight);
- margin: 0;
- color: var(--tblr-dark);
-}
-
-.mb-1 {
- margin-bottom: 0.25rem !important;
-}
-
-/* Buttons */
-.btn {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- padding: var(--tblr-btn-padding-y) var(--tblr-btn-padding-x);
- font-size: var(--tblr-font-size-base);
- font-weight: var(--tblr-btn-font-weight);
- line-height: 1.5;
- border: 1px solid transparent;
- border-radius: var(--tblr-btn-border-radius);
- cursor: pointer;
- transition: all 0.15s ease-in-out;
- text-decoration: none;
- white-space: nowrap;
-}
-
-.btn:hover {
- text-decoration: none;
- transform: translateY(-1px);
- box-shadow: var(--tblr-box-shadow);
-}
-
-.btn:disabled {
- opacity: 0.65;
- cursor: not-allowed;
- transform: none;
- box-shadow: none;
-}
-
-.btn-primary {
- background-color: var(--tblr-primary);
- border-color: var(--tblr-primary);
- color: #fff;
-}
-
-.btn-primary:hover {
- background-color: #1a5aa3;
- border-color: #1a5aa3;
- color: #fff;
-}
-
-.btn-secondary {
- background-color: var(--tblr-secondary);
- border-color: var(--tblr-secondary);
- color: #fff;
-}
-
-.btn-secondary:hover {
- background-color: #5a6268;
- border-color: #5a6268;
- color: #fff;
-}
-
-.btn-success {
- background-color: var(--tblr-success);
- border-color: var(--tblr-success);
- color: #fff;
-}
-
-.btn-success:hover {
- background-color: #28a745;
- border-color: #28a745;
- color: #fff;
-}
-
-.btn-warning {
- background-color: var(--tblr-warning);
- border-color: var(--tblr-warning);
- color: #fff;
-}
-
-.btn-warning:hover {
- background-color: #e0a800;
- border-color: #e0a800;
- color: #fff;
-}
-
-.btn-danger {
- background-color: var(--tblr-danger);
- border-color: var(--tblr-danger);
- color: #fff;
-}
-
-.btn-danger:hover {
- background-color: #c82333;
- border-color: #c82333;
- color: #fff;
-}
-
-.btn-outline-primary {
- background-color: transparent;
- border-color: var(--tblr-primary);
- color: var(--tblr-primary);
-}
-
-.btn-outline-primary:hover {
- background-color: var(--tblr-primary);
- border-color: var(--tblr-primary);
- color: #fff;
-}
-
-.btn-outline-secondary {
- background-color: transparent;
- border-color: var(--tblr-secondary);
- color: var(--tblr-secondary);
-}
-
-.btn-outline-secondary:hover {
- background-color: var(--tblr-secondary);
- border-color: var(--tblr-secondary);
- color: #fff;
-}
-
-.btn-outline-danger {
- background-color: transparent;
- border-color: var(--tblr-danger);
- color: var(--tblr-danger);
-}
-
-.btn-outline-danger:hover {
- background-color: var(--tblr-danger);
- border-color: var(--tblr-danger);
- color: #fff;
-}
-
-.btn-sm {
- padding: 0.25rem 0.5rem;
- font-size: 0.75rem;
-}
-
-.btn-list {
- display: flex;
- gap: 0.25rem;
-}
-
-/* Forms */
-.form-label {
- font-weight: 500;
- color: var(--tblr-dark);
- margin-bottom: 0.5rem;
-}
-
-.form-control {
- display: block;
- width: 100%;
- padding: var(--tblr-input-padding-y) var(--tblr-input-padding-x);
- font-size: var(--tblr-font-size-base);
- line-height: var(--tblr-line-height-base);
- color: var(--tblr-body-color);
- background-color: #fff;
- border: 1px solid var(--tblr-border-color);
- border-radius: var(--tblr-input-border-radius);
- transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
-}
-
-.form-control:focus {
- border-color: var(--tblr-primary);
- outline: 0;
- box-shadow: 0 0 0 0.2rem rgba(var(--tblr-primary-rgb), 0.25);
-}
-
-.form-control-sm {
- padding: 0.25rem 0.5rem;
- font-size: 0.75rem;
-}
-
-.form-footer {
- margin-top: 1rem;
- padding-top: 1rem;
- border-top: 1px solid var(--tblr-border-color);
-}
-
-/* Input Icon */
-.input-icon {
- position: relative;
-}
-
-.input-icon .icon {
- position: absolute;
- left: 0.75rem;
- top: 50%;
- transform: translateY(-50%);
- color: var(--tblr-secondary);
- z-index: 1;
-}
-
-.input-icon .form-control {
- padding-left: 2.5rem;
-}
-
-/* Tables */
-.table {
- width: 100%;
- margin-bottom: 1rem;
- color: var(--tblr-body-color);
- border-collapse: collapse;
-}
-
-.table th,
-.table td {
- padding: 0.75rem;
- vertical-align: top;
- border-top: 1px solid var(--tblr-border-color);
-}
-
-.table thead th {
- vertical-align: bottom;
- border-bottom: 2px solid var(--tblr-border-color);
- font-weight: 600;
- color: var(--tblr-dark);
- background-color: var(--tblr-light);
-}
-
-.table tbody tr:hover {
- background-color: rgba(var(--tblr-primary-rgb), 0.05);
-}
-
-.table-vcenter td {
- vertical-align: middle;
-}
-
-.card-table {
- margin-bottom: 0;
-}
-
-.card-table th:first-child,
-.card-table td:first-child {
- padding-left: 1.5rem;
-}
-
-.card-table th:last-child,
-.card-table td:last-child {
- padding-right: 1.5rem;
-}
-
-/* Badges */
-.badge {
- display: inline-block;
- padding: 0.25rem 0.5rem;
- font-size: 0.75rem;
- font-weight: 500;
- line-height: 1;
- text-align: center;
- white-space: nowrap;
- vertical-align: baseline;
- border-radius: var(--tblr-border-radius-sm);
-}
-
-.bg-blue-lt {
- background-color: rgba(var(--tblr-primary-rgb), 0.1);
- color: var(--tblr-primary);
-}
-
-/* Alerts */
-.alert {
- position: relative;
- padding: 1rem 1.5rem;
- margin-bottom: 1rem;
- border: 1px solid transparent;
- border-radius: var(--tblr-border-radius);
-}
-
-.alert-danger {
- color: #721c24;
- background-color: #f8d7da;
- border-color: #f5c6cb;
-}
-
-.alert-success {
- color: #155724;
- background-color: #d4edda;
- border-color: #c3e6cb;
-}
-
-.alert-dismissible {
- padding-right: 3rem;
-}
-
-.btn-close {
- position: absolute;
- top: 0;
- right: 0;
- z-index: 2;
- padding: 1rem 1.5rem;
- background: transparent;
- border: 0;
- cursor: pointer;
-}
-
-.btn-close::before {
- content: "×";
- font-size: 1.5rem;
- font-weight: 700;
- line-height: 1;
- color: #000;
- opacity: 0.5;
-}
-
-.btn-close:hover::before {
- opacity: 0.75;
-}
-
-.alert-icon {
- width: 1.25rem;
- height: 1.25rem;
- margin-right: 0.5rem;
-}
-
-/* Empty States */
-.empty {
- text-align: center;
- padding: 3rem 1rem;
-}
-
-.empty-icon {
- margin-bottom: 1rem;
-}
-
-.empty-icon .icon {
- width: 3rem;
- height: 3rem;
- color: var(--tblr-secondary);
-}
-
-.empty-title {
- font-size: 1.25rem;
- font-weight: var(--tblr-heading-font-weight);
- color: var(--tblr-dark);
- margin: 0 0 0.5rem 0;
-}
-
-.empty-subtitle {
- font-size: var(--tblr-font-size-base);
- margin: 0;
-}
-
-/* Icons */
-.icon {
- width: 1rem;
- height: 1rem;
- display: inline-block;
- vertical-align: middle;
-}
-
-/* Modal */
-.modal-backdrop {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: rgba(0, 0, 0, 0.5);
- z-index: 1050;
- display: flex;
- align-items: center;
- justify-content: center;
- backdrop-filter: blur(2px);
-}
-
-.modal-dialog {
- max-width: 500px;
- width: 90%;
- margin: 1.75rem auto;
- animation: modalFadeIn 0.3s ease-out;
-}
-
-.modal-content {
- background-color: #fff;
- border-radius: var(--tblr-card-border-radius);
- box-shadow: var(--tblr-box-shadow-lg);
- border: none;
-}
-
-.modal-header {
- padding: 1rem 1.5rem;
- border-bottom: 1px solid var(--tblr-border-color);
- display: flex;
- align-items: center;
-}
-
-.modal-title {
- font-size: 1.125rem;
- font-weight: var(--tblr-heading-font-weight);
- margin: 0;
- color: var(--tblr-dark);
-}
-
-.modal-body {
- padding: 1.5rem;
-}
-
-.modal-footer {
- padding: 1rem 1.5rem;
- border-top: 1px solid var(--tblr-border-color);
- display: flex;
- gap: 0.5rem;
- justify-content: flex-end;
-}
-
-@keyframes modalFadeIn {
+/* Custom animations */
+@keyframes fadeIn {
from {
opacity: 0;
- transform: translateY(-20px);
+ transform: translateY(10px);
}
to {
opacity: 1;
@@ -698,227 +18,28 @@ body {
}
}
-/* Utilities */
-.text-muted {
- color: var(--tblr-secondary) !important;
+.fade-in {
+ animation: fadeIn 0.3s ease-out;
}
-.text-center {
- text-align: center !important;
-}
-
-.font-weight-medium {
- font-weight: 500 !important;
-}
-
-.w-1 {
- width: 1rem !important;
-}
-
-.me-2 {
- margin-right: 0.5rem !important;
-}
-
-.mb-0 {
- margin-bottom: 0 !important;
-}
-
-.mb-3 {
- margin-bottom: 1rem !important;
-}
-
-.mt-1 {
- margin-top: 0.25rem !important;
-}
-
-.mt-3 {
- margin-top: 1rem !important;
-}
-
-.py-4 {
- padding-top: 1.5rem !important;
- padding-bottom: 1.5rem !important;
-}
-
-/* Footer */
-.footer {
- background-color: transparent;
- border-top: 1px solid var(--tblr-border-color);
- padding: 1rem 0;
- margin-top: auto;
-}
-
-.footer-transparent {
- background-color: transparent;
-}
-
-.list-inline {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-.list-inline-item {
- display: inline-block;
-}
-
-.list-inline-item:not(:last-child) {
- margin-right: 0.5rem;
-}
-
-.list-inline-dots .list-inline-item:not(:last-child)::after {
- content: "·";
- margin-left: 0.5rem;
- color: var(--tblr-secondary);
-}
-
-.link-secondary {
- color: var(--tblr-secondary);
- text-decoration: none;
-}
-
-.link-secondary:hover {
- color: var(--tblr-dark);
- text-decoration: underline;
-}
-
-/* Responsive */
-@media (max-width: 768px) {
- .navbar-expand-md .navbar-collapse {
- display: none;
- }
-
- .navbar-expand-md.show .navbar-collapse {
- display: block;
- position: absolute;
- top: 100%;
- left: 0;
- right: 0;
- background-color: #fff;
- border-top: 1px solid var(--tblr-border-color);
- box-shadow: var(--tblr-box-shadow);
- z-index: 1000;
- }
-
- .navbar-expand-md .navbar-nav {
- flex-direction: column;
- }
-
- .navbar-expand-md .nav-item {
- width: 100%;
- }
-
- .navbar-expand-md .nav-link {
- padding: 1rem;
- border-radius: 0;
- }
-
- .card-actions {
- flex-direction: column;
- gap: 0.5rem;
- }
-
- .btn-list {
- flex-direction: column;
- }
-
- .modal-footer {
- flex-direction: column;
- }
-
- .modal-footer .btn {
- width: 100%;
- }
-}
-
-/* Container */
-.container-xl {
- max-width: 1200px;
- margin: 0 auto;
- padding: 0 1rem;
-}
-
-/* Row and Col */
-.row {
- display: flex;
- flex-wrap: wrap;
- margin: 0 -0.75rem;
-}
-
-.col,
-.col-lg-4,
-.col-lg-8 {
- padding: 0 0.75rem;
-}
-
-.col {
- flex: 1;
-}
-
-.col-lg-4 {
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
-}
-
-.col-lg-8 {
- flex: 0 0 66.666667%;
- max-width: 66.666667%;
-}
-
-@media (max-width: 992px) {
- .col-lg-4,
- .col-lg-8 {
- flex: 0 0 100%;
- max-width: 100%;
- }
-}
-
-/* Spinner */
-.spinner-border {
- display: inline-block;
- width: 2rem;
- height: 2rem;
- border: 0.25em solid currentColor;
- border-right-color: transparent;
- border-radius: 50%;
- animation: spinner-border 0.75s linear infinite;
-}
-
-@keyframes spinner-border {
- to {
- transform: rotate(360deg);
- }
-}
-
-.text-primary {
- color: var(--tblr-primary) !important;
-}
-
-.visually-hidden {
- position: absolute !important;
- width: 1px !important;
- height: 1px !important;
- padding: 0 !important;
- margin: -1px !important;
- overflow: hidden !important;
- clip: rect(0, 0, 0, 0) !important;
- white-space: nowrap !important;
- border: 0 !important;
-}
-
-/* Enhanced hover effects */
-.card:hover .card-title {
- color: var(--tblr-primary);
+/* Custom hover effects */
+.card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
+ transition: all 0.3s ease;
}
.btn:hover {
transform: translateY(-1px);
- box-shadow: var(--tblr-box-shadow);
+ transition: all 0.2s ease;
}
-.form-control:focus {
- transform: translateY(-1px);
- box-shadow: 0 0 0 0.2rem rgba(var(--tblr-primary-rgb), 0.25), var(--tblr-box-shadow);
+/* Custom focus states */
+.btn:focus,
+.form-control:focus,
+.nav-link:focus {
+ outline: 2px solid var(--tblr-primary);
+ outline-offset: 2px;
}
/* Loading states */
@@ -927,45 +48,27 @@ body {
box-shadow: none !important;
}
-/* Focus states for accessibility */
-.btn:focus,
-.form-control:focus,
-.nav-link:focus {
- outline: 2px solid var(--tblr-primary);
- outline-offset: 2px;
+/* Custom responsive adjustments */
+@media (max-width: 992px) {
+ .page-wrapper {
+ margin-left: 0;
+ }
}
-/* Dark mode support (future enhancement) */
+/* Custom dark mode support */
@media (prefers-color-scheme: dark) {
- :root {
- --tblr-body-bg: #1a1a1a;
- --tblr-body-color: #e9ecef;
- --tblr-dark: #f8f9fa;
- --tblr-border-color: #2d3748;
- }
-
.card {
- background-color: #2d3748;
- border-color: #4a5568;
+ background-color: var(--tblr-dark);
+ border-color: var(--tblr-border-color);
}
.navbar {
- background-color: #2d3748;
- border-color: #4a5568;
+ background-color: var(--tblr-dark);
+ border-color: var(--tblr-border-color);
}
- .form-control {
- background-color: #4a5568;
- border-color: #718096;
- color: #e9ecef;
- }
-
- .table {
- color: #e9ecef;
- }
-
- .table thead th {
- background-color: #4a5568;
- color: #f8f9fa;
+ .navbar-vertical {
+ background-color: var(--tblr-dark);
+ border-color: var(--tblr-border-color);
}
}
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index f8cd04f..c210dad 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -6,36 +6,96 @@ import {
IconNetwork,
IconSettings,
IconMenu2,
- IconX
+ IconX,
+ IconHome,
+ IconDatabase,
+ IconUsers,
+ IconBell,
+ IconSearch,
+ IconChevronDown,
+ IconLogout,
+ IconUser,
+ IconDashboard,
+ IconFileText,
+ IconCloud,
+ IconShield,
+ IconActivity
} from '@tabler/icons-react';
import DataManager from './DataManager';
import './App.css';
function App() {
const [sidebarOpen, setSidebarOpen] = useState(false);
- const [activeTab, setActiveTab] = useState('domains');
+ const [activeTab, setActiveTab] = useState('dashboard');
+ const [notifications] = useState([
+ { id: 1, title: 'Новый домен добавлен', message: 'example.com был добавлен в список', time: '2 мин назад' },
+ { id: 2, title: 'Изменения сохранены', message: 'Список AS обновлен в S3', time: '5 мин назад' }
+ ]);
const toggleSidebar = () => setSidebarOpen(!sidebarOpen);
+ const sidebarItems = [
+ { id: 'dashboard', title: 'Dashboard', icon: IconDashboard, badge: null },
+ { id: 'domains', title: 'Домены', icon: IconWorld, badge: '12' },
+ { id: 'asns', title: 'AS', icon: IconNetwork, badge: '8' },
+ { id: 'files', title: 'Файлы', icon: IconFileText, badge: null },
+ { id: 'cloud', title: 'Облако', icon: IconCloud, badge: null },
+ { id: 'security', title: 'Безопасность', icon: IconShield, badge: null },
+ { id: 'activity', title: 'Активность', icon: IconActivity, badge: '3' },
+ { id: 'settings', title: 'Настройки', icon: IconSettings, badge: null }
+ ];
+
+ const renderContent = () => {
+ switch (activeTab) {
+ case 'dashboard':
+ return