mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-02-27 20:53:01 +00:00
feat(ui): add selectable tech theme and dashboard layout polish
This commit is contained in:
parent
b6ef094b0f
commit
4c612e463b
5 changed files with 648 additions and 51 deletions
532
web/assets/css/cyberpunk-theme.css
Normal file
532
web/assets/css/cyberpunk-theme.css
Normal file
|
|
@ -0,0 +1,532 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap');
|
||||
|
||||
body.cyberpunk {
|
||||
--font-mono: 'JetBrains Mono', 'IBM Plex Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
|
||||
--bg-app: #090b10;
|
||||
--bg-panel: #0f131b;
|
||||
--bg-elev: #161c27;
|
||||
--bg-soft: #1b2331;
|
||||
|
||||
--text-1: #e6edf7;
|
||||
--text-2: #b8c3d6;
|
||||
--text-3: #7d8aa1;
|
||||
|
||||
--line-1: #263044;
|
||||
--line-2: #33415a;
|
||||
--accent: #8aa4d6;
|
||||
--accent-2: #9fb5dd;
|
||||
--danger: #c97f90;
|
||||
--success: #85b79a;
|
||||
--warn: #c8b08a;
|
||||
|
||||
color: var(--text-1);
|
||||
font-family: var(--font-mono);
|
||||
letter-spacing: 0;
|
||||
background-color: var(--bg-app);
|
||||
background-image:
|
||||
linear-gradient(rgba(160, 180, 210, 0.03) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(160, 180, 210, 0.03) 1px, transparent 1px);
|
||||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
body.cyberpunk * {
|
||||
font-family: var(--font-mono) !important;
|
||||
transition: background-color 180ms ease, color 180ms ease, border-color 180ms ease, box-shadow 180ms ease !important;
|
||||
}
|
||||
|
||||
body.cyberpunk #app {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout,
|
||||
body.cyberpunk .ant-layout-content,
|
||||
body.cyberpunk #content-layout,
|
||||
body.cyberpunk .ant-drawer-content,
|
||||
body.cyberpunk .ant-drawer-wrapper-body,
|
||||
body.cyberpunk .ant-menu,
|
||||
body.cyberpunk .ant-menu-sub {
|
||||
background: transparent !important;
|
||||
color: var(--text-1);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-content {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider {
|
||||
background: var(--bg-panel) !important;
|
||||
border: 1px solid var(--line-1);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider,
|
||||
body.cyberpunk .ant-card,
|
||||
body.cyberpunk .ant-alert,
|
||||
body.cyberpunk .ant-tabs,
|
||||
body.cyberpunk .ant-table,
|
||||
body.cyberpunk .ant-modal-content {
|
||||
box-shadow: none !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider-children {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-sidebar > .ant-layout-sider {
|
||||
min-width: 72px !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .panel-brand {
|
||||
margin: 8px;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--line-1);
|
||||
border-radius: 2px;
|
||||
background: var(--bg-elev);
|
||||
}
|
||||
|
||||
body.cyberpunk .panel-brand-mark {
|
||||
border-radius: 2px;
|
||||
background: #202938;
|
||||
border: 1px solid var(--line-2);
|
||||
color: var(--text-1);
|
||||
}
|
||||
|
||||
body.cyberpunk .panel-brand-text {
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-item,
|
||||
body.cyberpunk .ant-menu-submenu-title,
|
||||
body.cyberpunk .ant-menu-theme-switch {
|
||||
min-height: 40px;
|
||||
line-height: 40px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid transparent;
|
||||
margin: 4px 0 !important;
|
||||
color: var(--text-2) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-inline .ant-menu-item,
|
||||
body.cyberpunk .ant-menu-inline .ant-menu-submenu-title {
|
||||
width: calc(100% - 4px);
|
||||
margin-left: 2px !important;
|
||||
margin-right: 2px !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-item > span {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-inline-collapsed > .ant-menu-item > span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-item .anticon,
|
||||
body.cyberpunk .ant-menu-submenu-title .anticon {
|
||||
color: var(--text-3) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-item:hover,
|
||||
body.cyberpunk .ant-menu-submenu-title:hover,
|
||||
body.cyberpunk .ant-menu-theme-switch:hover {
|
||||
background: var(--bg-elev) !important;
|
||||
border-color: var(--line-1);
|
||||
color: var(--text-1) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-item-selected {
|
||||
background: #202d43 !important;
|
||||
border-color: #435779 !important;
|
||||
color: var(--text-1) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-item-selected .anticon {
|
||||
color: var(--accent) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
|
||||
background-color: #202d43 !important;
|
||||
background-image: none !important;
|
||||
animation: none !important;
|
||||
border-radius: 2px !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected,
|
||||
body.cyberpunk .ant-layout-sider .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected:hover,
|
||||
body.cyberpunk .ant-layout-sider .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected:active {
|
||||
background: #202d43 !important;
|
||||
background-color: #202d43 !important;
|
||||
background-image: none !important;
|
||||
border-color: #435779 !important;
|
||||
color: var(--text-1) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider .ant-menu-item-active,
|
||||
body.cyberpunk .ant-layout-sider .ant-menu-item:hover,
|
||||
body.cyberpunk .ant-layout-sider .ant-menu-submenu-title:hover {
|
||||
background: #172033 !important;
|
||||
background-image: none !important;
|
||||
border-color: var(--line-1) !important;
|
||||
color: var(--text-1) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-menu-item:active,
|
||||
body.cyberpunk .ant-menu-item-active,
|
||||
body.cyberpunk .ant-menu-item:hover,
|
||||
body.cyberpunk .ant-menu-submenu-title:hover {
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider-collapsed .ant-menu-item,
|
||||
body.cyberpunk .ant-layout-sider-collapsed .ant-menu-submenu-title {
|
||||
padding-inline: 0 !important;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider-collapsed .ant-menu-item .anticon,
|
||||
body.cyberpunk .ant-layout-sider-collapsed .ant-menu-submenu-title .anticon {
|
||||
margin: 0 !important;
|
||||
font-size: 14px;
|
||||
color: #94a4bf !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider-collapsed .ant-menu-item-selected .anticon {
|
||||
color: #d0dcef !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider-trigger {
|
||||
background: #141e2f !important;
|
||||
border-top: 1px solid var(--line-1);
|
||||
color: var(--text-3) !important;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-layout-sider-trigger:hover {
|
||||
background: #1a273c !important;
|
||||
color: var(--text-1) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-submenu-arrow,
|
||||
body.cyberpunk .ant-menu-submenu-arrow::before,
|
||||
body.cyberpunk .ant-menu-submenu-arrow::after {
|
||||
background: var(--text-3) !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-radio-wrapper {
|
||||
color: var(--text-1) !important;
|
||||
opacity: 1 !important;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-radio-inner {
|
||||
border-radius: 2px;
|
||||
border-color: var(--line-2);
|
||||
background: #101521;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-radio-inner::after {
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-radio-wrapper:hover .ant-radio-inner,
|
||||
body.cyberpunk .ant-radio-checked .ant-radio-inner {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-alert {
|
||||
border-radius: 2px;
|
||||
border: 1px solid #5b3740;
|
||||
background: #271a1f;
|
||||
}
|
||||
|
||||
body.cyberpunk .theme-picker-item,
|
||||
body.cyberpunk .theme-picker-item.ant-menu-item {
|
||||
height: auto !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .theme-picker-item .ant-radio-group,
|
||||
body.cyberpunk .theme-picker-item .ant-space {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body.cyberpunk .theme-picker-item .ant-radio-wrapper {
|
||||
min-height: 24px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-alert-message {
|
||||
color: #dfb0bb;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-alert-description {
|
||||
color: #c396a1;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-card,
|
||||
body.cyberpunk .ant-tabs,
|
||||
body.cyberpunk .ant-table,
|
||||
body.cyberpunk .ant-modal-content,
|
||||
body.cyberpunk .ant-dropdown-menu,
|
||||
body.cyberpunk .ant-popover-inner,
|
||||
body.cyberpunk .ant-select-dropdown,
|
||||
body.cyberpunk .ant-calendar,
|
||||
body.cyberpunk .ant-collapse {
|
||||
background: var(--bg-panel);
|
||||
border: 1px solid var(--line-1);
|
||||
border-radius: 2px !important;
|
||||
box-shadow: none;
|
||||
color: var(--text-1);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-card::before,
|
||||
body.cyberpunk .ant-card::after {
|
||||
content: none !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-card:hover {
|
||||
border-color: var(--line-2);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-card-head,
|
||||
body.cyberpunk .ant-modal-header,
|
||||
body.cyberpunk .ant-collapse > .ant-collapse-item > .ant-collapse-header,
|
||||
body.cyberpunk .ant-table-thead > tr > th {
|
||||
background: var(--bg-elev);
|
||||
border-bottom: 1px solid var(--line-1);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-card-head-title,
|
||||
body.cyberpunk .ant-modal-title,
|
||||
body.cyberpunk .ant-form-item-label > label,
|
||||
body.cyberpunk .ant-statistic-title,
|
||||
body.cyberpunk .ant-table-thead > tr > th {
|
||||
color: var(--text-2) !important;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-card-actions {
|
||||
background: var(--bg-elev);
|
||||
border-top: 1px solid var(--line-1);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-card-actions > li > span {
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-btn {
|
||||
border-radius: 2px !important;
|
||||
height: 34px;
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-btn,
|
||||
body.cyberpunk .ant-btn-default {
|
||||
background: var(--bg-elev);
|
||||
border-color: var(--line-2);
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-btn:hover,
|
||||
body.cyberpunk .ant-btn:focus {
|
||||
border-color: var(--accent);
|
||||
color: var(--text-1);
|
||||
background: var(--bg-soft);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-btn-primary {
|
||||
background: #243248;
|
||||
border-color: #3e5374;
|
||||
color: #dbe6f7;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-btn-primary:hover,
|
||||
body.cyberpunk .ant-btn-primary:focus {
|
||||
background: #2a3b56;
|
||||
border-color: #4b6288;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-btn-danger,
|
||||
body.cyberpunk .ant-btn-dangerous {
|
||||
background: #3a262c;
|
||||
border-color: #70424d;
|
||||
color: #d9a9b4;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-input,
|
||||
body.cyberpunk .ant-input-number,
|
||||
body.cyberpunk .ant-input-number-input,
|
||||
body.cyberpunk .ant-select-selection,
|
||||
body.cyberpunk textarea.ant-input {
|
||||
background: #0d121d !important;
|
||||
border: 1px solid var(--line-2) !important;
|
||||
border-radius: 2px !important;
|
||||
color: var(--text-1) !important;
|
||||
min-height: 34px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-input::placeholder,
|
||||
body.cyberpunk textarea.ant-input::placeholder {
|
||||
color: var(--text-3);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-input:hover,
|
||||
body.cyberpunk .ant-input:focus,
|
||||
body.cyberpunk .ant-input-number:hover,
|
||||
body.cyberpunk .ant-input-number-focused,
|
||||
body.cyberpunk .ant-select-focused .ant-select-selection,
|
||||
body.cyberpunk .ant-select-selection:hover {
|
||||
border-color: var(--accent) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-tag {
|
||||
border-radius: 2px;
|
||||
background: #1a2230;
|
||||
border: 1px solid var(--line-2);
|
||||
color: var(--text-2);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-tag-green { background: #1d2b25; border-color: #355241; color: #9cccb0; }
|
||||
body.cyberpunk .ant-tag-red { background: #2f2025; border-color: #5f3a45; color: #d6a0ad; }
|
||||
body.cyberpunk .ant-tag-orange { background: #31291f; border-color: #64523a; color: #d2bc97; }
|
||||
body.cyberpunk .ant-tag-purple { background: #202736; border-color: #3f4f6b; color: #b6c7e7; }
|
||||
|
||||
body.cyberpunk .ant-statistic-content {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: var(--text-1);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-progress-text {
|
||||
color: var(--text-2);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-progress-trail {
|
||||
stroke: #273247;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-table {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-table-thead > tr > th {
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-table-tbody > tr > td {
|
||||
border-bottom: 1px solid #212c3f;
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-table-tbody > tr:hover > td {
|
||||
background: #1a2232;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-pagination-item,
|
||||
body.cyberpunk .ant-pagination-prev .ant-pagination-item-link,
|
||||
body.cyberpunk .ant-pagination-next .ant-pagination-item-link {
|
||||
background: var(--bg-elev);
|
||||
border: 1px solid var(--line-2);
|
||||
border-radius: 2px;
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-pagination-item-active {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-tabs-bar {
|
||||
border-bottom: 1px solid var(--line-1);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-tabs-tab {
|
||||
color: var(--text-3);
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-tabs-tab:hover,
|
||||
body.cyberpunk .ant-tabs-tab-active {
|
||||
color: var(--text-1);
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-tabs-ink-bar {
|
||||
background: var(--accent-2);
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
body.cyberpunk .ant-modal-mask {
|
||||
background: rgba(6, 8, 12, 0.78);
|
||||
}
|
||||
|
||||
body.cyberpunk .waves-header {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .title,
|
||||
body.cyberpunk h1,
|
||||
body.cyberpunk h2,
|
||||
body.cyberpunk h3 {
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
body.cyberpunk .xray-running-animation .ant-badge-status-dot,
|
||||
body.cyberpunk .online-animation .ant-badge-status-dot {
|
||||
animation: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
body.cyberpunk ::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
body.cyberpunk ::-webkit-scrollbar-thumb {
|
||||
border-radius: 2px;
|
||||
background: #2a3448;
|
||||
}
|
||||
|
||||
body.cyberpunk ::-webkit-scrollbar-thumb:hover {
|
||||
background: #374761;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body.cyberpunk #app { padding: 6px; }
|
||||
body.cyberpunk .ant-layout-content { margin-left: 0; margin-top: 8px; }
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
body.cyberpunk .index-page .dashboard-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||
gap: 12px 16px;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .index-page .dashboard-grid > .ant-col {
|
||||
max-width: none !important;
|
||||
width: auto !important;
|
||||
flex: none !important;
|
||||
float: none !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
body.cyberpunk .index-page .dashboard-grid > .ant-col:first-child {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
<meta name="robots" content="noindex,nofollow">
|
||||
<link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue/antd.min.css">
|
||||
<link rel="stylesheet" href="{{ .base_path }}assets/css/custom.min.css?{{ .cur_ver }}">
|
||||
<link rel="stylesheet" href="{{ .base_path }}assets/css/cyberpunk-theme.css?{{ .cur_ver }}-tech-v2">
|
||||
<style>
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
|
|
@ -89,4 +90,4 @@
|
|||
{{ define "page/body_end" }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
{{define "component/sidebar/content"}}
|
||||
<template>
|
||||
<div class="ant-sidebar">
|
||||
<a-layout-sider :theme="themeSwitcher.currentTheme" collapsible :collapsed="collapsed"
|
||||
<a-layout-sider :theme="themeSwitcher.currentTheme" :width="228" :collapsed-width="72" collapsible :collapsed="collapsed"
|
||||
@collapse="(isCollapsed, type) => collapseHandle(isCollapsed, type)" breakpoint="md">
|
||||
<div class="panel-brand" :class="{ collapsed: collapsed }">
|
||||
<span class="panel-brand-mark">3X</span>
|
||||
<span class="panel-brand-text" v-if="!collapsed">Control Grid</span>
|
||||
</div>
|
||||
<a-theme-switch></a-theme-switch>
|
||||
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" :selected-keys="activeTab"
|
||||
@click="({key}) => openLink(key)">
|
||||
|
|
@ -17,6 +21,10 @@
|
|||
<div class="drawer-handle" @click="toggleDrawer" slot="handle">
|
||||
<a-icon :type="visible ? 'close' : 'menu-fold'"></a-icon>
|
||||
</div>
|
||||
<div class="panel-brand">
|
||||
<span class="panel-brand-mark">3X</span>
|
||||
<span class="panel-brand-text">Control Grid</span>
|
||||
</div>
|
||||
<a-theme-switch></a-theme-switch>
|
||||
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" :selected-keys="activeTab"
|
||||
@click="({key}) => openLink(key)">
|
||||
|
|
@ -35,6 +43,27 @@
|
|||
.ant-sidebar>.ant-layout-sider {
|
||||
height: 100%;
|
||||
}
|
||||
.panel-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 10px 10px 4px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.panel-brand-mark {
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.18em;
|
||||
font-weight: 700;
|
||||
padding: 3px 6px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.panel-brand-text {
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
opacity: 0.85;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -3,19 +3,23 @@
|
|||
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" selected-keys="">
|
||||
<a-sub-menu>
|
||||
<span slot="title">
|
||||
<a-icon type="bulb" :theme="themeSwitcher.isDarkTheme ? 'filled' : 'outlined'"></a-icon>
|
||||
<a-icon type="bulb" :theme="themeSwitcher.currentTheme === 'light' ? 'outlined' : 'filled'"></a-icon>
|
||||
<span>{{ i18n "menu.theme" }}</span>
|
||||
</span>
|
||||
<a-menu-item id="change-theme" class="ant-menu-theme-switch" @mousedown="themeSwitcher.animationsOff()">
|
||||
<span>{{ i18n "menu.dark" }}</span>
|
||||
<a-switch :style="{ marginLeft: '2px' }" size="small" :default-checked="themeSwitcher.isDarkTheme"
|
||||
@change="themeSwitcher.toggleTheme()"></a-switch>
|
||||
</a-menu-item>
|
||||
<a-menu-item id="change-theme-ultra" v-if="themeSwitcher.isDarkTheme" class="ant-menu-theme-switch"
|
||||
@mousedown="themeSwitcher.animationsOffUltra()">
|
||||
<span>{{ i18n "menu.ultraDark" }}</span>
|
||||
<a-checkbox :style="{ marginLeft: '2px' }" :checked="themeSwitcher.isUltra"
|
||||
@click="themeSwitcher.toggleUltra()"></a-checkbox>
|
||||
<a-menu-item
|
||||
id="change-theme"
|
||||
class="ant-menu-theme-switch theme-picker-item"
|
||||
:style="{ height: 'auto', lineHeight: 'normal', paddingTop: '8px', paddingBottom: '8px' }"
|
||||
@mousedown.stop="themeSwitcher.animationsOff()"
|
||||
@click.stop>
|
||||
<a-radio-group :value="themeSwitcher.selectedTheme" @change="themeSwitcher.selectTheme($event.target.value)" @click.stop>
|
||||
<a-space direction="vertical" :size="8">
|
||||
<a-radio value="light">Light</a-radio>
|
||||
<a-radio value="dark">{{ i18n "menu.dark" }}</a-radio>
|
||||
<a-radio value="ultra-dark">{{ i18n "menu.ultraDark" }}</a-radio>
|
||||
<a-radio value="cyberpunk">Cyberpunk</a-radio>
|
||||
</a-space>
|
||||
</a-radio-group>
|
||||
</a-menu-item>
|
||||
</a-sub-menu>
|
||||
</a-menu>
|
||||
|
|
@ -25,29 +29,72 @@
|
|||
{{define "component/themeSwitchTemplateLogin"}}
|
||||
<template>
|
||||
<a-space @mousedown="themeSwitcher.animationsOff()" id="change-theme" direction="vertical" :size="10" :style="{ width: '100%' }">
|
||||
<a-space direction="horizontal" size="small">
|
||||
<a-switch size="small" :default-checked="themeSwitcher.isDarkTheme" @change="themeSwitcher.toggleTheme()"></a-switch>
|
||||
<span>{{ i18n "menu.dark" }}</span>
|
||||
</a-space>
|
||||
<a-space v-if="themeSwitcher.isDarkTheme" direction="horizontal" size="small">
|
||||
<a-checkbox :checked="themeSwitcher.isUltra" @click="themeSwitcher.toggleUltra()"></a-checkbox>
|
||||
<span>{{ i18n "menu.ultraDark" }}</span>
|
||||
</a-space>
|
||||
<a-radio-group :value="themeSwitcher.selectedTheme" @change="themeSwitcher.selectTheme($event.target.value)">
|
||||
<a-space direction="vertical" :size="8">
|
||||
<a-radio value="light">Light</a-radio>
|
||||
<a-radio value="dark">{{ i18n "menu.dark" }}</a-radio>
|
||||
<a-radio value="ultra-dark">{{ i18n "menu.ultraDark" }}</a-radio>
|
||||
<a-radio value="cyberpunk">Cyberpunk</a-radio>
|
||||
</a-space>
|
||||
</a-radio-group>
|
||||
</a-space>
|
||||
</template>
|
||||
{{end}}
|
||||
|
||||
{{define "component/aThemeSwitch"}}
|
||||
<style>
|
||||
.theme-picker-item.ant-menu-item-selected {
|
||||
background: transparent !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function createThemeSwitcher() {
|
||||
const isDarkTheme = localStorage.getItem('dark-mode') === 'true';
|
||||
const isUltra = localStorage.getItem('isUltraDarkThemeEnabled') === 'true';
|
||||
if (isUltra) {
|
||||
document.documentElement.setAttribute('data-theme', 'ultra-dark');
|
||||
const isCyberpunk = localStorage.getItem('cyberpunk-mode') === 'true';
|
||||
|
||||
const selectedTheme = isCyberpunk
|
||||
? 'cyberpunk'
|
||||
: isUltra
|
||||
? 'ultra-dark'
|
||||
: isDarkTheme
|
||||
? 'dark'
|
||||
: 'light';
|
||||
|
||||
function applyTheme(theme) {
|
||||
const body = document.querySelector('body');
|
||||
const root = document.documentElement;
|
||||
const dark = theme !== 'light';
|
||||
const ultra = theme === 'ultra-dark';
|
||||
const cyberpunk = theme === 'cyberpunk';
|
||||
|
||||
body.setAttribute('class', dark ? 'dark' : 'light');
|
||||
body.classList.toggle('cyberpunk', cyberpunk);
|
||||
|
||||
if (ultra) {
|
||||
root.setAttribute('data-theme', 'ultra-dark');
|
||||
} else {
|
||||
root.removeAttribute('data-theme');
|
||||
}
|
||||
|
||||
localStorage.setItem('dark-mode', dark.toString());
|
||||
localStorage.setItem('isUltraDarkThemeEnabled', ultra.toString());
|
||||
localStorage.setItem('cyberpunk-mode', cyberpunk.toString());
|
||||
}
|
||||
const theme = isDarkTheme ? 'dark' : 'light';
|
||||
document.querySelector('body').setAttribute('class', theme);
|
||||
|
||||
applyTheme(selectedTheme);
|
||||
|
||||
return {
|
||||
selectedTheme,
|
||||
isDarkTheme: selectedTheme !== 'light',
|
||||
isUltra: selectedTheme === 'ultra-dark',
|
||||
isCyberpunk: selectedTheme === 'cyberpunk',
|
||||
syncFlags() {
|
||||
this.isDarkTheme = this.selectedTheme !== 'light';
|
||||
this.isUltra = this.selectedTheme === 'ultra-dark';
|
||||
this.isCyberpunk = this.selectedTheme === 'cyberpunk';
|
||||
},
|
||||
animationsOff() {
|
||||
document.documentElement.setAttribute('data-theme-animations', 'off');
|
||||
const themeAnimations = document.querySelector('#change-theme');
|
||||
|
|
@ -58,35 +105,23 @@
|
|||
document.documentElement.removeAttribute('data-theme-animations');
|
||||
});
|
||||
},
|
||||
animationsOffUltra() {
|
||||
document.documentElement.setAttribute('data-theme-animations', 'off');
|
||||
const themeAnimationsUltra = document.querySelector('#change-theme-ultra');
|
||||
themeAnimationsUltra.addEventListener('mouseleave', () => {
|
||||
document.documentElement.removeAttribute('data-theme-animations');
|
||||
});
|
||||
themeAnimationsUltra.addEventListener('touchend', () => {
|
||||
document.documentElement.removeAttribute('data-theme-animations');
|
||||
});
|
||||
},
|
||||
isDarkTheme,
|
||||
isUltra,
|
||||
get currentTheme() {
|
||||
return this.isDarkTheme ? 'dark' : 'light';
|
||||
return this.selectedTheme === 'light' ? 'light' : 'dark';
|
||||
},
|
||||
selectTheme(theme) {
|
||||
this.selectedTheme = theme;
|
||||
this.syncFlags();
|
||||
applyTheme(theme);
|
||||
document.getElementById('message').className = this.currentTheme;
|
||||
},
|
||||
toggleTheme() {
|
||||
this.isDarkTheme = !this.isDarkTheme;
|
||||
localStorage.setItem('dark-mode', this.isDarkTheme);
|
||||
document.querySelector('body').setAttribute('class', this.isDarkTheme ? 'dark' : 'light');
|
||||
document.getElementById('message').className = themeSwitcher.currentTheme;
|
||||
this.selectTheme(this.currentTheme === 'light' ? 'dark' : 'light');
|
||||
},
|
||||
toggleUltra() {
|
||||
this.isUltra = !this.isUltra;
|
||||
if (this.isUltra) {
|
||||
document.documentElement.setAttribute('data-theme', 'ultra-dark');
|
||||
} else {
|
||||
document.documentElement.removeAttribute('data-theme');
|
||||
}
|
||||
localStorage.setItem('isUltraDarkThemeEnabled', this.isUltra.toString());
|
||||
this.selectTheme(this.selectedTheme === 'ultra-dark' ? 'dark' : 'ultra-dark');
|
||||
},
|
||||
toggleCyberpunk() {
|
||||
this.selectTheme(this.selectedTheme === 'cyberpunk' ? 'dark' : 'cyberpunk');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -116,4 +151,4 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||
</a-card>
|
||||
</a-row>
|
||||
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||
<a-row class="dashboard-grid" :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||
<a-col>
|
||||
<a-card hoverable>
|
||||
<a-row :gutter="[0, isMobile ? 16 : 0]">
|
||||
|
|
|
|||
Loading…
Reference in a new issue