1panel
This commit is contained in:
272
frontend/src/style/mixins.scss
Normal file
272
frontend/src/style/mixins.scss
Normal file
@@ -0,0 +1,272 @@
|
||||
// SCSS Mixins 混合器
|
||||
|
||||
// 響應式斷點混合器
|
||||
@mixin respond-to($breakpoint) {
|
||||
@if $breakpoint == xs {
|
||||
@media (max-width: #{$breakpoint-xs - 1px}) { @content; }
|
||||
}
|
||||
@if $breakpoint == sm {
|
||||
@media (max-width: #{$breakpoint-sm - 1px}) { @content; }
|
||||
}
|
||||
@if $breakpoint == md {
|
||||
@media (max-width: #{$breakpoint-md - 1px}) { @content; }
|
||||
}
|
||||
@if $breakpoint == lg {
|
||||
@media (max-width: #{$breakpoint-lg - 1px}) { @content; }
|
||||
}
|
||||
@if $breakpoint == xl {
|
||||
@media (min-width: $breakpoint-xl) { @content; }
|
||||
}
|
||||
}
|
||||
|
||||
// 最小寬度斷點
|
||||
@mixin respond-above($breakpoint) {
|
||||
@if $breakpoint == xs {
|
||||
@media (min-width: $breakpoint-xs) { @content; }
|
||||
}
|
||||
@if $breakpoint == sm {
|
||||
@media (min-width: $breakpoint-sm) { @content; }
|
||||
}
|
||||
@if $breakpoint == md {
|
||||
@media (min-width: $breakpoint-md) { @content; }
|
||||
}
|
||||
@if $breakpoint == lg {
|
||||
@media (min-width: $breakpoint-lg) { @content; }
|
||||
}
|
||||
}
|
||||
|
||||
// Flexbox 輔助混合器
|
||||
@mixin flex-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@mixin flex-between {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@mixin flex-start {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
@mixin flex-end {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
@mixin flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@mixin flex-column-center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
// 文字省略號
|
||||
@mixin text-ellipsis {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@mixin multi-line-ellipsis($lines: 2) {
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: $lines;
|
||||
-webkit-box-orient: vertical;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// 清除浮動
|
||||
@mixin clearfix {
|
||||
&::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
// 隱藏滾動條
|
||||
@mixin hide-scrollbar {
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none; /* IE 10+ */
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none; /* Chrome Safari */
|
||||
}
|
||||
}
|
||||
|
||||
// 自定義滾動條
|
||||
@mixin custom-scrollbar($thumb-color: $border-color, $track-color: transparent, $size: 6px) {
|
||||
&::-webkit-scrollbar {
|
||||
width: $size;
|
||||
height: $size;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: $track-color;
|
||||
border-radius: $size / 2;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: $thumb-color;
|
||||
border-radius: $size / 2;
|
||||
|
||||
&:hover {
|
||||
background: darken($thumb-color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 絕對定位置中
|
||||
@mixin absolute-center {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@mixin absolute-center-x {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@mixin absolute-center-y {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
// 固定比例容器
|
||||
@mixin aspect-ratio($width: 16, $height: 9) {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding-top: ($height / $width) * 100%;
|
||||
}
|
||||
|
||||
> * {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 過渡動畫
|
||||
@mixin transition($property: all, $duration: $transition-duration-base, $timing-function: ease-in-out) {
|
||||
transition: $property $duration $timing-function;
|
||||
}
|
||||
|
||||
@mixin hover-lift {
|
||||
transition: transform $transition-duration-fast ease-out, box-shadow $transition-duration-fast ease-out;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: $box-shadow-dark;
|
||||
}
|
||||
}
|
||||
|
||||
// 按鈕樣式混合器
|
||||
@mixin button-variant($color, $background, $border: $background) {
|
||||
color: $color;
|
||||
background-color: $background;
|
||||
border-color: $border;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $color;
|
||||
background-color: lighten($background, 5%);
|
||||
border-color: lighten($border, 5%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: $color;
|
||||
background-color: darken($background, 5%);
|
||||
border-color: darken($border, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
// 狀態標籤樣式
|
||||
@mixin status-badge($color) {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
font-size: $font-size-small;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
background-color: $color;
|
||||
border-radius: $border-radius-base;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
// 卡片樣式
|
||||
@mixin card-style($padding: $spacing-lg, $border-radius: $border-radius-base) {
|
||||
background: $bg-color;
|
||||
border: 1px solid $border-color-lighter;
|
||||
border-radius: $border-radius;
|
||||
box-shadow: $box-shadow-light;
|
||||
padding: $padding;
|
||||
transition: box-shadow $transition-duration-base;
|
||||
|
||||
&:hover {
|
||||
box-shadow: $box-shadow-dark;
|
||||
}
|
||||
}
|
||||
|
||||
// 表單輸入樣式
|
||||
@mixin form-input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
font-size: $font-size-base;
|
||||
line-height: $line-height-base;
|
||||
color: $text-color-primary;
|
||||
background-color: $bg-color;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: $border-radius-base;
|
||||
transition: border-color $transition-duration-fast, box-shadow $transition-duration-fast;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: $primary-color;
|
||||
box-shadow: 0 0 0 2px rgba($primary-color, 0.2);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: $bg-color-light;
|
||||
color: $text-color-placeholder;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
// Loading 動畫
|
||||
@mixin loading-spinner($size: 20px, $color: $primary-color) {
|
||||
width: $size;
|
||||
height: $size;
|
||||
border: 2px solid transparent;
|
||||
border-top-color: $color;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
Reference in New Issue
Block a user