From 07b402379c8f6ce9ed74404acd3a8bb92ef2bfe2 Mon Sep 17 00:00:00 2001 From: Syarif Ubaidillah Date: Fri, 3 Jul 2026 16:02:46 +0700 Subject: [PATCH] feat: integrate CoreUI for improved layout and UI, implement dynamic theme switching with dark mode support, and enhance DataTables with custom feature configurations. --- .ai/mcp/mcp.json | 18 +- .../DataTables/Identity/UserDataTable.php | 20 +- package-lock.json | 37 +- package.json | 1 + resources/js/bootstrap.js | 96 +- resources/js/plugin/datatables.js | 20 +- resources/js/sidebar.js | 31 - resources/scss/_avatar.scss | 153 -- resources/scss/_border.scss | 34 - resources/scss/_button.scss | 39 - resources/scss/_custom.scss | 138 -- resources/scss/_icon-shape.scss | 50 - resources/scss/_utilities.scss | 59 - resources/scss/_variables.scss | 141 -- resources/scss/app.scss | 74 +- resources/scss/plugin/apexchart.scss | 3 +- resources/scss/plugin/datatables.scss | 383 ++-- resources/scss/plugin/filepond.scss | 47 +- resources/scss/plugin/select2.scss | 453 ++--- resources/scss/plugin/sweetalert.scss | 90 +- resources/scss/style.css | 1618 +++++++++++++++++ .../views/components/layouts/app.blade.php | 52 +- .../components/layouts/nav/sidebar.blade.php | 38 +- .../layouts/nav/sidebar/nav-link.blade.php | 5 +- .../components/layouts/nav/topbar.blade.php | 74 +- .../language-switcher.blade.php | 2 +- .../⚔notification/notification.blade.php | 2 +- .../pages/identity/users/index.blade.php | 39 +- 28 files changed, 2501 insertions(+), 1216 deletions(-) delete mode 100644 resources/js/sidebar.js delete mode 100644 resources/scss/_avatar.scss delete mode 100644 resources/scss/_border.scss delete mode 100644 resources/scss/_button.scss delete mode 100644 resources/scss/_custom.scss delete mode 100644 resources/scss/_icon-shape.scss delete mode 100644 resources/scss/_utilities.scss delete mode 100644 resources/scss/_variables.scss create mode 100644 resources/scss/style.css diff --git a/.ai/mcp/mcp.json b/.ai/mcp/mcp.json index 40b4d24..25352be 100644 --- a/.ai/mcp/mcp.json +++ b/.ai/mcp/mcp.json @@ -1,11 +1,11 @@ { - "mcpServers": { - "laravel-boost": { - "command": "php", - "args": [ - "artisan", - "boost:mcp" - ] - } + "mcpServers": { + "laravel-boost": { + "command": "php", + "args": [ + "artisan", + "boost:mcp" + ] } -} + } +} \ No newline at end of file diff --git a/app/Http/DataTables/Identity/UserDataTable.php b/app/Http/DataTables/Identity/UserDataTable.php index 228da29..f96f5ab 100644 --- a/app/Http/DataTables/Identity/UserDataTable.php +++ b/app/Http/DataTables/Identity/UserDataTable.php @@ -103,12 +103,30 @@ class UserDataTable extends DataTable ->orderBy(-1) ->layout([ 'topStart' => [ + 'rowClass' => 'row gap-1', 'className' => 'col-md-auto me-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-start align-items-center align-items-md-start gap-1', 'features' => ['buttons', 'pageLength'], ], 'topEnd' => [ 'className' => 'col-md-auto ms-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-end align-items-center align-items-md-start gap-1', - 'features' => ['status-filter', 'role-filter', 'search'], + 'features' => [ + // 1. Pass your first custom filter layout option cleanly mapping to the target element ID + [ + 'custom-features' => [ + 'targetId' => 'template-role-filter', + 'style' => 'width: 200px;' + ] + ], + // 2. Pass your second custom filter layout option + [ + 'custom-features' => [ + 'targetId' => 'template-status-filter', + 'style' => 'width: 200px;' + ] + ], + // Keep your original native layout features running seamlessly alongside them + 'search' + ], ], 'bottomStart' => 'info', diff --git a/package-lock.json b/package-lock.json index 84952e1..b3b0ed7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10 +1,11 @@ { - "name": "laravel-base", + "name": "keuangan-uniba", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { + "@coreui/coreui": "^5.8.0", "datatables.net-bs5": "^2.3.7", "datatables.net-dt": "^2.3.7", "datatables.net-fixedcolumns": "^5.0.5", @@ -32,6 +33,24 @@ "vite": "^8.0.7" } }, + "node_modules/@coreui/coreui": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@coreui/coreui/-/coreui-5.8.0.tgz", + "integrity": "sha512-92v/kpla3YaGzAchwSEALRoouV0EQMiljEcaMQ7UqbMBISSoRCUtO+UbeiVBmRQTOdaJSJIu4rh3IwP+2QbKcQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/coreui" + } + ], + "license": "MIT", + "dependencies": { + "html-entities": "^2.6.0" + }, + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, "node_modules/@emnapi/core": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", @@ -2094,6 +2113,22 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, "node_modules/https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", diff --git a/package.json b/package.json index 71d29bb..17a500b 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "vite": "^8.0.7" }, "dependencies": { + "@coreui/coreui": "^5.8.0", "datatables.net-bs5": "^2.3.7", "datatables.net-dt": "^2.3.7", "datatables.net-fixedcolumns": "^5.0.5", diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js index e251574..f4123a7 100644 --- a/resources/js/bootstrap.js +++ b/resources/js/bootstrap.js @@ -1,4 +1,94 @@ -import * as bootstrap from 'bootstrap'; -import './sidebar.js' +import * as coreui from '@coreui/coreui'; +window.coreui = coreui; -window.bootstrap = bootstrap +const THEME = 'coreui-free-bootstrap-admin-template-theme'; + +// Helper functions declared outside of event scopes so they stay clean +const getStoredTheme = () => localStorage.getItem(THEME); +const setStoredTheme = theme => localStorage.setItem(THEME, theme); + +const getPreferredTheme = () => { + const storedTheme = getStoredTheme(); + if (storedTheme) return storedTheme; + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; +}; + +const setTheme = theme => { + if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.documentElement.setAttribute('data-coreui-theme', 'dark'); + } else { + document.documentElement.setAttribute('data-coreui-theme', theme); + } + document.documentElement.dispatchEvent(new Event('ColorSchemeChange')); +}; + +const showActiveTheme = theme => { + const btnToActive = document.querySelector(`[data-coreui-theme-value="${theme}"]`); + if (!btnToActive) return; // Guard clause in case toggle buttons aren't on the current page + + const activeThemeIcon = document.querySelector('.theme-icon-active'); + const svgOfActiveBtn = btnToActive.querySelector('svg'); + + for (const element of document.querySelectorAll('[data-coreui-theme-value]')) { + element.classList.remove('active'); + } + + btnToActive.classList.add('active'); + + if (activeThemeIcon && svgOfActiveBtn) { + const useElement = svgOfActiveBtn.querySelector('use'); + if (useElement) { + const activeUseElement = activeThemeIcon.querySelector('use'); + if (activeUseElement) { + activeUseElement.setAttribute('xlink:href', useElement.getAttribute('xlink:href')); + } + } else { + activeThemeIcon.innerHTML = svgOfActiveBtn.innerHTML; + } + } +}; + +// 1. Run theme initialization immediately on file execution to prevent dark-mode flashbangs +(() => { + const urlParams = new URLSearchParams(window.location.href.split('?')[1]); + if (urlParams.get('theme') && ['auto', 'dark', 'light'].includes(urlParams.get('theme'))) { + localStorage.setItem(THEME, urlParams.get('theme')); + } + setTheme(getPreferredTheme()); +})(); + +// System preferences watcher +window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + const storedTheme = getStoredTheme(); + if (storedTheme !== 'light' && storedTheme !== 'dark') { + setTheme(getPreferredTheme()); + } +}); + +// 2. CORE LIVEWIRE FIX: Run UI bindings on every single page navigation step +document.addEventListener('livewire:navigated', () => { + const preferredTheme = getPreferredTheme(); + + // initiate sidebar toggle + const toggleButton = document.querySelector('.header-toggler'); + const sidebar = document.querySelector('.sidebar'); + if(toggleButton) { + toggleButton.addEventListener('click', () => { + window.coreui.Sidebar.getOrCreateInstance(sidebar).toggle(); + }) + } + + // Ensure the state continues to match after navigation + setTheme(preferredTheme); + showActiveTheme(preferredTheme); + + // Re-attach query click listeners to newly swapped DOM elements + for (const toggle of document.querySelectorAll('[data-coreui-theme-value]')) { + toggle.addEventListener('click', () => { + const theme = toggle.getAttribute('data-coreui-theme-value'); + setStoredTheme(theme); + setTheme(theme); + showActiveTheme(theme); + }); + } +}); diff --git a/resources/js/plugin/datatables.js b/resources/js/plugin/datatables.js index ab95177..ad8ba8d 100644 --- a/resources/js/plugin/datatables.js +++ b/resources/js/plugin/datatables.js @@ -5,8 +5,8 @@ window.ModulesFullyLoaded = false; window.DataTableLockedQueue = window.DataTableLockedQueue || []; import('laravel-datatables-vite').then(() => { - document.dispatchEvent(new CustomEvent('DOMContentLoaded')) window.ModulesFullyLoaded = true; + document.dispatchEvent(new CustomEvent('DOMContentLoaded')) window.checkAndFlushDataTables(); }); @@ -21,6 +21,24 @@ window.addEventListener('yajra:boot', (event) => { try { window.LaravelDataTables = window.LaravelDataTables || {}; + window.DataTable.feature.register('custom-features', function (settings, opts) { + let container = document.createElement('div'); + + // Fallback styles if none are provided dynamically + container.style = opts.style || 'width: 250px;'; + + // Look for a targeting template element or fallback to inline html string + if (opts.targetId) { + const template = document.getElementById(opts.targetId); + if (template) { + container.innerHTML = template.innerHTML; + } + } else if (opts.html) { + container.innerHTML = opts.html; + } + + return container; + }); window.LaravelDataTables[id] = $el.DataTable(config); } catch (e) { console.error(`Failed to boot DataTable [${id}]:`, e); diff --git a/resources/js/sidebar.js b/resources/js/sidebar.js deleted file mode 100644 index d26193a..0000000 --- a/resources/js/sidebar.js +++ /dev/null @@ -1,31 +0,0 @@ -const sidebar = document.getElementById('sidebar'); -const content = document.getElementById('content'); -const topbar = document.getElementById('topbar'); -const toggleBtn = document.getElementById('toggleBtn'); -const mobileBtn = document.getElementById('mobileBtn'); -const overlay = document.getElementById('overlay'); - -// Desktop collapse -if (toggleBtn) { - toggleBtn.addEventListener('click', () => { - if (sidebar) sidebar.classList.toggle('collapsed'); - if (content) content.classList.toggle('full'); - if (topbar) topbar.classList.toggle('full'); - }); -} - -// Mobile sidebar open -if (mobileBtn) { - mobileBtn.addEventListener('click', () => { - if (sidebar) sidebar.classList.add('mobile-show'); - if (overlay) overlay.classList.add('show'); - }); -} - -// šŸ”„ Click outside to close -if (overlay) { - overlay.addEventListener('click', () => { - if (sidebar) sidebar.classList.remove('mobile-show'); - if (overlay) overlay.classList.remove('show'); - }); -} \ No newline at end of file diff --git a/resources/scss/_avatar.scss b/resources/scss/_avatar.scss deleted file mode 100644 index b421e64..0000000 --- a/resources/scss/_avatar.scss +++ /dev/null @@ -1,153 +0,0 @@ -// Avatar -.avatar { - position: relative; - display: inline-block; - width: 3rem; - height: 3rem; -} - -// Avatar Size -.avatar-xs { - width: $avatar-size-xs; - height: $avatar-size-xs; -} - -.avatar-sm { - width: $avatar-size-sm; - height: $avatar-size-sm; -} - -.avatar-md { - width: $avatar-size-md; - height: $avatar-size-md; -} - -.avatar-lg { - width: $avatar-size-lg; - height: $avatar-size-lg; -} - -.avatar-xl { - width: $avatar-size-xl; - height: $avatar-size-xl; -} - -.avatar-xxl { - width: $avatar-size-xxl; - height: $avatar-size-xxl; -} - -// Avatar img -.avatar img { - width: 100%; - height: 100%; - -o-object-fit: cover; - object-fit: cover; -} - -.avatar-indicators { - position: relative; -} - -.avatar-indicators:before { - content: ''; - position: absolute; - bottom: 0px; - right: 5%; - width: 30%; - height: 30%; - border-radius: 50%; - border: 2px solid var(--#{$prefix}white); - display: table; -} - -.avatar-xxl.avatar-indicators:before { - bottom: 5px; - right: 17%; - width: 16%; - height: 16%; -} - -// Avatar indicators -.avatar-offline:before { - background-color: var(--#{$prefix}gray-400); -} - -.avatar-online:before { - background-color: $success; -} - -.avatar-away:before { - background-color: $warning; -} - -.avatar-busy:before { - background-color: $danger; -} - -.avatar-info:before { - background-color: $info; -} - -// Avatar intials -.avatar-initials { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: center; - justify-content: center; - -ms-flex-align: center; - align-items: center; - width: 100%; - height: 100%; - pointer-events: none; - text-transform: uppercase; -} - -// Color varient -.avatar-primary .avatar-initials { - color: var(--#{$prefix}white); - background-color: $primary; -} -.avatar-secondary .avatar-initials { - color: var(--#{$prefix}white); - background-color: $secondary; -} -.avatar-success .avatar-initials { - color: var(--#{$prefix}white); - background-color: $success; -} -.avatar-warning .avatar-initials { - color: var(--#{$prefix}white); - background-color: $warning; -} -.avatar-info .avatar-initials { - color: var(--#{$prefix}white); - background-color: $info; -} -.avatar-danger .avatar-initials { - color: var(--#{$prefix}white); - background-color: $danger; -} -.avatar-light .avatar-initials { - color: var(--#{$prefix}white); - background-color: $light; -} -.avatar-dark .avatar-initials { - color: var(--#{$prefix}white); - background-color: $dark; -} - -// Avatar Group -.avatar-group .avatar + .avatar { - margin-left: -1.2rem; -} - -.avatar-group .avatar:hover { - z-index: 2; -} - -// Avatar border -.avatar-group img, -.avatar-group .avatar .avatar-initials { - border: 2px solid var(--#{$prefix}white); -} diff --git a/resources/scss/_border.scss b/resources/scss/_border.scss deleted file mode 100644 index b63f975..0000000 --- a/resources/scss/_border.scss +++ /dev/null @@ -1,34 +0,0 @@ -// Border dashed - -.border-dashed { - --ds-border-style: dashed; -} - -.timeline-vertical { - position: relative; - .timeline-item { - .timeline-bar { - position: absolute; - height: 100px; - left: 5px; - top: 24px; - } - } -} -.timeline-vertical-height { - .timeline-item { - .timeline-bar { - height: calc(100% - 1rem) !important; - } - } -} - -// vr border -.vr { - display: inline-block; - align-self: stretch; - width: $vr-border-width; - min-height: 1em; - background-color: var(--#{$prefix}border-color) !important; - opacity: $hr-opacity; -} diff --git a/resources/scss/_button.scss b/resources/scss/_button.scss deleted file mode 100644 index c2b7670..0000000 --- a/resources/scss/_button.scss +++ /dev/null @@ -1,39 +0,0 @@ -.btn * { - // disable pointer event - pointer-events: none; -} - -.btn-icon { - position: relative; - display: -ms-inline-flexbox; - display: inline-flex; - -ms-flex-negative: 0; - flex-shrink: 0; - -ms-flex-pack: center; - justify-content: center; - -ms-flex-align: center; - align-items: center; - font-size: 0.92969rem; - font-weight: 400; - width: 2.5rem; - height: 2.5rem; - padding: 0; -} - -.btn-icon.btn-xs { - font-size: 0.75rem; - width: 1.75rem; - height: 1.75rem; -} - -.btn-icon.btn-sm { - font-size: 0.875rem; - width: 2.1875rem; - height: 2.1875rem; -} - -.btn-icon.btn-lg { - font-size: 1rem; - width: 3.36875rem; - height: 3.36875rem; -} \ No newline at end of file diff --git a/resources/scss/_custom.scss b/resources/scss/_custom.scss deleted file mode 100644 index 603e128..0000000 --- a/resources/scss/_custom.scss +++ /dev/null @@ -1,138 +0,0 @@ -.overlay { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, .45); - backdrop-filter: blur(1px); - display: none; - z-index: 1030; -} - -.overlay.show { - display: block; -} - -.sidebar { - width: 240px; - background: $white; - transition: width .3s, left .3s; - border-right: 1px solid $gray-200; - height: 100vh; - position: fixed; - top: 0; - left: 0; - padding-top: 60px; - z-index: 1030; - - .nav-link { - color: $gray-800; - padding: 8px 10px; - display: flex; - align-items: center; - font-size: 14px; - font-weight: 400; - gap: 12px; - white-space: nowrap; - margin: 1px 12px; - border-radius: 8px; - - &:hover { - color: $primary; - background-color: rgba($primary, 0.095); - } - - &.active { - color: $primary; - background-color: rgba($primary, 0.095); - } - - .ti { - font-size: 18px; - } - } - - .nav-text { - transition: opacity .2s; - } - - .logo-area { - position: absolute; - top: 0; - left: 0; - height: 60px; - width: 100%; - background: $white; - display: flex; - align-items: center; - gap: 10px; - padding-left: 17px; - color: $gray-800; - border-bottom: 1px solid $gray-200; - } -} - -.sidebar.collapsed { - width: 60px; - - .nav-link { - margin: 0 0px; - background-color: transparent; - padding: 8px 18px; - } - - .nav-text { - display: none; - } - - .logo-text { - display: none; - } -} - -.topbar { - height: 60px; - margin-left: 240px; - // transition: margin-left .3s; -} - -.topbar.full { - margin-left: 60px; -} - -.content { - margin-left: 240px; - // transition: margin-left .3s; - // padding: 20px; -} - -.content.full { - margin-left: 60px; -} - -@media (max-width: 992px) { - .sidebar { - left: -240px; - } - - .sidebar.mobile-show { - left: 0; - } - - .topbar { - margin-left: 0 !important; - width: 100% !important; - } - - .content { - margin-left: 0 !important; - } -} - -.min-vh-90 { - min-height: 90vh; -} - - -@import "./avatar"; -@import "./button"; -@import "./icon-shape"; -@import "./utilities"; \ No newline at end of file diff --git a/resources/scss/_icon-shape.scss b/resources/scss/_icon-shape.scss deleted file mode 100644 index 93ba461..0000000 --- a/resources/scss/_icon-shape.scss +++ /dev/null @@ -1,50 +0,0 @@ -// Icon shape - -.icon-xxs { - width: $icon-size-xxs; - height: $icon-size-xxs; - line-height: $icon-size-xxs; -} -.icon-xs { - width: $icon-size-xs; - height: $icon-size-xs; - line-height: $icon-size-xs; -} -.icon-sm { - width: $icon-size-sm; - height: $icon-size-sm; - line-height: $icon-size-sm; -} -.icon-md { - width: $icon-size-md; - height: $icon-size-md; - line-height: $icon-size-md; -} -.icon-lg { - width: $icon-size-lg; - height: $icon-size-lg; - line-height: $icon-size-lg; -} -.icon-xl { - width: $icon-size-xl; - height: $icon-size-xl; - line-height: $icon-size-xl; -} -.icon-xxl { - width: $icon-size-xxl; - height: $icon-size-xxl; - line-height: $icon-size-xxl; -} - -.icon-xxxl { - width: $icon-size-xxxl; - height: $icon-size-xxxl; - line-height: $icon-size-xxxl; -} -.icon-shape { - display: inline-flex; - align-items: center; - justify-content: center; - text-align: center; - vertical-align: middle; -} diff --git a/resources/scss/_utilities.scss b/resources/scss/_utilities.scss deleted file mode 100644 index a3db9e2..0000000 --- a/resources/scss/_utilities.scss +++ /dev/null @@ -1,59 +0,0 @@ -@import "bootstrap/scss/functions"; -@import "bootstrap/scss/variables"; -@import "bootstrap/scss/variables-dark"; -@import "bootstrap/scss/maps"; -@import "bootstrap/scss/mixins"; -@import "bootstrap/scss/utilities"; - -$utilities: map-merge( - $utilities, - ( - "font-size": ( - rfs: true, - responsive: true, - property: font-size, - class: fs, - values: $font-sizes -), -"position": ( - property: position, - responsive: true, - values: static relative absolute fixed sticky -), -"top": ( - property: top, - responsive: true, - values: $position-values -), -"bottom": ( - property: bottom, - responsive: true, - values: $position-values -), -"start": ( - property: left, - class: start, - responsive: true, - - values: $position-values -), -"end": ( - property: right, - class: end, - responsive: true, - values: $position-values -), -"translate-middle": ( - property: transform, - class: translate-middle, - responsive: true, - values: ( - null: translate(-50%, -50%), - x: translateX(-50%), - y: translateY(-50%), - ) -), - ) -); - -@import "bootstrap/scss/utilities/api"; \ No newline at end of file diff --git a/resources/scss/_variables.scss b/resources/scss/_variables.scss deleted file mode 100644 index 98d7d0b..0000000 --- a/resources/scss/_variables.scss +++ /dev/null @@ -1,141 +0,0 @@ -// Example: override Bootstrap color variables - -$gray-50: #fafafa !default; -$gray-100: #f5f5f5 !default; -$gray-200: #e5e5e5 !default; -$gray-300: #d4d4d4 !default; -$gray-400: #a3a3a3 !default; -$gray-500: #737373 !default; -$gray-600: #525252 !default; -$gray-700: #404040 !default; -$gray-800: #262626 !default; -$gray-900: #171717 !default; -$gray-950: #0a0a0a !default; - -$white: #ffffff !default; -$black: #000000 !default; - -$orange: #E66239 !default; -$red: #FB2C36 !default; -$green: #00C951 !default; -$cyan: #00B8DB !default; -$yellow: #F0B100 !default; - - -$primary: $orange !default; -$secondary: $gray-600 !default; -$success: $green !default; -$info: $cyan !default; -$warning: $yellow !default; -$danger: $red !default; - -$min-contrast-ratio: 2.5 !default; -$link-hover-decoration: none !default; -$link-color: $gray-700 !default; -$link-hover-color: $primary !default; - - -$light: $gray-100 !default; -$border-color: $gray-200 !default; -$border-color-translucent: $gray-200 !default; - -$enable-negative-margins: true !default; -$enable-rounded: true !default; - -$headings-font-weight: 400 !default; -$grid-gutter-width: 2.5rem !default; - -// scss-docs-start position-map -$position-values: ( - 0: 0, - 10: 10%, - 25: 25%, - 50: 50%, - 60: 60%, - 65:65%, - 70: 70%, - 75: 75%, - 100: 100%, - auto: auto -) !default; -// scss-docs-end position-map - - -// scss-docs-start spacer-variables-maps -$spacer: 1rem !default; -$spacers: ( - 0: 0, - 1: $spacer * 0.25, - // 4px - 2: $spacer * 0.5, - // 8px - 3: $spacer, - // 16px - 4: $spacer * 1.5, - // 24px - 5: $spacer * 2, - // 32px - 6: $spacer * 2.5, - // 40px - 7: $spacer * 3, - // 48px - 8: $spacer * 4, - // 64px - 9: $spacer * 5, - // 80px - 10: $spacer * 6, - // 96px - 11: $spacer * 8, - // 128px -) !default; -// scss-docs-end spacer-variables-maps - -$font-family-base: 'Poppins', sans-serif !default; -$font-size-root: null !default; -$font-size-base: .875rem !default; // Assumes the browser default, typically `16px` -$font-size-sm: $font-size-base * .85 !default; -$font-size-lg: $font-size-base * 1.25 !default; - -$font-xs: 0.75rem !default; - -$h1-font-size: $font-size-base * 2.5 !default; -$h2-font-size: $font-size-base * 2 !default; -$h3-font-size: $font-size-base * 1.75 !default; -$h4-font-size: $font-size-base * 1.5 !default; -$h5-font-size: $font-size-base * 1.25 !default; -$h6-font-size: $font-size-base !default; - -// scss-docs-start border-radius-variables - - - - -$input-btn-padding-y: 0.5rem !default; -$input-btn-padding-x: .875rem !default; -$table-th-font-weight: 400!default; - - - -$link-decoration: none !default; - -$link-hover-decoration: underline !default; - - -// Icon -$icon-color: $gray-500 !default; -$icon-size-xxs: 1rem !default; -$icon-size-xs: 1.5rem !default; -$icon-size-sm: 2rem !default; -$icon-size-md: 2.5rem !default; -$icon-size-lg: 3rem !default; -$icon-size-xl: 3.5rem !default; -$icon-size-xxl: 4rem !default; -$icon-size-xxxl: 7rem !default; - -// Avatar -$avatar-size-xs: 1.5rem !default; -$avatar-size-sm: 2rem !default; -$avatar-size-md: 2.5rem !default; -$avatar-size-lg: 3.5rem !default; -$avatar-size-xl: 5rem !default; -$avatar-size-xxl: 7.5rem !default; diff --git a/resources/scss/app.scss b/resources/scss/app.scss index 591fc2a..6d57b51 100644 --- a/resources/scss/app.scss +++ b/resources/scss/app.scss @@ -1,13 +1,69 @@ -@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); +@use "@coreui/coreui/scss/coreui" as * with ( + $enable-deprecation-messages: false +); -// Import Bootstrap functions first -@import "bootstrap/scss/functions"; +body { + background-color: var(--cui-tertiary-bg); +} -// Override Bootstrap variables here -@import "./variables"; +.icon { + fill: none !important; +} -// Import Bootstrap -@import "bootstrap/scss/bootstrap"; +.wrapper { + width: 100%; + padding-inline: var(--cui-sidebar-occupy-start, 0) var(--cui-sidebar-occupy-end, 0); + will-change: auto; + @include transition(padding .15s); +} -// Custom styles -@import "./custom"; \ No newline at end of file +.header > .container-fluid, +.sidebar-header { + min-height: calc(4rem + 1px); // stylelint-disable-line function-disallowed-list +} + +.sidebar-brand-full { + margin-left: 3px; +} + +.sidebar-header { + .nav-underline-border { + --cui-nav-underline-border-link-padding-x: 1rem; + --cui-nav-underline-border-gap: 0; + } + + .nav-link { + display: flex; + align-items: center; + min-height: calc(4rem + 1px); // stylelint-disable-line function-disallowed-list + } +} + +.sidebar-toggler { + margin-inline-start: auto; +} + +.sidebar-narrow, +.sidebar-narrow-unfoldable:not(:hover) { + .sidebar-toggler { + margin-inline-end: auto; + } +} + +.header > .container-fluid + .container-fluid { + min-height: 3rem; +} + +.footer { + min-height: calc(3rem + 1px); // stylelint-disable-line function-disallowed-list +} + +@include color-mode(dark) { + body { + background-color: var(--cui-dark-bg-subtle); + } + + .footer { + --cui-footer-bg: var(--cui-body-bg); + } +} diff --git a/resources/scss/plugin/apexchart.scss b/resources/scss/plugin/apexchart.scss index 96c4dfd..8433b30 100644 --- a/resources/scss/plugin/apexchart.scss +++ b/resources/scss/plugin/apexchart.scss @@ -1,4 +1,5 @@ -@import "../variables"; +@import "@coreui/coreui/scss/variables"; +@import "@coreui/coreui/scss/mixins"; @import "apexcharts/dist/apexcharts.css"; // ApexCharts Theme Overrides diff --git a/resources/scss/plugin/datatables.scss b/resources/scss/plugin/datatables.scss index 0ac8fbe..d2dc5ba 100644 --- a/resources/scss/plugin/datatables.scss +++ b/resources/scss/plugin/datatables.scss @@ -1,218 +1,222 @@ -@import "../variables"; +@import "@coreui/coreui/scss/variables"; +@import "@coreui/coreui/scss/mixins"; @import "datatables.net-bs5/css/dataTables.bootstrap5.min.css"; // DataTables Theme Overrides table.dataTable { - font-family: $font-family-base; - font-size: $font-size-base; - color: $gray-800; - border-collapse: collapse !important; - border-color: $border-color; - - // Header cells - thead { - - th, - td { - font-weight: 500; - font-size: $font-size-sm; - color: $gray-600; - background: $gray-100; - border-bottom: 1px solid $border-color !important; - padding: 0.625rem 0.75rem; - white-space: nowrap; - } + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-body-font-size); + color: var(--cui-body-color); + border-collapse: collapse !important; + border-color: var(--cui-border-color); + + // Header cells + thead { + th, + td { + font-weight: 500; + font-size: var(--cui-font-size-sm); + color: var(--cui-secondary-color); + background: var(--cui-tertiary-bg); + border-bottom: 1px solid var(--cui-border-color) !important; + padding: 0.625rem 0.75rem; + white-space: nowrap; + } - // Sort icons - th.sorting, - th.sorting_asc, - th.sorting_desc { - cursor: pointer; - - &::before, - &::after { - opacity: 0.4; - color: $gray-500; - } - - &.sorting_asc::before, - &.sorting_desc::after { - opacity: 1; - color: $primary; - } - } - } - - // Body cells - tbody { - td { - padding: 0.625rem 0.75rem; - vertical-align: middle; - border-top: 1px solid $border-color; + // Sort icons + th.sorting, + th.sorting_asc, + th.sorting_desc { + cursor: pointer; + + &::before, + &::after { + opacity: 0.4; + color: var(--cui-secondary-color); + } + + &.sorting_asc::before, + &.sorting_desc::after { + opacity: 1; + color: var(--cui-primary); + } + } } - tr { - transition: background-color 0.15s; + // Body cells + tbody { + td { + padding: 0.625rem 0.75rem; + vertical-align: middle; + border-top: 1px solid var(--cui-border-color); + } - &:hover>td { - background-color: rgba($primary, 0.04); + tr { + transition: background-color 0.15s; - &.dtfc-fixed-left, - &.dtfc-fixed-right { - background-color: mix($primary, $white, 4%); - } - } + &:hover > td { + // Safe runtime transparency generation via color-mix() + background-color: color-mix(in srgb, var(--cui-primary) 4%, transparent); + + &.dtfc-fixed-left, + &.dtfc-fixed-right { + background-color: color-mix(in srgb, var(--cui-primary) 4%, var(--cui-body-bg)); + } + } - &.selected>td { - background-color: rgba($primary, 0.1); - color: $gray-900; + &.selected > td { + background-color: color-mix(in srgb, var(--cui-primary) 10%, transparent); + color: var(--cui-emphasis-color); - &.dtfc-fixed-left, - &.dtfc-fixed-right { - background-color: mix($primary, $white, 10%); + &.dtfc-fixed-left, + &.dtfc-fixed-right { + background-color: color-mix(in srgb, var(--cui-primary) 10%, var(--cui-body-bg)); + } + } } - } } - } - // Footer cells - tfoot { - - th, - td { - border-top: 2px solid $border-color; - font-weight: 500; - color: $gray-800; + // Footer cells + tfoot { + th, + td { + border-top: 2px solid var(--cui-border-color); + font-weight: 500; + color: var(--cui-emphasis-color); + } } - } - // Striped rows - &.table-striped>tbody>tr:nth-child(odd)>td { - background-color: rgba($gray-50, 0.6); + // Striped rows + &.table-striped { + > tbody > tr:nth-child(odd) > td { + background-color: var(--cui-table-striped-bg); - &.dtfc-fixed-left, - &.dtfc-fixed-right { - background-color: mix($gray-50, $white, 60%); + &.dtfc-fixed-left, + &.dtfc-fixed-right { + background-color: color-mix(in srgb, var(--cui-tertiary-bg) 60%, var(--cui-body-bg)); + } + } } - } } // Wrapper lengths control .dataTables_wrapper { - font-family: $font-family-base; - font-size: $font-size-base; - color: $gray-800; - - // Length (items per page) select - .dataTables_length { - label { - font-size: $font-size-sm; - color: $gray-600; - display: flex; - align-items: center; - gap: 0.5rem; - } + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-body-font-size); + color: var(--cui-body-color); + + // Length (items per page) select + .dataTables_length { + label { + font-size: var(--cui-font-size-sm); + color: var(--cui-secondary-color); + display: flex; + align-items: center; + gap: 0.5rem; + } - select { - font-family: $font-family-base; - font-size: $font-size-sm; - border: 1px solid $border-color; - border-radius: 0.5rem; - padding: 0.25rem 2.25rem 0.25rem 0.75rem; /* Increased padding-right for dropdown arrow */ - color: $gray-800; - background-color: $white; - min-width: 80px; /* Force minimum width to prevent cut-off */ - - &:focus { - border-color: $primary; - outline: 0; - box-shadow: 0 0 0 3px rgba($primary, 0.12); - } + select { + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-font-size-sm); + border: 1px solid var(--cui-border-color); + border-radius: 0.5rem; + padding: 0.25rem 2.25rem 0.25rem 0.75rem; + color: var(--cui-body-color); + background-color: var(--cui-body-bg); + min-width: 80px; + + &:focus { + border-color: var(--cui-primary); + outline: 0; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--cui-primary) 12%, transparent); + } + } } - } - - // Search input - .dataTables_filter { - label { - font-size: $font-size-sm; - color: $gray-600; - display: flex; - align-items: center; - gap: 0.5rem; + + // Search input + .dataTables_filter { + label { + font-size: var(--cui-font-size-sm); + color: var(--cui-secondary-color); + display: flex; + align-items: center; + gap: 0.5rem; + } + + input { + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-font-size-sm); + border: 1px solid var(--cui-border-color); + border-radius: 0.5rem; + padding: 0.375rem 0.75rem; + color: var(--cui-body-color); + background-color: var(--cui-body-bg); + + &:focus { + border-color: var(--cui-primary); + outline: 0; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--cui-primary) 12%, transparent); + } + } } - input { - font-family: $font-family-base; - font-size: $font-size-sm; - border: 1px solid $border-color; - border-radius: 0.5rem; - padding: 0.375rem 0.75rem; - color: $gray-800; - - &:focus { - border-color: $primary; - outline: 0; - box-shadow: 0 0 0 3px rgba($primary, 0.12); - } + // Info text + .dataTables_info { + font-size: var(--cui-font-size-sm); + color: var(--cui-secondary-color); + padding-top: 0.5rem; } - } - - // Info text - .dataTables_info { - font-size: $font-size-sm; - color: $gray-500; - padding-top: 0.5rem; - } - - // Pagination - .dataTables_paginate { - .paginate_button { - font-family: $font-family-base; - font-size: $font-size-sm; - border-radius: 0.5rem !important; - border: 1px solid transparent !important; - color: $gray-800 !important; - padding: 0.3rem 0.65rem; - transition: all 0.15s; - - &:hover { - background: rgba($primary, 0.08) !important; - color: $primary !important; - border-color: transparent !important; - box-shadow: none !important; - } - - &.current, - &.current:hover { - background: $primary !important; - color: $white !important; - border-color: $primary !important; - box-shadow: none !important; - font-weight: 500; - } - - &.disabled, - &.disabled:hover { - color: $gray-600 !important; - cursor: not-allowed; - } + + // Pagination + .dataTables_paginate { + .paginate_button { + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-font-size-sm); + border-radius: 0.5rem !important; + border: 1px solid transparent !important; + color: var(--cui-body-color) !important; + padding: 0.3rem 0.65rem; + transition: all 0.15s; + + &:hover { + background: color-mix(in srgb, var(--cui-primary) 8%, transparent) !important; + color: var(--cui-primary) !important; + border-color: transparent !important; + box-shadow: none !important; + } + + &.current, + &.current:hover { + background: var(--cui-primary) !important; + color: var(--cui-white) !important; + border-color: var(--cui-primary) !important; + box-shadow: none !important; + font-weight: 500; + } + + &.disabled, + &.disabled:hover { + color: var(--cui-secondary-color) !important; + background: transparent !important; + cursor: not-allowed; + } + } } - } - - // Processing indicator - .dataTables_processing { - font-family: $font-family-base; - font-size: $font-size-sm; - border: 1px solid $border-color; - border-radius: 0.5rem; - background: $white; - box-shadow: 0 4px 16px rgba($black, 0.15); - color: $gray-800; - - >div:last-child>div { - background: $primary; + + // Processing indicator + .dataTables_processing { + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-font-size-sm); + border: 1px solid var(--cui-border-color); + border-radius: 0.5rem; + background: var(--cui-body-bg); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); + color: var(--cui-body-color); + + > div:last-child > div { + background: var(--cui-primary); + } } - } } .dt-length { @@ -220,3 +224,10 @@ table.dataTable { min-width: 70px !important; } } + +// Scoped CoreUI Theme High Contrast Shadows +[data-coreui-theme="dark"] { + .dataTables_wrapper .dataTables_processing { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5); + } +} diff --git a/resources/scss/plugin/filepond.scss b/resources/scss/plugin/filepond.scss index 01a65eb..9b710e2 100644 --- a/resources/scss/plugin/filepond.scss +++ b/resources/scss/plugin/filepond.scss @@ -1,4 +1,5 @@ -@import "../variables"; +@import "@coreui/coreui/scss/variables"; +@import "@coreui/coreui/scss/mixins"; @import "../../../vendor/spatie/livewire-filepond/resources/dist/filepond.css"; .filepond--root { @@ -6,24 +7,27 @@ width: 100%; border-radius: 1rem; overflow: hidden; - border: 2px dashed $primary; - background: $light; - box-shadow: 0 8px 24px rgba(#000, 0.08); + border: 2px dashed var(--cui-primary); + // Uses adaptive background variable instead of static light mode background + background: var(--cui-tertiary-bg); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); transition: all 0.2s ease-in-out; &:hover { - border-color: mix(#000, $primary, 20%); - box-shadow: 0 10px 28px rgba(#000, 0.12); + // Native browser mixing prevents compile errors with var() + border-color: color-mix(in srgb, var(--cui-primary) 80%, black); + box-shadow: 0 10px 28px rgba(0, 0, 0, 0.12); } .filepond--panel-root { - background-color: rgba($primary, 0.05) !important; + // Combines primary color-mix transparency natively with background colors + background-color: color-mix(in srgb, var(--cui-primary) 5%, transparent) !important; border-radius: 1rem !important; } .filepond--drop-label { font-size: 1.1rem; - color: $secondary; + color: var(--cui-secondary-color); font-weight: 700; padding: 1.4rem; } @@ -31,24 +35,24 @@ .filepond--item { border-radius: 0.75rem; overflow: hidden; - box-shadow: 0 4px 12px rgba(#000, 0.06); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06); margin-bottom: 0.75rem; transition: all 0.2s ease-in-out; &:hover { transform: translateY(-2px); - box-shadow: 0 8px 20px rgba(#000, 0.1); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1); } } .filepond--file-action-button { - background-color: $primary !important; - color: #fff !important; + background-color: var(--cui-primary) !important; + color: var(--cui-white) !important; border-radius: 0.5rem !important; transition: all 0.2s ease-in-out; &:hover { - background-color: mix(#000, $primary, 20%) !important; + background-color: color-mix(in srgb, var(--cui-primary) 80%, black) !important; } } @@ -56,3 +60,20 @@ display: none !important; } } + +// Scoped CoreUI Dark Theme Context overrides +[data-coreui-theme="dark"] { + .filepond--root { + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4) !important; + + &:hover { + box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5) !important; + // Brightens the line accent relative to standard dark theme rules + border-color: color-mix(in srgb, var(--cui-primary) 85%, white); + } + + .filepond--file-action-button:hover { + background-color: color-mix(in srgb, var(--cui-primary) 85%, white) !important; + } + } +} diff --git a/resources/scss/plugin/select2.scss b/resources/scss/plugin/select2.scss index 0be5016..97f14fe 100644 --- a/resources/scss/plugin/select2.scss +++ b/resources/scss/plugin/select2.scss @@ -1,277 +1,288 @@ -@import "../variables"; +@import "@coreui/coreui/scss/variables"; +@import "@coreui/coreui/scss/mixins"; @import "select2/dist/css/select2.min.css"; @import "select2-bootstrap-5-theme/dist/select2-bootstrap-5-theme.min.css"; // Select2 Theme Overrides .select2-container { - font-family: $font-family-base; - font-size: $font-size-base; - width: 100% !important; - - // Main selection box - .select2-selection--single, - .select2-selection--multiple { - font-family: $font-family-base; - font-size: $font-size-base; - border: 1px solid $border-color; - border-radius: 0.5rem !important; - background-color: $white; - transition: border-color 0.15s, box-shadow 0.15s; + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-body-font-size); + width: 100% !important; + + // Main selection box + .select2-selection--single, + .select2-selection--multiple { + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-body-font-size); + border: 1px solid var(--cui-border-color); + border-radius: 0.5rem !important; + background-color: var(--cui-body-bg); + color: var(--cui-body-color); + transition: border-color 0.15s, box-shadow 0.15s; - &:hover { - border-color: $gray-600; + &:hover { + border-color: var(--cui-border-color-translucent); + } } - } // Single select rendered value - .select2-selection--single { - height: calc(1.5em + 0.75rem + 2px); - - .select2-selection__rendered { - color: $gray-800; - padding-left: 0.75rem; - padding-right: 2rem; - width: 90%; - line-height: calc(1.5em + 0.75rem); - overflow: hidden !important; - text-overflow: ellipsis !important; - white-space: nowrap !important; - display: block !important; - - // Increase padding right when clear button is present so text truncates before it - &:has(.select2-selection__clear) { - padding-right: .3rem !important; - } - } + .select2-selection--single { + height: calc(1.5em + 0.75rem + 2px); + + .select2-selection__rendered { + color: var(--cui-body-color); + padding-left: 0.75rem; + padding-right: 2rem; + width: 90%; + line-height: calc(1.5em + 0.75rem); + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + display: block !important; + + // Increase padding right when clear button is present so text truncates before it + &:has(.select2-selection__clear) { + padding-right: .3rem !important; + } + } - .select2-selection__placeholder { - color: $gray-600; - } + .select2-selection__placeholder { + color: var(--cui-secondary-color); + } - .select2-selection__clear { - position: absolute; - right: 1.8rem; - top: 50%; - transform: translateY(-50%); - z-index: 10; - cursor: pointer; - color: $gray-500; - background: transparent; - padding: 0; - display: flex; - align-items: center; - justify-content: center; - height: 1rem; - width: 1rem; - line-height: 1; - - &:hover { - color: $danger; - } - } + .select2-selection__clear { + position: absolute; + right: 1.8rem; + top: 50%; + transform: translateY(-50%); + z-index: 10; + cursor: pointer; + color: var(--cui-secondary-color); + background: transparent; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + height: 1rem; + width: 1rem; + line-height: 1; + + &:hover { + color: var(--cui-danger); + } + } - .select2-selection__arrow { - height: 100%; - right: 0.5rem; + .select2-selection__arrow { + height: 100%; + right: 0.5rem; - b { - border-color: $gray-600 transparent transparent; - border-width: 5px 4px 0; - } + b { + // Native CSS properties to draw the carets cleanly in dark theme + border-color: var(--cui-secondary-color) transparent transparent; + border-width: 5px 4px 0; + } + } } - } - - // Multiple select tags - .select2-selection--multiple { - padding: 0.25rem 0.5rem; - min-height: calc(1.5em + 0.75rem + 2px); - - .select2-selection__choice { - background-color: rgba($primary, 0.1); - border: 1px solid rgba($primary, 0.2); - border-radius: 0.375rem; - color: $primary; - font-size: $font-size-sm; - font-weight: 500; - padding: 0.1rem 0.5rem; - - .select2-selection__choice__remove { - color: $primary; - font-weight: 700; - margin-right: 4px; - &:hover { - color: $danger; - background: transparent; + // Multiple select tags + .select2-selection--multiple { + padding: 0.25rem 0.5rem; + min-height: calc(1.5em + 0.75rem + 2px); + + .select2-selection__choice { + background-color: color-mix(in srgb, var(--cui-primary) 10%, transparent); + border: 1px solid color-mix(in srgb, var(--cui-primary) 20%, transparent); + border-radius: 0.375rem; + color: var(--cui-primary); + font-size: var(--cui-font-size-sm); + font-weight: 500; + padding: 0.1rem 0.5rem; + + .select2-selection__choice__remove { + color: var(--cui-primary); + font-weight: 700; + margin-right: 4px; + + &:hover { + color: var(--cui-danger); + background: transparent; + } + } } - } - } - .select2-search__field { - font-family: $font-family-base; - font-size: $font-size-sm; - color: $gray-800; + .select2-search__field { + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-font-size-sm); + color: var(--cui-body-color); + background-color: transparent; - &::placeholder { - color: $gray-600; - } + &::placeholder { + color: var(--cui-secondary-color); + } + } } - } - // Focused state - &--open, - &--focus { - - .select2-selection--single, - .select2-selection--multiple { - border-color: $primary !important; - box-shadow: 0 0 0 3px rgba($primary, 0.12) !important; - outline: 0; - } + // Focused state + &--open, + &--focus { + .select2-selection--single, + .select2-selection--multiple { + border-color: var(--cui-primary) !important; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--cui-primary) 12%, transparent) !important; + outline: 0; + } - .select2-selection--single .select2-selection__arrow b { - border-color: transparent transparent $primary; - border-width: 0 4px 5px; + .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent var(--cui-primary); + border-width: 0 4px 5px; + } } - } } // Support for form-control-sm select.form-control-sm + .select2-container, select.form-select-sm + .select2-container, .select2-container--sm { - .select2-selection--single, - .select2-selection--multiple { - border-radius: 0.375rem !important; - } - - .select2-selection--single { - height: calc(1.5em + 0.5rem + 2px) !important; - - .select2-selection__rendered { - padding-left: 0.5rem; - font-size: $font-size-sm; - line-height: calc(1.5em + 0.5rem) !important; + .select2-selection--single, + .select2-selection--multiple { + border-radius: 0.375rem !important; } - .select2-selection__clear { - right: 0.5rem; + .select2-selection--single { + height: calc(1.5em + 0.5rem + 2px) !important; + + .select2-selection__rendered { + padding-left: 0.5rem; + font-size: var(--cui-font-size-sm); + line-height: calc(1.5em + 0.5rem) !important; + } + + .select2-selection__clear { + right: 0.5rem; + } } - } - .select2-selection--multiple { - min-height: calc(1.5em + 0.5rem + 2px) !important; - padding: 0.15rem 0.5rem; + .select2-selection--multiple { + min-height: calc(1.5em + 0.5rem + 2px) !important; + padding: 0.15rem 0.5rem; - .select2-search__field { - font-size: $font-size-sm; + .select2-search__field { + font-size: var(--cui-font-size-sm); + } } - } } // Dropdown panel .select2-dropdown { - font-family: $font-family-base; - font-size: $font-size-base; - border: 1px solid $border-color; - border-radius: 0.5rem !important; - box-shadow: 0 8px 24px rgba($black, 0.15); - overflow: hidden; - - // Search field inside dropdown - .select2-search--dropdown { - padding: 0.5rem; - background: $gray-100; - border-bottom: 1px solid $border-color; - - .select2-search__field { - font-family: $font-family-base; - font-size: $font-size-sm; - border: 1px solid $border-color; - border-radius: 0.375rem; - padding: 0.375rem 0.75rem; - color: $gray-800; - width: 100%; - background-color: $white; - - &:focus { - border-color: $primary; - outline: 0; - box-shadow: 0 0 0 3px rgba($primary, 0.12); - } + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-body-font-size); + border: 1px solid var(--cui-border-color); + border-radius: 0.5rem !important; + background-color: var(--cui-body-bg); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); + overflow: hidden; + + // Search field inside dropdown + .select2-search--dropdown { + padding: 0.5rem; + background: var(--cui-tertiary-bg); + border-bottom: 1px solid var(--cui-border-color); + + .select2-search__field { + font-family: var(--cui-font-sans-serif); + font-size: var(--cui-font-size-sm); + border: 1px solid var(--cui-border-color); + border-radius: 0.375rem; + padding: 0.375rem 0.75rem; + color: var(--cui-body-color); + width: 100%; + background-color: var(--cui-body-bg); + + &:focus { + border-color: var(--cui-primary); + outline: 0; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--cui-primary) 12%, transparent); + } + } } - } - // Option list - .select2-results__options { - padding: 0.25rem 0; - max-height: 220px; - overflow-y: auto; + // Option list + .select2-results__options { + padding: 0.25rem 0; + max-height: 220px; + overflow-y: auto; - // Scrollbar - &::-webkit-scrollbar { - width: 5px; - } + // Scrollbar styling to respect theme + &::-webkit-scrollbar { + width: 5px; + } - &::-webkit-scrollbar-track { - background: $gray-100; - } + &::-webkit-scrollbar-track { + background: var(--cui-tertiary-bg); + } - &::-webkit-scrollbar-thumb { - background: $gray-300; - border-radius: 4px; - } - } - - .select2-results__option { - font-size: $font-size-sm; - color: $gray-800; - padding: 0.45rem 0.85rem; - transition: background 0.12s; - - // Highlighted (hover or keyboard) - &--highlighted { - background-color: rgba($primary, 0.08) !important; - color: $primary !important; + &::-webkit-scrollbar-thumb { + background: var(--cui-border-color); + border-radius: 4px; + } } - // Selected - &[aria-selected='true'] { - background-color: rgba($primary, 0.12); - color: $primary; - font-weight: 500; - } + .select2-results__option { + font-size: var(--cui-font-size-sm); + color: var(--cui-body-color); + background-color: transparent; + padding: 0.45rem 0.85rem; + transition: background 0.12s; + + // Highlighted (hover or keyboard) + &--highlighted { + background-color: color-mix(in srgb, var(--cui-primary) 8%, transparent) !important; + color: var(--cui-primary) !important; + } - // Disabled - &[aria-disabled='true'] { - color: $gray-600; - cursor: not-allowed; - } + // Selected + &[aria-selected='true'] { + background-color: color-mix(in srgb, var(--cui-primary) 12%, transparent); + color: var(--cui-primary); + font-weight: 500; + } + + // Disabled + &[aria-disabled='true'] { + color: var(--cui-secondary-color); + cursor: not-allowed; + } - // Option group label - &--group { - color: $gray-500; - font-size: $font-xs; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.04em; - padding: 0.5rem 0.85rem 0.25rem; - cursor: default; + // Option group label + &--group { + color: var(--cui-secondary-color); + font-size: var(--cui-font-size-sm); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + padding: 0.5rem 0.85rem 0.25rem; + cursor: default; + } } - } } // Disabled state .select2-container--disabled { + .select2-selection--single, + .select2-selection--multiple { + background-color: var(--cui-disabled-bg) !important; + border-color: var(--cui-border-color) !important; + cursor: not-allowed; - .select2-selection--single, - .select2-selection--multiple { - background-color: $gray-100 !important; - border-color: $border-color !important; - cursor: not-allowed; + .select2-selection__rendered { + color: var(--cui-disabled-color); + } + } +} - .select2-selection__rendered { - color: $gray-600; +// Scoped CoreUI Theme adjustments for intense dark background shadows +[data-coreui-theme="dark"] { + .select2-dropdown { + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45); } - } } diff --git a/resources/scss/plugin/sweetalert.scss b/resources/scss/plugin/sweetalert.scss index cf33709..7e5548e 100644 --- a/resources/scss/plugin/sweetalert.scss +++ b/resources/scss/plugin/sweetalert.scss @@ -1,51 +1,54 @@ -@import "../variables"; +@import "@coreui/coreui/scss/variables"; +@import "@coreui/coreui/scss/mixins"; @import "sweetalert2/src/sweetalert2.scss"; -// Override SweetAlert2 variables -// Brand Colors +// ========================================================================== +// 1. Core SweetAlert2 Base Variables (Safe Fallbacks) +// ========================================================================== $swal2-confirm-button-background-color: $primary; $swal2-deny-button-background-color: $danger; $swal2-cancel-button-background-color: $secondary; -// States $swal2-success: $success; $swal2-error: $danger; $swal2-warning: $warning; $swal2-info: $info; $swal2-question: $secondary; -// Typography & Base Styling $swal2-font: $font-family-base; $swal2-color: $gray-800; -// Buttons matching UI Form Controls -$swal2-button-padding: $input-btn-padding-y ( - $input-btn-padding-x * 1.5 -); +$swal2-button-padding: $input-btn-padding-y ($input-btn-padding-x * 1.5); $swal2-confirm-button-border-radius: 0.5rem; $swal2-deny-button-border-radius: 0.5rem; $swal2-cancel-button-border-radius: 0.5rem; $swal2-border-radius: 0.75rem; - -// Custom Class Styles for Premium Look +// ========================================================================== +// 2. Custom Layout & Core Dark Mode Compatibility +// ========================================================================== .swal2-popup { padding: 1.5rem; - box-shadow: 0 10px 40px rgba($black, 0.08); - border: 1px solid rgba($gray-900, 0.05); + // CoreUI native background tracking (automatically dark/light compliant) + background: var(--cui-body-bg); + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08); + border: 1px solid var(--cui-border-color-translucent); + + // Global adjustments inside popup tracking CoreUI mode text + color: var(--cui-body-color); .swal2-title { font-weight: 600; font-size: 1.25rem; - color: $gray-900; + color: var(--cui-emphasis-color); margin-bottom: 0.75rem; padding-top: 0.5rem; } .swal2-html-container { font-size: 0.95rem; - color: $gray-600; + color: var(--cui-secondary-color); line-height: 1.6; margin: 0.5rem 1rem 0; } @@ -62,7 +65,8 @@ $swal2-border-radius: 0.75rem; &:hover { transform: translateY(-1px); - filter: brightness(1.05); + // Pure CSS adjustment safely altering colors inside runtime vars + filter: brightness(1.1); } &:active { @@ -70,50 +74,66 @@ $swal2-border-radius: 0.75rem; } &.swal2-confirm { - background-color: $primary !important; + background-color: var(--cui-primary) !important; + color: var(--cui-white) !important; } &.swal2-cancel { - background-color: $gray-200 !important; - color: $gray-800 !important; - border: 1px solid $border-color; + background-color: var(--cui-secondary-bg) !important; + color: var(--cui-secondary-color) !important; + border: 1px solid var(--cui-border-color) !important; } &.swal2-deny { - background-color: $danger !important; + background-color: var(--cui-danger) !important; + color: var(--cui-white) !important; } } } + // Modal Status Indicators .swal2-icon { margin-top: 0.5rem; margin-bottom: 0.5rem; border-width: 2px; &.swal2-success { - border-color: $success; + border-color: var(--cui-success); [class^='swal2-success-line'] { - background-color: $success; + background-color: var(--cui-success); } .swal2-success-ring { - border-color: rgba($success, 0.3); + // native CSS color-mix handles alpha modifications without triggering compilation crash + border-color: color-mix(in srgb, var(--cui-success) 30%, transparent); } } &.swal2-error { - border-color: $danger; + border-color: var(--cui-danger); .swal2-x-mark-line-left, .swal2-x-mark-line-right { - background-color: $danger; + background-color: var(--cui-danger); } } + + &.swal2-warning { + border-color: var(--cui-warning); + color: var(--cui-warning); + } + + &.swal2-info { + border-color: var(--cui-info); + color: var(--cui-info); + } } } -// Toast styling +// ========================================================================== +// 3. Toast Customization +// ========================================================================== @keyframes swal2-toast-show { 0% { transform: scale(0.9) translateY(-10px); @@ -127,7 +147,10 @@ $swal2-border-radius: 0.75rem; .swal2-toast { padding: 0.75rem 1rem !important; - box-shadow: 0 5px 15px rgba($black, 0.08) !important; + background: var(--cui-body-bg) !important; + color: var(--cui-body-color) !important; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08) !important; + border: 1px solid var(--cui-border-color-translucent) !important; border-radius: 0.5rem !important; &.swal2-show { @@ -135,8 +158,19 @@ $swal2-border-radius: 0.75rem; } .swal2-title { + color: var(--cui-emphasis-color) !important; font-size: 0.875rem !important; margin: 0 0.5rem !important; padding-top: 0 !important; } } + +// ========================================================================== +// 4. Scoped CoreUI Dark Mode Hooks +// ========================================================================== +[data-coreui-theme="dark"] { + .swal2-popup, .swal2-toast { + // High Contrast Shadow adjustments for Dark Backgrounds + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.45) !important; + } +} diff --git a/resources/scss/style.css b/resources/scss/style.css new file mode 100644 index 0000000..3158a5d --- /dev/null +++ b/resources/scss/style.css @@ -0,0 +1,1618 @@ +:root { + --sidebar-width: 280px; + --sidebar-mini-width: 84px; + --admin-bg: #f5f7fb; + --admin-surface: #ffffff; + --admin-surface-soft: #f8fafc; + --admin-border: #dbe4ef; + --admin-text: #1f2937; + --admin-muted: #6b7280; + --admin-primary: #2563eb; + --admin-primary-dark: #1d4ed8; + --admin-success: #0f766e; + --admin-warning: #d97706; + --admin-danger: #dc2626; + --admin-sidebar: #111827; + --admin-sidebar-soft: #1f2937; + --admin-shadow-sm: 0 10px 24px rgba(15, 23, 42, 0.06); + --admin-shadow: 0 18px 46px rgba(15, 23, 42, 0.09); + --admin-shadow-lg: 0 26px 70px rgba(15, 23, 42, 0.12); + --admin-ring: 0 0 0 4px rgba(37, 99, 235, 0.12); +} + +* { + box-sizing: border-box; +} + +html { + min-height: 100%; +} + +body { + min-height: 100vh; + margin: 0; + background: linear-gradient(180deg, #f8fbff 0%, var(--admin-bg) 42%, #eef4fa 100%); + color: var(--admin-text); + font-family: "Segoe UI", Arial, sans-serif; +} + +a { + text-decoration: none; +} + +.admin-shell { + min-height: 100vh; +} + +.admin-sidebar { + position: fixed; + inset: 0 auto 0 0; + z-index: 1040; + width: var(--sidebar-width); + display: flex; + flex-direction: column; + overflow-x: hidden; + overflow-y: auto; + /* Reserve scrollbar gutter to keep inner content width stable so header/footer dividers align with scrollbar */ + scrollbar-gutter: stable; + background: var(--admin-sidebar); + color: #ffffff; + box-shadow: 18px 0 42px rgba(15, 23, 42, 0.18); + transform: translateX(0); + transition: width 0.2s ease, transform 0.2s ease; +} + +.sidebar-header { + padding: 1.35rem 1.25rem 1.15rem; + margin-inline: 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} + +.brand-mark { + display: flex; + align-items: center; + gap: 0.75rem; + min-width: 0; + color: #ffffff; +} + +.brand-mark:hover, +.brand-mark:focus { + color: #ffffff; +} + +.brand-icon, +.profile-avatar, +.metric-icon, +.nav-icon { + display: inline-grid; + place-items: center; + flex: 0 0 auto; + font-weight: 800; +} + +.brand-icon { + width: 42px; + height: 42px; + border-radius: 8px; + background: linear-gradient(135deg, #2563eb, #0f766e); + color: #ffffff; +} + +.brand-copy, +.brand-title, +.brand-subtitle, +.nav-text, +.sidebar-footer-text { + min-width: 0; + transition: opacity 0.16s ease, width 0.16s ease; +} + +.brand-title, +.brand-subtitle { + display: block; + line-height: 1.2; + white-space: nowrap; +} + +.brand-title { + font-size: 1.05rem; + font-weight: 800; +} + +.brand-subtitle { + color: #9ca3af; + font-size: 0.78rem; +} + +.sidebar-nav { + display: grid; + gap: 0.45rem; + padding: 1.1rem 1rem; +} + +.sidebar-nav .nav-link { + display: flex; + align-items: center; + gap: 0.75rem; + min-height: 48px; + padding: 0.78rem 0.9rem; + border-radius: 8px; + color: #d1d5db; + font-weight: 700; + transition: background 0.16s ease, color 0.16s ease, transform 0.16s ease; + white-space: nowrap; +} + +.sidebar-nav .nav-link:hover, +.sidebar-nav .nav-link:focus, +.sidebar-nav .nav-link.active { + background: var(--admin-sidebar-soft); + color: #ffffff; +} + +.sidebar-nav .nav-link:hover, +.sidebar-nav .nav-link:focus { + transform: translateX(2px); +} + +.nav-icon { + width: 30px; + height: 30px; + border-radius: 8px; + background: rgba(255, 255, 255, 0.08); + color: #bfdbfe; + font-size: 0.76rem; +} + +.sidebar-footer { + display: flex; + align-items: center; + gap: 0.65rem; + margin-top: auto; + margin-inline: 1.25rem; + padding: 1rem 0; + color: #d1d5db; + border-top: 1px solid rgba(255, 255, 255, 0.08); + font-size: 0.9rem; + white-space: nowrap; +} + +.sidebar-user { + margin: auto 1rem 1rem; + padding: 0.85rem; + display: grid; + justify-items: center; + gap: 0.22rem; + border: 1px solid var(--admin-sidebar-border); + border-radius: 8px; + background: var(--admin-sidebar-soft); + text-align: center; +} + +.sidebar-user-avatar { + border: 3px solid #53e9b9; +} + +.sidebar-user strong { + color: var(--admin-sidebar-text-strong); + font-size: 1rem; + line-height: 1.1; +} + +.sidebar-user small { + color: var(--admin-sidebar-muted); + font-size: 0.84rem; +} + +.status-dot, +.notification-dot { + width: 9px; + height: 9px; + border-radius: 50%; +} + +.status-dot { + flex: 0 0 auto; + background: #22c55e; +} + +.sidebar-backdrop { + position: fixed; + inset: 0; + z-index: 1030; + display: none; + background: rgba(15, 23, 42, 0.5); +} + +.admin-main { + width: auto; + min-width: 0; + min-height: 100vh; + margin-left: var(--sidebar-width); + transition: margin-left 0.2s ease; +} + +.admin-navbar { + position: sticky; + top: 0; + z-index: 1020; + min-height: 72px; + border-bottom: 1px solid var(--admin-border); + box-shadow: var(--admin-shadow-sm); +} + +.admin-navbar.bg-white { + background-color: rgba(255, 255, 255, 0.94) !important; + backdrop-filter: blur(14px); +} + +.sidebar-toggle { + width: 42px; + height: 42px; + display: inline-grid; + place-items: center; + gap: 4px; + padding: 9px; + border: 1px solid var(--admin-border); + border-radius: 8px; + background: #ffffff; + box-shadow: 0 8px 18px rgba(15, 23, 42, 0.05); + transition: border-color 0.16s ease, background 0.16s ease, box-shadow 0.16s ease; +} + +.sidebar-toggle:hover, +.sidebar-toggle:focus { + border-color: #bfdbfe; + background: #f8fbff; + box-shadow: var(--admin-ring); +} + +.sidebar-toggle span { + width: 18px; + height: 2px; + display: block; + background: var(--admin-text); + border-radius: 999px; +} + +.search-input { + max-width: 520px; + border-color: var(--admin-border); + border-radius: 8px; + background: var(--admin-surface-soft); + min-height: 42px; + box-shadow: none; +} + +.search-input:focus { + border-color: #93c5fd; + box-shadow: var(--admin-ring); +} + +.navbar-actions { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.icon-button, +.profile-button { + border: 1px solid var(--admin-border); + background: #ffffff; + color: var(--admin-text); + box-shadow: 0 8px 18px rgba(15, 23, 42, 0.05); + transition: border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease; +} + +.icon-button:hover, +.icon-button:focus, +.profile-button:hover, +.profile-button:focus { + border-color: #bfdbfe; + box-shadow: var(--admin-ring); +} + +.icon-button { + position: relative; + width: 42px; + height: 42px; + border-radius: 8px; + font-weight: 800; +} + +.notification-dot { + position: absolute; + top: 8px; + right: 8px; + background: var(--admin-danger); +} + +.notification-menu { + width: min(320px, calc(100vw - 2rem)); + border: 1px solid var(--admin-border); + border-radius: 8px; + box-shadow: var(--admin-shadow); +} + +.notification-menu .dropdown-item { + display: grid; + gap: 0.2rem; + padding-block: 0.7rem; +} + +.notification-title { + font-weight: 700; +} + +.notification-time { + color: var(--admin-muted); + font-size: 0.82rem; +} + +.profile-button { + display: flex; + align-items: center; + gap: 0.55rem; + min-height: 42px; + padding: 0.35rem 0.65rem; + border-radius: 8px; + font-weight: 700; +} + +.profile-avatar { + width: 30px; + height: 30px; + border-radius: 8px; + background: #e0ecff; + color: var(--admin-primary-dark); + font-size: 0.76rem; +} + +.avatar-img { + display: block; + flex: 0 0 auto; + object-fit: cover; + object-position: center; +} + +.avatar-sm { + width: 34px; + height: 34px; + border-radius: 10px; +} + +.avatar-md { + width: 56px; + height: 56px; + border-radius: 50%; +} + +.avatar-xl { + width: 78px; + height: 78px; + border-radius: 50%; +} + +.profile-button .avatar-sm { + border: 2px solid #52e7b8; + box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.08); +} + +html[data-theme="dark"] .profile-button .avatar-sm { + border-color: #54f0be; + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.08); +} + +.dashboard-content { + min-height: calc(100vh - 132px); +} + +.dashboard-content > .container-fluid { + padding-top: 1.75rem !important; + padding-bottom: 1.75rem !important; +} + +.page-heading, +.panel-header, +.metric-top { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.page-heading { + margin-bottom: 1.35rem; +} + +.page-heading h1 { + font-weight: 800; + letter-spacing: 0; +} + +.eyebrow { + color: var(--admin-primary); + font-size: 0.78rem; + font-weight: 800; + text-transform: uppercase; +} + +.heading-actions { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 0.65rem; +} + +.btn { + border-radius: 8px; + font-weight: 700; + box-shadow: 0 8px 18px rgba(15, 23, 42, 0.05); + transition: border-color 0.16s ease, background 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease; +} + +.btn:hover, +.btn:focus { + transform: translateY(-1px); +} + +.btn-primary { + border-color: var(--admin-primary); + background: var(--admin-primary); +} + +.btn-primary:hover, +.btn-primary:focus { + border-color: var(--admin-primary-dark); + background: var(--admin-primary-dark); +} + +.metric-card, +.panel { + border: 1px solid var(--admin-border); + border-radius: 8px; + background: var(--admin-surface); + box-shadow: var(--admin-shadow); +} + +.metric-card { + position: relative; + min-height: 164px; + padding: 1.35rem; + overflow: hidden; + transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease; +} + +.metric-card::before { + content: ""; + position: absolute; + inset: 0 auto 0 0; + width: 4px; + background: var(--metric-color, var(--admin-primary)); +} + +.metric-card:hover { + border-color: #c6d5e8; + box-shadow: var(--admin-shadow-lg); + transform: translateY(-3px); +} + +.metric-primary { + --metric-color: var(--admin-primary); +} + +.metric-success { + --metric-color: var(--admin-success); +} + +.metric-warning { + --metric-color: var(--admin-warning); +} + +.metric-danger { + --metric-color: var(--admin-danger); +} + +.metric-label { + color: var(--admin-muted); + font-size: 0.78rem; + font-weight: 800; + text-transform: uppercase; +} + +.metric-icon { + width: 42px; + height: 42px; + border-radius: 8px; + background: #eaf2ff; + color: var(--metric-color, var(--admin-primary)); + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.7); +} + +.metric-success .metric-icon { + background: #e7f6f3; +} + +.metric-warning .metric-icon { + background: #fff4df; +} + +.metric-danger .metric-icon { + background: #ffecec; +} + +.metric-value { + margin-top: 1rem; + color: var(--admin-text); + font-size: 2.18rem; + font-weight: 800; + line-height: 1; +} + +.metric-meta { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; + margin-top: 0.9rem; + color: var(--admin-muted); + font-size: 0.9rem; + font-weight: 700; +} + +.panel { + padding: 1.35rem; + transition: border-color 0.18s ease, box-shadow 0.18s ease; +} + +.panel:hover { + border-color: #c6d5e8; + box-shadow: var(--admin-shadow-lg); +} + +.panel-header { + margin-bottom: 1.25rem; +} + +.panel-header p { + font-size: 0.92rem; +} + +.chart-bars { + height: 292px; + display: grid; + grid-template-columns: repeat(6, minmax(38px, 1fr)); + align-items: end; + gap: 1rem; + padding: 1.2rem 0.4rem 0; + border-radius: 8px; + background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%); +} + +.chart-column { + height: 100%; + display: grid; + grid-template-rows: 1fr auto; + align-items: end; + gap: 0.6rem; + color: var(--admin-muted); + font-size: 0.84rem; + font-weight: 700; + text-align: center; +} + +.chart-column span { + width: 100%; + height: var(--bar-size); + min-height: 28px; + display: block; + border-radius: 8px 8px 3px 3px; + background: linear-gradient(180deg, var(--admin-primary), var(--admin-success)); + box-shadow: 0 10px 20px rgba(37, 99, 235, 0.18); +} + +.bar-42 { + --bar-size: 42%; +} + +.bar-58 { + --bar-size: 58%; +} + +.bar-51 { + --bar-size: 51%; +} + +.bar-72 { + --bar-size: 72%; +} + +.bar-66 { + --bar-size: 66%; +} + +.bar-83 { + --bar-size: 83%; +} + +.activity-list { + display: grid; + gap: 1.1rem; +} + +.activity-item { + display: grid; + grid-template-columns: auto 1fr; + gap: 0.85rem; + padding-bottom: 1.1rem; + border-bottom: 1px solid var(--admin-border); +} + +.activity-item:last-child { + padding-bottom: 0; + border-bottom: 0; +} + +.activity-dot { + width: 12px; + height: 12px; + margin-top: 0.45rem; + border-radius: 50%; + box-shadow: 0 0 0 5px rgba(37, 99, 235, 0.08); +} + +.table { + --bs-table-bg: transparent; +} + +.table thead th { + color: var(--admin-muted); + font-size: 0.78rem; + text-transform: uppercase; + white-space: nowrap; +} + +.table tbody td { + min-width: 120px; + padding-top: 1rem; + padding-bottom: 1rem; +} + +.table tbody tr { + transition: background 0.16s ease; +} + +.table tbody tr:hover { + background: #f8fbff; +} + +.badge { + border-radius: 8px; + padding: 0.45rem 0.65rem; +} + +.table-search { + width: min(260px, 100%); + border-color: var(--admin-border); + border-radius: 8px; +} + +.table-media { + display: flex; + align-items: center; + gap: 0.7rem; +} + +.product-thumb { + width: 42px; + height: 42px; + border-radius: 8px; + object-fit: cover; + flex: 0 0 auto; + border: 1px solid var(--admin-border); +} + +.profile-avatar-lg { + width: 92px; + height: 92px; + border-radius: 8px; + font-size: 1.5rem; +} + +.profile-hero { + display: grid; + justify-items: center; +} + +.profile-card { + overflow: hidden; +} + +.profile-cover { + margin: -1.35rem -1.35rem 0.9rem; + height: 96px; + border-bottom: 1px solid var(--admin-border); +} + +.profile-cover img { + width: 100%; + height: 100%; + display: block; + object-fit: cover; + object-position: center; +} + +.profile-photo { + margin-top: -44px; + border: 4px solid var(--admin-surface); + box-shadow: var(--admin-shadow-sm); +} + +.info-list, +.settings-list, +.legend-list { + display: grid; + gap: 0.85rem; +} + +.info-list div, +.mini-card, +.settings-row, +.legend-list div { + border: 1px solid var(--admin-border); + border-radius: 8px; + background: var(--admin-surface-soft); +} + +.info-list div, +.legend-list div { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.85rem; +} + +.info-list span, +.mini-card span, +.settings-row small { + color: var(--admin-muted); + font-size: 0.84rem; +} + +.info-list strong, +.mini-card strong { + text-align: right; +} + +.mini-card { + display: grid; + gap: 0.35rem; + min-height: 104px; + align-content: center; + padding: 1rem; +} + +.mini-card strong { + color: var(--admin-text); + font-size: 1.05rem; +} + +.settings-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 1rem; + cursor: pointer; +} + +.settings-row span { + display: grid; + gap: 0.2rem; +} + +.donut-chart { + width: 190px; + height: 190px; + display: grid; + place-items: center; + border-radius: 50%; + background: conic-gradient(var(--admin-primary) 0 42%, var(--admin-success) 42% 68%, var(--admin-warning) 68% 86%, var(--admin-danger) 86% 100%); + box-shadow: var(--admin-shadow-sm); +} + +.donut-chart span { + width: 112px; + height: 112px; + display: grid; + place-items: center; + border-radius: 50%; + background: #ffffff; + color: var(--admin-text); + font-size: 1.65rem; + font-weight: 800; +} + +.legend-list div { + padding: 0.75rem 0.85rem; +} + +.legend-dot { + width: 10px; + height: 10px; + flex: 0 0 auto; + border-radius: 50%; +} + +.legend-list strong { + margin-left: auto; +} + +.progress { + height: 1.15rem; + border-radius: 8px; + background: #e8eef6; +} + +.progress-bar { + border-radius: 8px; + font-size: 0.75rem; + font-weight: 800; +} + +.progress-42 { + width: 42%; +} + +.progress-58 { + width: 58%; +} + +.progress-72 { + width: 72%; +} + +.blank-panel { + min-height: 440px; + display: grid; + place-items: center; + text-align: center; +} + +.blank-state { + max-width: 440px; + display: grid; + justify-items: center; +} + +.blank-visual { + width: 88px; + height: 88px; + object-fit: contain; + margin-bottom: 0.9rem; +} + +.auth-body { + min-height: 100vh; + background: linear-gradient(135deg, #f8fbff 0%, #eaf2ff 44%, #eef8f6 100%); +} + +.auth-page, +.error-page { + min-height: 100vh; + display: grid; + place-items: center; + padding: 1.5rem; +} + +.auth-card, +.error-card { + width: min(100%, 460px); + border: 1px solid var(--admin-border); + border-radius: 8px; + background: rgba(255, 255, 255, 0.96); + box-shadow: var(--admin-shadow-lg); +} + +.auth-card { + padding: 1.5rem; +} + +.auth-visual { + margin-bottom: 1rem; + height: 96px; + border: 1px solid var(--admin-border); + border-radius: 8px; + overflow: hidden; +} + +.auth-visual img { + width: 100%; + height: 100%; + display: block; + object-fit: cover; + object-position: center; +} + +.error-card { + padding: 2rem; + text-align: center; +} + +.error-illustration { + width: min(260px, 100%); + max-height: 132px; + object-fit: contain; + margin: 0 auto 0.55rem; +} + +.auth-brand { + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 1.5rem; + color: var(--admin-text); +} + +.auth-brand:hover, +.auth-brand:focus { + color: var(--admin-text); +} + +.auth-brand span:last-child { + display: grid; + line-height: 1.2; +} + +.auth-brand small, +.auth-footer { + color: var(--admin-muted); +} + +.auth-footer { + margin-top: 1.2rem; + text-align: center; + font-size: 0.92rem; +} + +.error-code { + color: var(--admin-primary); + font-size: clamp(5rem, 18vw, 8rem); + font-weight: 800; + line-height: 1; +} + +.admin-footer { + padding: 1.1rem 0 1.35rem; + color: var(--admin-muted); + font-size: 0.9rem; +} + +.admin-footer .container-fluid { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +@media (min-width: 992px) { + body.sidebar-mini .admin-sidebar { + width: var(--sidebar-mini-width); + } + + body.sidebar-mini .admin-main { + margin-left: var(--sidebar-mini-width); + } + + body.sidebar-mini .brand-copy, + body.sidebar-mini .nav-text, + body.sidebar-mini .sidebar-footer-text { + width: 0; + opacity: 0; + overflow: hidden; + } + + body.sidebar-mini .sidebar-header, + body.sidebar-mini .sidebar-footer { + margin-inline: 1rem; + padding-inline: 0; + } + + body.sidebar-mini .sidebar-nav .nav-link { + justify-content: center; + padding-inline: 0.65rem; + } + + body.sidebar-mini .sidebar-nav .nav-link:hover, + body.sidebar-mini .sidebar-nav .nav-link:focus { + transform: none; + } +} + +@media (max-width: 991.98px) { + .admin-sidebar { + width: min(var(--sidebar-width), calc(100vw - 48px)); + transform: translateX(-100%); + } + + .admin-main { + margin-left: 0; + } + + body.sidebar-open { + overflow: hidden; + } + + body.sidebar-open .admin-sidebar { + transform: translateX(0); + } + + body.sidebar-open .sidebar-backdrop { + display: block; + } +} + +@media (max-width: 575.98px) { + .page-heading, + .panel-header { + align-items: flex-start; + flex-direction: column; + } + + .heading-actions { + width: 100%; + justify-content: stretch; + } + + .heading-actions .btn { + flex: 1 1 0; + } + + .chart-bars { + height: 220px; + gap: 0.6rem; + padding-inline: 0.25rem; + } + + .metric-value { + font-size: 1.85rem; + } + + .metric-card, + .panel { + padding: 1.1rem; + } + + .admin-footer .container-fluid { + align-items: flex-start; + flex-direction: column; + } +} + +@media (prefers-reduced-motion: reduce) { + .sidebar-nav .nav-link, + .sidebar-toggle, + .icon-button, + .profile-button, + .btn, + .metric-card, + .panel, + .table tbody tr { + transition: none; + } + + .sidebar-nav .nav-link:hover, + .sidebar-nav .nav-link:focus, + .btn:hover, + .btn:focus, + .metric-card:hover { + transform: none; + } +} + +html[data-theme="dark"] { + --admin-bg: #0f172a; + --admin-surface: #182235; + --admin-surface-soft: #111827; + --admin-border: #2f3b52; + --admin-text: #e5edf7; + --admin-muted: #9aa8bd; + --admin-primary: #60a5fa; + --admin-primary-dark: #3b82f6; + --admin-success: #2dd4bf; + --admin-warning: #fbbf24; + --admin-danger: #f87171; + --admin-sidebar: #090f1d; + --admin-sidebar-soft: #172033; + --admin-shadow-sm: 0 10px 24px rgba(0, 0, 0, 0.24); + --admin-shadow: 0 18px 46px rgba(0, 0, 0, 0.32); + --admin-shadow-lg: 0 26px 70px rgba(0, 0, 0, 0.42); + --admin-ring: 0 0 0 4px rgba(96, 165, 250, 0.18); +} + +html[data-theme="dark"] body { + background: linear-gradient(180deg, #111827 0%, var(--admin-bg) 48%, #0b1120 100%); +} + +.brand-icon { + font-size: 1.1rem; +} + +.nav-icon { + font-size: 0.95rem; +} + +.theme-toggle i { + font-size: 1rem; +} + +.admin-navbar.bg-white, +.sidebar-toggle, +.icon-button, +.profile-button { + background-color: var(--admin-surface) !important; + color: var(--admin-text); +} + +html[data-theme="dark"] .admin-navbar.bg-white { + background-color: rgba(24, 34, 53, 0.92) !important; +} + +html[data-theme="dark"] .profile-avatar { + background: #1e3a5f; + color: #bfdbfe; +} + +.page-heading-copy { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 1rem; + min-width: 0; +} + +.page-icon, +.section-title i { + display: inline-grid; + place-items: center; + flex: 0 0 auto; + border-radius: 8px; + background: #eaf2ff; + color: var(--admin-primary-dark); +} + +.page-icon { + width: 48px; + height: 48px; + font-size: 1.25rem; +} + +.section-title { + display: inline-flex; + align-items: center; + gap: 0.55rem; +} + +.section-title i { + width: 34px; + height: 34px; + font-size: 0.95rem; +} + +html[data-theme="dark"] .page-icon, +html[data-theme="dark"] .section-title i { + background: #1e3a5f; + color: #bfdbfe; +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.4rem; +} + +.btn-light { + border-color: var(--admin-border); + background: var(--admin-surface-soft); + color: var(--admin-text); +} + +.btn-outline-secondary { + border-color: var(--admin-border); + color: var(--admin-text); +} + +.btn-outline-secondary:hover, +.btn-outline-secondary:focus { + border-color: var(--admin-primary); + background: #eaf2ff; + color: var(--admin-primary-dark); +} + +html[data-theme="dark"] .btn-outline-secondary:hover, +html[data-theme="dark"] .btn-outline-secondary:focus { + background: #1e3a5f; + color: #bfdbfe; +} + +html[data-theme="dark"] .chart-bars { + background: linear-gradient(180deg, #111827 0%, #182235 100%); +} + +html[data-theme="dark"] .table tbody tr:hover { + background: #111827; +} + +html[data-theme="dark"] .progress { + background: #243149; +} + +html[data-theme="dark"] .auth-body { + background: linear-gradient(135deg, #0b1120 0%, #111827 48%, #10201f 100%); +} + +.auth-card, +.error-card { + background: var(--admin-surface); +} + +.auth-theme-toggle { + position: fixed; + top: 1rem; + right: 1rem; + z-index: 10; +} + +.dropdown-menu, +.modal-content, +.accordion-item, +.accordion-button { + border-color: var(--admin-border); + background-color: var(--admin-surface); + color: var(--admin-text); +} + +.dropdown-item, +.accordion-body { + color: var(--admin-text); +} + +.dropdown-item:hover, +.dropdown-item:focus, +.accordion-button:not(.collapsed) { + background-color: var(--admin-surface-soft); + color: var(--admin-text); +} + +.form-control, +.form-select { + border-color: var(--admin-border); + background-color: var(--admin-surface); + color: var(--admin-text); +} + +.form-control:focus, +.form-select:focus { + border-color: #93c5fd; + background-color: var(--admin-surface); + color: var(--admin-text); + box-shadow: var(--admin-ring); +} + +.form-control::placeholder { + color: var(--admin-muted); +} + +.text-muted { + color: var(--admin-muted) !important; +} + +html[data-theme="dark"] .text-body { + color: var(--admin-text) !important; +} + +html[data-theme="dark"] .text-bg-secondary { + background-color: #334155 !important; + color: #e5edf7 !important; +} + +@media (max-width: 767.98px) { + .navbar-actions { + gap: 0.5rem; + } + + .icon-button, + .profile-button, + .sidebar-toggle { + width: 40px; + height: 40px; + } + + .profile-button { + padding: 0.3rem; + } + + .page-heading-copy { + align-items: flex-start; + } +} + +@media (max-width: 575.98px) { + .page-heading-copy { + width: 100%; + } + + .page-icon { + width: 44px; + height: 44px; + } + + .panel-header .d-flex, + .panel-header .form-control, + .panel-header .form-select { + width: 100%; + } +} + +html[data-theme="light"] { + color-scheme: light; +} + +html[data-theme="dark"] { + color-scheme: dark; +} + +body, +.admin-navbar, +.admin-sidebar, +.admin-main, +.metric-card, +.panel, +.auth-card, +.error-card, +.dropdown-menu, +.modal-content, +.form-control, +.form-select { + transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease, box-shadow 0.18s ease; +} + +.table { + --bs-table-color: var(--admin-text); + --bs-table-border-color: var(--admin-border); + color: var(--admin-text); +} + +.page-link { + border-color: var(--admin-border); + background: var(--admin-surface); + color: var(--admin-text); +} + +.page-link:hover, +.page-link:focus { + border-color: var(--admin-primary); + background: var(--admin-surface-soft); + color: var(--admin-primary); +} + +.page-item.active .page-link { + border-color: var(--admin-primary); + background: var(--admin-primary); + color: #ffffff; +} + +.page-item.disabled .page-link { + border-color: var(--admin-border); + background: var(--admin-surface-soft); + color: var(--admin-muted); +} + +.alert { + border-radius: 8px; +} + +html[data-theme="dark"] .alert-primary { + border-color: #1d4ed8; + background: rgba(37, 99, 235, 0.16); + color: #bfdbfe; +} + +html[data-theme="dark"] .alert-success { + border-color: #0f766e; + background: rgba(15, 118, 110, 0.18); + color: #99f6e4; +} + +html[data-theme="dark"] .alert-warning { + border-color: #d97706; + background: rgba(217, 119, 6, 0.18); + color: #fde68a; +} + +html[data-theme="dark"] .alert-danger { + border-color: #dc2626; + background: rgba(220, 38, 38, 0.16); + color: #fecaca; +} + +html[data-theme="dark"] .modal-header, +html[data-theme="dark"] .modal-footer, +html[data-theme="dark"] .accordion-item { + border-color: var(--admin-border); +} + +html[data-theme="dark"] .btn-close { + filter: invert(1) grayscale(100%) brightness(180%); +} + +html[data-theme="dark"] .text-bg-info { + background-color: #0e7490 !important; + color: #ecfeff !important; +} + +html[data-theme="dark"] .text-bg-warning { + background-color: #b45309 !important; + color: #fff7ed !important; +} + +html[data-theme="dark"] .text-bg-success { + background-color: #0f766e !important; + color: #ecfdf5 !important; +} + +html[data-theme="dark"] .text-bg-danger { + background-color: #b91c1c !important; + color: #fef2f2 !important; +} + +@media (max-width: 991.98px) { + .dashboard-content > .container-fluid { + padding-top: 1.25rem !important; + padding-bottom: 1.25rem !important; + } + + .admin-sidebar { + box-shadow: 18px 0 48px rgba(0, 0, 0, 0.28); + } +} + +@media (max-width: 767.98px) { + .panel-header { + align-items: flex-start; + } + + .panel-header > .d-flex { + width: 100%; + } + + .table-search { + width: 100%; + } + + .auth-page, + .error-page { + padding: 1rem; + } + + .auth-card, + .error-card { + padding: 1.15rem; + } +} + +@media (max-width: 420px) { + .heading-actions { + width: 100%; + } + + .heading-actions .btn { + width: 100%; + } + + .metric-card { + min-height: 146px; + } + + .profile-avatar-lg { + width: 76px; + height: 76px; + } +} + +@media (max-width: 575.98px) { + .avatar-sm { + width: 32px; + height: 32px; + border-radius: 8px; + } + + .avatar-xl { + width: 70px; + height: 70px; + } + + .profile-cover { + height: 82px; + margin-bottom: 0.75rem; + } + + .profile-photo { + margin-top: -38px; + } + + .auth-visual { + height: 82px; + } + + .product-thumb { + width: 36px; + height: 36px; + } +} + +html:not([data-theme="dark"]) { + --admin-sidebar: #ffffff; + --admin-sidebar-soft: #eef4ff; + --admin-sidebar-border: #dbe4ef; + --admin-sidebar-text: #475569; + --admin-sidebar-text-strong: #0f172a; + --admin-sidebar-muted: #64748b; + --admin-sidebar-icon-bg: #eaf2ff; + --admin-sidebar-icon: #2563eb; + --admin-sidebar-shadow: 18px 0 42px rgba(15, 23, 42, 0.08); +} + +html[data-theme="dark"] { + --admin-sidebar-border: rgba(255, 255, 255, 0.08); + --admin-sidebar-text: #d1d5db; + --admin-sidebar-text-strong: #ffffff; + --admin-sidebar-muted: #9ca3af; + --admin-sidebar-icon-bg: rgba(255, 255, 255, 0.08); + --admin-sidebar-icon: #bfdbfe; + --admin-sidebar-shadow: 18px 0 42px rgba(0, 0, 0, 0.34); +} + +.admin-sidebar { + border-right: 1px solid var(--admin-sidebar-border); + background: var(--admin-sidebar); + color: var(--admin-sidebar-text-strong); + box-shadow: var(--admin-sidebar-shadow); +} + +.sidebar-header { + border-bottom-color: var(--admin-sidebar-border); +} + +.brand-mark, +.brand-mark:hover, +.brand-mark:focus { + color: var(--admin-sidebar-text-strong); +} + +.brand-subtitle { + color: var(--admin-sidebar-muted); +} + +.sidebar-nav .nav-link { + color: var(--admin-sidebar-text); +} + +.sidebar-nav .nav-link:hover, +.sidebar-nav .nav-link:focus, +.sidebar-nav .nav-link.active { + background: var(--admin-sidebar-soft); + color: var(--admin-sidebar-text-strong); +} + +.nav-icon { + background: var(--admin-sidebar-icon-bg); + color: var(--admin-sidebar-icon); +} + +.sidebar-footer { + border-top-color: var(--admin-sidebar-border); + color: var(--admin-sidebar-text); +} diff --git a/resources/views/components/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php index 48d1b1d..7fdd418 100644 --- a/resources/views/components/layouts/app.blade.php +++ b/resources/views/components/layouts/app.blade.php @@ -21,45 +21,29 @@ @gtmBody -
- - + - - - - -
-
-
- -

{{ $header }}

+
+ +
+
+ {{ $slot }}
- {{ $slot }}
- -
+ +@livewireScriptConfig @stack('page-scripts') -@livewireScriptConfig() -
- diff --git a/resources/views/components/layouts/nav/sidebar.blade.php b/resources/views/components/layouts/nav/sidebar.blade.php index f0775e6..624a39f 100644 --- a/resources/views/components/layouts/nav/sidebar.blade.php +++ b/resources/views/components/layouts/nav/sidebar.blade.php @@ -1,17 +1,26 @@ - + diff --git a/resources/views/components/layouts/nav/sidebar/nav-link.blade.php b/resources/views/components/layouts/nav/sidebar/nav-link.blade.php index 405486f..41a5dc9 100644 --- a/resources/views/components/layouts/nav/sidebar/nav-link.blade.php +++ b/resources/views/components/layouts/nav/sidebar/nav-link.blade.php @@ -6,7 +6,8 @@ ]) @if((is_string($permission) && auth()->user()->hasPermissionTo($permission))) -
  • - url()->current() == $route]) /> +
  • + url()->current() == $route]) />
  • @endif diff --git a/resources/views/components/layouts/nav/topbar.blade.php b/resources/views/components/layouts/nav/topbar.blade.php index f264d52..370af04 100644 --- a/resources/views/components/layouts/nav/topbar.blade.php +++ b/resources/views/components/layouts/nav/topbar.blade.php @@ -1,28 +1,64 @@ - + diff --git a/resources/views/components/layouts/⚔language-switcher/language-switcher.blade.php b/resources/views/components/layouts/⚔language-switcher/language-switcher.blade.php index 140bb3a..8a759ee 100644 --- a/resources/views/components/layouts/⚔language-switcher/language-switcher.blade.php +++ b/resources/views/components/layouts/⚔language-switcher/language-switcher.blade.php @@ -1,5 +1,5 @@
    - diff --git a/resources/views/components/layouts/⚔notification/notification.blade.php b/resources/views/components/layouts/⚔notification/notification.blade.php index e3ec065..74afa95 100644 --- a/resources/views/components/layouts/⚔notification/notification.blade.php +++ b/resources/views/components/layouts/⚔notification/notification.blade.php @@ -1,5 +1,5 @@
    -