feat: 引入 postcss-nested

This commit is contained in:
Hooray Hu 2024-08-26 23:16:32 +08:00
parent fab5d0539b
commit 2fe0fc95ee
31 changed files with 155 additions and 131 deletions

View File

@ -81,6 +81,7 @@
"picocolors": "^1.0.1",
"plop": "^4.0.1",
"postcss": "^8.4.40",
"postcss-nested": "^6.2.0",
"sass": "^1.77.8",
"simple-git-hooks": "^2.11.1",
"stylelint": "^16.8.1",

View File

@ -12,6 +12,6 @@ defineOptions({
</div>
</template>
<style lang="scss" scoped>
// 样式
<style scoped>
/* 样式 */
</style>

View File

@ -17,6 +17,6 @@ defineOptions({
</div>
</template>
<style lang="scss" scoped>
// 样式
<style scoped>
/* 样式 */
</style>

View File

@ -177,6 +177,9 @@ importers:
postcss:
specifier: ^8.4.40
version: 8.4.40
postcss-nested:
specifier: ^6.2.0
version: 6.2.0(postcss@8.4.40)
sass:
specifier: ^1.77.8
version: 1.77.8
@ -4949,6 +4952,12 @@ packages:
postcss-media-query-parser@0.2.3:
resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==}
postcss-nested@6.2.0:
resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
engines: {node: '>=12.0'}
peerDependencies:
postcss: ^8.2.14
postcss-prefix-selector@1.16.0:
resolution: {integrity: sha512-rdVMIi7Q4B0XbXqNUEI+Z4E+pueiu/CS5E6vRCQommzdQ/sgsS4dK42U7GX8oJR+TJOtT+Qv3GkNo6iijUMp3Q==}
peerDependencies:
@ -11467,6 +11476,11 @@ snapshots:
postcss-media-query-parser@0.2.3: {}
postcss-nested@6.2.0(postcss@8.4.40):
dependencies:
postcss: 8.4.40
postcss-selector-parser: 6.1.1
postcss-prefix-selector@1.16.0(postcss@5.2.18):
dependencies:
postcss: 5.2.18

View File

@ -1,5 +1,6 @@
export default {
plugins: {
autoprefixer: {},
'autoprefixer': {},
'postcss-nested': {},
},
}

View File

@ -1,20 +1,24 @@
// 页面布局 CSS 变量
/* 页面布局 CSS 变量 */
:root {
// 头部高度
/* 头部高度 */
--g-header-height: 60px;
// 侧边栏宽度
/* 侧边栏宽度 */
--g-main-sidebar-width: 80px;
--g-sub-sidebar-width: 220px;
--g-sub-sidebar-collapse-width: 64px;
// 侧边栏 Logo 区域高度
/* 侧边栏 Logo 区域高度 */
--g-sidebar-logo-height: 50px;
// 标签栏高度
/* 标签栏高度 */
--g-tabbar-height: 50px;
// 工具栏高度
/* 工具栏高度 */
--g-toolbar-height: 50px;
}
// 明暗模式 CSS 变量
/* 明暗模式 CSS 变量 */
/* stylelint-disable-next-line no-duplicate-selectors */
:root {
--g-box-shadow-color: rgb(0 0 0 / 12%);
@ -87,22 +91,21 @@ body {
box-sizing: inherit;
}
// 右侧内容区针对fixed元素有横向铺满的需求可在fixed元素上设置 [data-fixed-calc-width]
/* 右侧内容区针对fixed元素有横向铺满的需求可在fixed元素上设置 [data-fixed-calc-width] */
[data-fixed-calc-width] {
position: fixed;
right: 0;
left: 50%;
width: calc(100% - var(--g-main-sidebar-actual-width) - var(--g-sub-sidebar-actual-width));
transform: translateX(-50%) translateX(calc(var(--g-main-sidebar-actual-width) / 2)) translateX(calc(var(--g-sub-sidebar-actual-width) / 2));
}
[data-mode="mobile"] {
[data-fixed-calc-width] {
[data-mode="mobile"] & {
width: 100% !important;
transform: translateX(-50%) !important;
}
}
// textarea 字体跟随系统
/* textarea 字体跟随系统 */
textarea {
font-family: inherit;
}
@ -110,12 +113,12 @@ textarea {
/* Overrides Floating Vue */
.v-popper--theme-dropdown,
.v-popper--theme-tooltip {
--at-apply: inline-flex;
--uno: inline-flex;
}
.v-popper--theme-dropdown .v-popper__inner,
.v-popper--theme-tooltip .v-popper__inner {
--at-apply: bg-white dark-bg-stone-8 text-dark dark-text-white rounded shadow ring-1 ring-gray-200 dark-ring-gray-800 border border-solid border-stone/20 text-xs font-normal;
--uno: bg-white dark-bg-stone-8 text-dark dark-text-white rounded shadow ring-1 ring-gray-200 dark-ring-gray-800 border border-solid border-stone/20 text-xs font-normal;
box-shadow: 0 6px 30px rgb(0 0 0 / 10%);
}
@ -124,12 +127,12 @@ textarea {
.v-popper--theme-dropdown .v-popper__arrow-inner {
visibility: visible;
--at-apply: border-white dark-border-stone-8;
--uno: border-white dark-border-stone-8;
}
.v-popper--theme-tooltip .v-popper__arrow-outer,
.v-popper--theme-dropdown .v-popper__arrow-outer {
--at-apply: border-stone/20;
--uno: border-stone/20;
}
.v-popper--theme-tooltip.v-popper--shown,

View File

@ -114,7 +114,7 @@ const onPreview: UploadProps['onPreview'] = (e) => {
</ElUpload>
</template>
<style lang="scss" scoped>
<style scoped>
:deep(.el-upload.is-drag) {
display: inline-block;

View File

@ -34,7 +34,7 @@ function onScroll() {
</div>
</template>
<style lang="scss" scoped>
<style scoped>
.fixed-action-bar {
box-shadow: 0 0 1px 0 var(--g-box-shadow-color);

View File

@ -34,7 +34,7 @@ const realHeight = computed(() => {
</ElImage>
</template>
<style lang="scss" scoped>
<style scoped>
.el-image {
background-color: var(--el-fill-color);
border-radius: 5px;

View File

@ -136,7 +136,7 @@ const onSuccess: UploadProps['onSuccess'] = (res) => {
</div>
</template>
<style lang="scss" scoped>
<style scoped>
.upload-container {
line-height: initial;
}
@ -160,14 +160,16 @@ const onSuccess: UploadProps['onSuccess'] = (res) => {
transition: opacity 0.3s;
.actions {
position: absolute;
top: 50%;
left: 50%;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
@include position-center(xy);
transform: translateX(-50%) translateY(-50%);
span {
width: 50%;
@ -235,9 +237,11 @@ const onSuccess: UploadProps['onSuccess'] = (res) => {
}
.el-progress {
position: absolute;
top: 50%;
left: 50%;
z-index: 1;
@include position-center(xy);
transform: translateX(-50%) translateY(-50%);
.el-progress__text {
color: var(--el-text-color-placeholder);

View File

@ -153,7 +153,7 @@ const onSuccess: UploadProps['onSuccess'] = (res) => {
</div>
</template>
<style lang="scss" scoped>
<style scoped>
.upload-container {
line-height: initial;
}
@ -180,14 +180,16 @@ const onSuccess: UploadProps['onSuccess'] = (res) => {
transition: opacity 0.3s;
.actions {
position: absolute;
top: 50%;
left: 50%;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
@include position-center(xy);
transform: translateX(-50%) translateY(-50%);
span {
width: 50%;
@ -260,9 +262,11 @@ const onSuccess: UploadProps['onSuccess'] = (res) => {
}
.el-progress {
position: absolute;
top: 50%;
left: 50%;
z-index: 1;
@include position-center(xy);
transform: translateX(-50%) translateY(-50%);
.el-progress__text {
color: var(--el-text-color-placeholder);

View File

@ -132,7 +132,7 @@ function testAccount(account: string) {
</ElForm>
</template>
<style lang="scss" scoped>
<style scoped>
:deep(input[type="password"]::-ms-reveal) {
display: none;
}

View File

@ -113,7 +113,7 @@ function handleRegister() {
</ElForm>
</template>
<style lang="scss" scoped>
<style scoped>
:deep(input[type="password"]::-ms-reveal) {
display: none;
}

View File

@ -91,7 +91,7 @@ function handleReset() {
</ElForm>
</template>
<style lang="scss" scoped>
<style scoped>
:deep(input[type="password"]::-ms-reveal) {
display: none;
}

View File

@ -360,96 +360,96 @@ function handleCopy() {
</HSlideover>
</template>
<style lang="scss" scoped>
<style scoped>
.divider {
--at-apply: flex items-center justify-between gap-4 my-4 whitespace-nowrap text-sm font-500;
--uno: flex items-center justify-between gap-4 my-4 whitespace-nowrap text-sm font-500;
&::before,
&::after {
--at-apply: content-empty w-full h-1px bg-stone-2 dark-bg-stone-6;
--uno: content-empty w-full h-1px bg-stone-2 dark-bg-stone-6;
}
}
.menu-mode {
--at-apply: flex items-center justify-center gap-4 pb-4;
--uno: flex items-center justify-center gap-4 pb-4;
.mode {
--at-apply: relative w-16 h-12 rounded-2 ring-1 ring-stone-2 dark-ring-stone-7 cursor-pointer transition;
--uno: relative w-16 h-12 rounded-2 ring-1 ring-stone-2 dark-ring-stone-7 cursor-pointer transition;
&.active {
--at-apply: ring-ui-primary ring-2;
--uno: ring-ui-primary ring-2;
}
&::before,
&::after,
.mode-container {
--at-apply: absolute pointer-events-none;
--uno: absolute pointer-events-none;
}
&::before {
--at-apply: content-empty bg-ui-primary;
--uno: content-empty bg-ui-primary;
}
&::after {
--at-apply: content-empty bg-ui-primary/60;
--uno: content-empty bg-ui-primary/60;
}
.mode-container {
--at-apply: bg-ui-primary/20 border-width-1.5 border-dashed border-ui-primary;
--uno: bg-ui-primary/20 border-width-1.5 border-dashed border-ui-primary;
&::before {
--at-apply: content-empty absolute w-full h-full;
--uno: content-empty absolute w-full h-full;
}
}
&-side {
&::before {
--at-apply: top-2 bottom-2 left-2 w-2 rounded-tl-1 rounded-bl-1;
--uno: top-2 bottom-2 left-2 w-2 rounded-tl-1 rounded-bl-1;
}
&::after {
--at-apply: top-2 bottom-2 left-4.5 w-3;
--uno: top-2 bottom-2 left-4.5 w-3;
}
.mode-container {
--at-apply: inset-t-2 inset-r-2 inset-b-2 inset-l-8 rounded-tr-1 rounded-br-1;
--uno: inset-t-2 inset-r-2 inset-b-2 inset-l-8 rounded-tr-1 rounded-br-1;
}
}
&-head {
&::before {
--at-apply: top-2 left-2 right-2 h-2 rounded-tl-1 rounded-tr-1;
--uno: top-2 left-2 right-2 h-2 rounded-tl-1 rounded-tr-1;
}
&::after {
--at-apply: top-4.5 left-2 bottom-2 w-3 rounded-bl-1;
--uno: top-4.5 left-2 bottom-2 w-3 rounded-bl-1;
}
.mode-container {
--at-apply: inset-t-4.5 inset-r-2 inset-b-2 inset-l-5.5 rounded-br-1;
--uno: inset-t-4.5 inset-r-2 inset-b-2 inset-l-5.5 rounded-br-1;
}
}
&-single {
&::after {
--at-apply: top-2 left-2 bottom-2 w-3 rounded-tl-1 rounded-bl-1;
--uno: top-2 left-2 bottom-2 w-3 rounded-tl-1 rounded-bl-1;
}
.mode-container {
--at-apply: inset-t-2 inset-r-2 inset-b-2 inset-l-5.5 rounded-tr-1 rounded-br-1;
--uno: inset-t-2 inset-r-2 inset-b-2 inset-l-5.5 rounded-tr-1 rounded-br-1;
}
}
}
}
.setting-item {
--at-apply: flex items-center justify-between gap-4 px-4 py-2 rounded-2 transition hover-bg-stone-1 dark-hover-bg-stone-9;
--uno: flex items-center justify-between gap-4 px-4 py-2 rounded-2 transition hover-bg-stone-1 dark-hover-bg-stone-9;
.label {
--at-apply: flex items-center flex-shrink-0 gap-2 text-sm;
--uno: flex items-center flex-shrink-0 gap-2 text-sm;
i {
--at-apply: text-xl text-orange cursor-help;
--uno: text-xl text-orange cursor-help;
}
}
}

View File

@ -4,7 +4,7 @@
</div>
</template>
<style lang="scss" scoped>
<style scoped>
:deep(.breadcrumb-item) {
&:first-child {
.separator {

View File

@ -21,17 +21,17 @@ const settingsStore = useSettingsStore()
</footer>
</template>
<style lang="scss" scoped>
<style scoped>
.copyright {
--at-apply: flex items-center justify-center flex-wrap my-4 px-4 text-sm text-stone-5;
--uno: flex items-center justify-center flex-wrap my-4 px-4 text-sm text-stone-5;
span,
a {
--at-apply: px-1;
--uno: px-1;
}
a {
--at-apply: text-center no-underline text-stone-5 hover-text-dark dark-hover-text-light transition;
--uno: text-center no-underline text-stone-5 hover-text-dark dark-hover-text-light transition;
}
}
</style>

View File

@ -61,7 +61,7 @@ function handlerMouserScroll(event: WheelEvent) {
</Transition>
</template>
<style lang="scss" scoped>
<style scoped>
header {
position: fixed;
top: 0;
@ -115,10 +115,10 @@ header {
overflow-x: auto;
mask-image: linear-gradient(to right, transparent, #000 20px, #000 calc(100% - 20px), transparent);
// firefox
/* firefox隐藏滚动条 */
scrollbar-width: none;
// chrome
/* chrome隐藏滚动条 */
&::-webkit-scrollbar {
display: none;
}
@ -151,7 +151,7 @@ header {
}
}
//
/* 头部动画 */
.header-enter-active,
.header-leave-active {
transition: transform 0.3s;

View File

@ -46,7 +46,7 @@ const { switchTo } = useMenu()
</Transition>
</template>
<style lang="scss" scoped>
<style scoped>
.main-sidebar-container {
position: relative;
z-index: 1;
@ -69,10 +69,10 @@ const { switchTo } = useMenu()
overflow: hidden auto;
overscroll-behavior: contain;
// firefox
/* firefox隐藏滚动条 */
scrollbar-width: none;
// chrome
/* chrome隐藏滚动条 */
&::-webkit-scrollbar {
display: none;
}
@ -100,7 +100,7 @@ const { switchTo } = useMenu()
}
}
//
/* 主侧边栏动画 */
.main-sidebar-enter-active,
.main-sidebar-leave-active {
transition: 0.3s;

View File

@ -97,7 +97,7 @@ onMounted(() => {
</div>
</template>
<style lang="scss" scoped>
<style scoped>
.sub-sidebar-container {
position: absolute;
top: 0;
@ -140,10 +140,10 @@ onMounted(() => {
overflow: hidden auto;
overscroll-behavior: contain;
// firefox
/* firefox隐藏滚动条 */
scrollbar-width: none;
// chrome
/* chrome隐藏滚动条 */
&::-webkit-scrollbar {
display: none;
}
@ -166,7 +166,7 @@ onMounted(() => {
}
}
//
/* 次侧边栏动画 */
.sub-sidebar-enter-active {
transition: 0.2s;
}

View File

@ -198,48 +198,44 @@ onUnmounted(() => {
</div>
</template>
<style lang="scss">
<style>
.tabbar-contextmenu {
z-index: 1000;
--uno: fixed ring-1 ring-stone-2 dark-ring-stone-7 shadow-2xl;
.mx-context-menu {
--at-apply: fixed ring-1 ring-stone-2 dark-ring-stone-7 shadow-2xl;
background-color: var(--g-container-bg);
background-color: var(--g-container-bg);
.mx-context-menu-items .mx-context-menu-item {
--uno: transition-background-color;
.mx-context-menu-items .mx-context-menu-item {
--at-apply: transition-background-color;
&:not(.disabled):hover {
--at-apply: cursor-pointer bg-stone-1 dark-bg-stone-9;
}
span {
color: initial;
}
.icon {
color: initial;
}
&.disabled span,
&.disabled .icon {
opacity: 0.25;
}
&:not(.disabled):hover {
--uno: cursor-pointer bg-stone-1 dark-bg-stone-9;
}
.mx-context-menu-item-sperator {
background-color: var(--g-container-bg);
span {
color: initial;
}
&::after {
--at-apply: bg-stone-2 dark-bg-stone-7;
}
.icon {
color: initial;
}
&.disabled span,
&.disabled .icon {
opacity: 0.25;
}
}
.mx-context-menu-item-sperator {
background-color: var(--g-container-bg);
&::after {
--uno: bg-stone-2 dark-bg-stone-7;
}
}
}
</style>
<style lang="scss" scoped>
<style scoped>
.tabbar-container {
position: relative;
height: var(--g-tabbar-height);
@ -253,10 +249,10 @@ onUnmounted(() => {
overflow-y: hidden;
white-space: nowrap;
// firefox
/* firefox隐藏滚动条 */
scrollbar-width: none;
// chrome
/* chrome隐藏滚动条 */
&::-webkit-scrollbar {
display: none;
}
@ -410,14 +406,14 @@ onUnmounted(() => {
transform: translateY(-50%);
&:hover {
--at-apply: ring-1 ring-stone-3 dark-ring-stone-7;
--uno: ring-1 ring-stone-3 dark-ring-stone-7;
background-color: var(--g-bg);
}
}
.hotkey-number {
--at-apply: ring-1 ring-stone-3 dark-ring-stone-7;
--uno: ring-1 ring-stone-3 dark-ring-stone-7;
position: absolute;
top: 50%;
@ -440,7 +436,7 @@ onUnmounted(() => {
}
}
//
/* 标签栏动画 */
.tabs {
.tabbar-move,
.tabbar-enter-active,

View File

@ -45,8 +45,8 @@ function pathCompile(path: string) {
</Breadcrumb>
</template>
<style lang="scss" scoped>
//
<style scoped>
/* 面包屑动画 */
.breadcrumb-enter-active {
transition: transform 0.3s, opacity 0.3s;
}

View File

@ -21,7 +21,7 @@ const settingsStore = useSettingsStore()
</div>
</template>
<style lang="scss" scoped>
<style scoped>
.toolbar-container {
height: var(--g-toolbar-height);
background-color: var(--g-container-bg);

View File

@ -53,7 +53,7 @@ watch(scrollTop, (val, oldVal) => {
</div>
</template>
<style lang="scss" scoped>
<style scoped>
.topbar-container {
position: absolute;
top: 0;

View File

@ -46,7 +46,7 @@ function open() {
</div>
</template>
<style lang="scss" scoped>
<style scoped>
.slide-right-enter-active {
transition: 0.2s;
}

View File

@ -109,7 +109,7 @@ const enableAppSetting = import.meta.env.VITE_APP_SETTING === 'true'
</div>
</template>
<style lang="scss" scoped>
<style scoped>
[data-mode="mobile"] {
.sidebar-container {
transform: translateX(calc((var(--g-main-sidebar-width) + var(--g-sub-sidebar-width)) * -1));
@ -240,7 +240,7 @@ header:not(.header-leave-active) + .wrapper {
}
.app-setting {
--at-apply: text-white dark-text-dark bg-ui-primary;
--uno: text-white dark-text-dark bg-ui-primary;
position: fixed;
top: calc(50% + 250px);
@ -271,7 +271,7 @@ header:not(.header-leave-active) + .wrapper {
}
}
//
/* 主内容区动画 */
.slide-right-enter-active {
transition: 0.2s;
}

View File

@ -26,7 +26,7 @@ import icons from '@/iconify/index.json'
import 'virtual:uno.css'
// 全局样式
import '@/assets/styles/globals.scss'
import '@/assets/styles/globals.css'
const app = createApp(App)
app.use(FloatingVue, {

View File

@ -1,7 +1,7 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import { useNProgress } from '@vueuse/integrations/useNProgress'
import '@/assets/styles/nprogress.scss'
import '@/assets/styles/nprogress.css'
// 路由相关数据
import { asyncRoutes, asyncRoutesByFilesystem, constantRoutes, constantRoutesByFilesystem } from './routes'

View File

@ -165,30 +165,30 @@ function open(url: string) {
</div>
</template>
<style lang="scss" scoped>
<style scoped>
.text-emphasis {
text-emphasis-style: "❤";
}
.ecology {
--at-apply: flex-1 m-0;
--uno: flex-1 m-0;
:deep(.title-container) {
--at-apply: flex items-center justify-between flex-wrap gap-4;
--uno: flex items-center justify-between flex-wrap gap-4;
.title-info {
--at-apply: flex items-center gap-4;
--uno: flex items-center gap-4;
img {
--at-apply: block w-12 h-12;
--uno: block w-12 h-12;
}
h1 {
--at-apply: m-0 text-2xl;
--uno: m-0 text-2xl;
}
h2 {
--at-apply: m-0 text-base text-stone-5 font-normal;
--uno: m-0 text-base text-stone-5 font-normal;
}
}
}

View File

@ -61,7 +61,7 @@ const formRef = ref()
<Copyright />
</template>
<style lang="scss" scoped>
<style scoped>
.bg-banner {
position: fixed;
z-index: 0;
@ -124,9 +124,10 @@ const formRef = ref()
background-color: var(--g-bg);
.banner {
position: absolute;
top: 50%;
width: 100%;
@include position-center(y);
transform: translateY(-50%);
}
}