mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 12:44:22 +00:00
refactor(frontend): consolidate shared page-shell rules into one stylesheet
Every panel page CSS file repeated the same wrapper boilerplate — the --bg-page/--bg-card token triples for light/dark/ultra-dark, the min-height + background root rule, the .ant-layout transparent reset, the .content-shell transparent reset, and the .loading-spacer min-height. That's ~30 identical lines duplicated across IndexPage, ClientsPage, InboundsPage, XrayPage, SettingsPage, NodesPage, and ApiDocsPage. Move all of it into styles/page-shell.css and import it once from main.tsx alongside utils.css and page-cards.css. Each page CSS file now only contains genuinely page-specific rules (content-area padding overrides, page-specific tokens like ApiDocs's Swagger --sw-* set). Also drop the per-page `import '@/styles/page-cards.css'` statements from the 7 page tsx files now that main.tsx loads it globally. Net: -211 deleted, +6 inserted in the touched files, plus the new page-shell.css. .zero-margin (Divider override used by Nord/Warp modals) folded into utils.css alongside the margin classes.
This commit is contained in:
parent
21e1be43bd
commit
4e7cecb71b
19 changed files with 71 additions and 211 deletions
|
|
@ -3,6 +3,8 @@ import { RouterProvider } from 'react-router-dom';
|
|||
import { message } from 'antd';
|
||||
import 'antd/dist/reset.css';
|
||||
import '@/styles/utils.css';
|
||||
import '@/styles/page-shell.css';
|
||||
import '@/styles/page-cards.css';
|
||||
|
||||
import { setupAxios } from '@/api/axios-init';
|
||||
import { readyI18n } from '@/i18n/react';
|
||||
|
|
|
|||
|
|
@ -1,13 +1,4 @@
|
|||
.api-docs-page {
|
||||
--bg-page: #e6e8ec;
|
||||
--bg-card: #ffffff;
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.api-docs-page.is-dark {
|
||||
--bg-page: #1a1b1f;
|
||||
--bg-card: #23252b;
|
||||
--sw-bg: #1f2026;
|
||||
--sw-bg-soft: #25272e;
|
||||
--sw-bg-input: #15161a;
|
||||
|
|
@ -22,8 +13,6 @@
|
|||
}
|
||||
|
||||
.api-docs-page.is-dark.is-ultra {
|
||||
--bg-page: #000;
|
||||
--bg-card: #101013;
|
||||
--sw-bg: #0a0a0d;
|
||||
--sw-bg-soft: #131316;
|
||||
--sw-bg-input: #050507;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import 'swagger-ui-react/swagger-ui.css';
|
|||
|
||||
import { useTheme } from '@/hooks/useTheme';
|
||||
import AppSidebar from '@/components/AppSidebar';
|
||||
import '@/styles/page-cards.css';
|
||||
import './ApiDocsPage.css';
|
||||
|
||||
const basePath = window.X_UI_BASE_PATH || '';
|
||||
|
|
|
|||
|
|
@ -1,29 +1,3 @@
|
|||
.clients-page {
|
||||
--bg-page: #e6e8ec;
|
||||
--bg-card: #ffffff;
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.clients-page.is-dark {
|
||||
--bg-page: #1a1b1f;
|
||||
--bg-card: #23252b;
|
||||
}
|
||||
|
||||
.clients-page.is-dark.is-ultra {
|
||||
--bg-page: #000;
|
||||
--bg-card: #101013;
|
||||
}
|
||||
|
||||
.clients-page .ant-layout,
|
||||
.clients-page .ant-layout-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.clients-page .content-shell {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.clients-page .content-area {
|
||||
padding: 24px;
|
||||
}
|
||||
|
|
@ -39,10 +13,6 @@
|
|||
min-width: 100px;
|
||||
}
|
||||
|
||||
.clients-page .loading-spacer {
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.clients-page .summary-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ const ClientInfoModal = lazy(() => import('./ClientInfoModal'));
|
|||
const ClientQrModal = lazy(() => import('./ClientQrModal'));
|
||||
const ClientBulkAddModal = lazy(() => import('./ClientBulkAddModal'));
|
||||
const ClientBulkAdjustModal = lazy(() => import('./ClientBulkAdjustModal'));
|
||||
import '@/styles/page-cards.css';
|
||||
import './ClientsPage.css';
|
||||
|
||||
const FILTER_STATE_KEY = 'clientsFilterState';
|
||||
|
|
|
|||
|
|
@ -1,44 +1,13 @@
|
|||
.inbounds-page {
|
||||
--bg-page: #e6e8ec;
|
||||
--bg-card: #ffffff;
|
||||
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.inbounds-page.is-dark {
|
||||
--bg-page: #1a1b1f;
|
||||
--bg-card: #23252b;
|
||||
}
|
||||
|
||||
.inbounds-page.is-dark.is-ultra {
|
||||
--bg-page: #000;
|
||||
--bg-card: #101013;
|
||||
}
|
||||
|
||||
.inbounds-page .ant-layout,
|
||||
.inbounds-page .ant-layout-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.content-shell {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.content-area {
|
||||
.inbounds-page .content-area {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.content-area {
|
||||
.inbounds-page .content-area {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-spacer {
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import LazyMount from '@/components/LazyMount';
|
|||
const InboundFormModal = lazy(() => import('./InboundFormModal'));
|
||||
const InboundInfoModal = lazy(() => import('./InboundInfoModal'));
|
||||
const QrCodeModal = lazy(() => import('./QrCodeModal'));
|
||||
import '@/styles/page-cards.css';
|
||||
import './InboundsPage.css';
|
||||
|
||||
type RowAction =
|
||||
|
|
|
|||
|
|
@ -1,30 +1,3 @@
|
|||
.index-page {
|
||||
--bg-page: #e6e8ec;
|
||||
--bg-card: #ffffff;
|
||||
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.index-page.is-dark {
|
||||
--bg-page: #1a1b1f;
|
||||
--bg-card: #23252b;
|
||||
}
|
||||
|
||||
.index-page.is-dark.is-ultra {
|
||||
--bg-page: #000;
|
||||
--bg-card: #101013;
|
||||
}
|
||||
|
||||
.index-page .ant-layout,
|
||||
.index-page .ant-layout-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.index-page .content-shell {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.index-page .content-area {
|
||||
padding: 24px;
|
||||
}
|
||||
|
|
@ -36,10 +9,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.index-page .loading-spacer {
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.index-page .action {
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ const SystemHistoryModal = lazy(() => import('./SystemHistoryModal'));
|
|||
const XrayMetricsModal = lazy(() => import('./XrayMetricsModal'));
|
||||
const XrayLogModal = lazy(() => import('./XrayLogModal'));
|
||||
const VersionModal = lazy(() => import('./VersionModal'));
|
||||
import '@/styles/page-cards.css';
|
||||
import './IndexPage.css';
|
||||
|
||||
export default function IndexPage() {
|
||||
|
|
|
|||
|
|
@ -1,29 +1,3 @@
|
|||
.nodes-page {
|
||||
--bg-page: #e6e8ec;
|
||||
--bg-card: #ffffff;
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.nodes-page.is-dark {
|
||||
--bg-page: #1a1b1f;
|
||||
--bg-card: #23252b;
|
||||
}
|
||||
|
||||
.nodes-page.is-dark.is-ultra {
|
||||
--bg-page: #000;
|
||||
--bg-card: #101013;
|
||||
}
|
||||
|
||||
.nodes-page .ant-layout,
|
||||
.nodes-page .ant-layout-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.nodes-page .content-shell {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.nodes-page .content-area {
|
||||
padding: 24px;
|
||||
}
|
||||
|
|
@ -34,10 +8,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.nodes-page .loading-spacer {
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.nodes-page .summary-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import AppSidebar from '@/components/AppSidebar';
|
|||
import NodeList from './NodeList';
|
||||
import NodeFormModal from './NodeFormModal';
|
||||
import { setMessageInstance } from '@/utils/messageBus';
|
||||
import '@/styles/page-cards.css';
|
||||
import './NodesPage.css';
|
||||
|
||||
export default function NodesPage() {
|
||||
|
|
|
|||
|
|
@ -1,37 +1,7 @@
|
|||
.settings-page {
|
||||
--bg-page: #e6e8ec;
|
||||
--bg-card: #ffffff;
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.settings-page.is-dark {
|
||||
--bg-page: #1a1b1f;
|
||||
--bg-card: #23252b;
|
||||
}
|
||||
|
||||
.settings-page.is-dark.is-ultra {
|
||||
--bg-page: #000;
|
||||
--bg-card: #101013;
|
||||
}
|
||||
|
||||
.settings-page .ant-layout,
|
||||
.settings-page .ant-layout-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.settings-page .content-shell {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.settings-page .content-area {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.settings-page .loading-spacer {
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.settings-page .conf-alert {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ import SecurityTab from './SecurityTab';
|
|||
import TelegramTab from './TelegramTab';
|
||||
import SubscriptionGeneralTab from './SubscriptionGeneralTab';
|
||||
import SubscriptionFormatsTab from './SubscriptionFormatsTab';
|
||||
import '@/styles/page-cards.css';
|
||||
import './SettingsPage.css';
|
||||
|
||||
interface ApiMsg {
|
||||
|
|
|
|||
|
|
@ -22,10 +22,6 @@
|
|||
background: var(--ant-color-fill-tertiary);
|
||||
}
|
||||
|
||||
.zero-margin {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.server-row {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -22,10 +22,6 @@
|
|||
background: var(--ant-color-fill-tertiary);
|
||||
}
|
||||
|
||||
.zero-margin {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.license-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -1,38 +1,7 @@
|
|||
.xray-page {
|
||||
--bg-page: #e6e8ec;
|
||||
--bg-card: #ffffff;
|
||||
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.xray-page.is-dark {
|
||||
--bg-page: #1a1b1f;
|
||||
--bg-card: #23252b;
|
||||
}
|
||||
|
||||
.xray-page.is-dark.is-ultra {
|
||||
--bg-page: #000;
|
||||
--bg-card: #101013;
|
||||
}
|
||||
|
||||
.xray-page .ant-layout,
|
||||
.xray-page .ant-layout-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.xray-page .content-shell {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.xray-page .content-area {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.xray-page .loading-spacer {
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.xray-page .header-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ import BalancersTab from './BalancersTab';
|
|||
import DnsTab from './DnsTab';
|
||||
import WarpModal from './WarpModal';
|
||||
import NordModal from './NordModal';
|
||||
import '@/styles/page-cards.css';
|
||||
import './XrayPage.css';
|
||||
|
||||
const TAB_KEYS = ['tpl-basic', 'tpl-routing', 'tpl-outbound', 'tpl-balancer', 'tpl-dns', 'tpl-advanced'];
|
||||
|
|
|
|||
65
frontend/src/styles/page-shell.css
Normal file
65
frontend/src/styles/page-shell.css
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
.index-page,
|
||||
.clients-page,
|
||||
.inbounds-page,
|
||||
.xray-page,
|
||||
.settings-page,
|
||||
.nodes-page,
|
||||
.api-docs-page {
|
||||
--bg-page: #e6e8ec;
|
||||
--bg-card: #ffffff;
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.index-page.is-dark,
|
||||
.clients-page.is-dark,
|
||||
.inbounds-page.is-dark,
|
||||
.xray-page.is-dark,
|
||||
.settings-page.is-dark,
|
||||
.nodes-page.is-dark,
|
||||
.api-docs-page.is-dark {
|
||||
--bg-page: #1a1b1f;
|
||||
--bg-card: #23252b;
|
||||
}
|
||||
|
||||
.index-page.is-dark.is-ultra,
|
||||
.clients-page.is-dark.is-ultra,
|
||||
.inbounds-page.is-dark.is-ultra,
|
||||
.xray-page.is-dark.is-ultra,
|
||||
.settings-page.is-dark.is-ultra,
|
||||
.nodes-page.is-dark.is-ultra,
|
||||
.api-docs-page.is-dark.is-ultra {
|
||||
--bg-page: #000;
|
||||
--bg-card: #101013;
|
||||
}
|
||||
|
||||
.index-page .ant-layout,
|
||||
.index-page .ant-layout-content,
|
||||
.clients-page .ant-layout,
|
||||
.clients-page .ant-layout-content,
|
||||
.inbounds-page .ant-layout,
|
||||
.inbounds-page .ant-layout-content,
|
||||
.xray-page .ant-layout,
|
||||
.xray-page .ant-layout-content,
|
||||
.settings-page .ant-layout,
|
||||
.settings-page .ant-layout-content,
|
||||
.nodes-page .ant-layout,
|
||||
.nodes-page .ant-layout-content,
|
||||
.api-docs-page .ant-layout,
|
||||
.api-docs-page .ant-layout-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.index-page .content-shell,
|
||||
.clients-page .content-shell,
|
||||
.inbounds-page .content-shell,
|
||||
.xray-page .content-shell,
|
||||
.settings-page .content-shell,
|
||||
.nodes-page .content-shell,
|
||||
.api-docs-page .content-shell {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.loading-spacer {
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
|
@ -13,3 +13,5 @@
|
|||
|
||||
.my-8 { margin: 8px 0; }
|
||||
.my-10 { margin: 10px 0; }
|
||||
|
||||
.zero-margin { margin: 0; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue