// 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); } }