| @use "config" as *; |
| @use "functions" as *; |
| @use "mixins/border-radius" as *; |
| @use "mixins/box-shadow" as *; |
| @use "mixins/tokens" as *; |
| @use "mixins/transition" as *; |
| |
| // stylelint-disable scss/dollar-variable-default, custom-property-no-missing-var-function |
| $menu-tokens: () !default; |
| |
| // scss-docs-start menu-tokens |
| $menu-tokens: defaults( |
| ( |
| --menu-zindex: var(--z-menu), |
| --menu-gap: .125rem, |
| --menu-min-width: 10rem, |
| --menu-padding-x: .25rem, |
| --menu-padding-y: .25rem, |
| --menu-spacer: .125rem, |
| --menu-font-size: var(--font-size-sm), |
| --menu-color: var(--fg-body), |
| --menu-bg: var(--bg-body), |
| // --menu-border-color: var(--border-color-translucent), |
| // --menu-border-radius: var(--radius-7), |
| // --menu-border-width: var(--border-width), |
| --menu-box-shadow: var(--box-shadow-lg), |
| // --menu-max-height: none, |
| --menu-divider-bg: var(--border-color-translucent), |
| --menu-divider-margin-y: .125rem, |
| --menu-divider-margin-x: .25rem, |
| --menu-item-color: var(--menu-color, var(--fg-body)), |
| --menu-item-hover-color: var(--menu-color, var(--fg-body)), |
| --menu-item-hover-bg: var(--bg-1), |
| --menu-item-active-color: var(--primary-contrast), |
| --menu-item-active-bg: var(--primary-bg), |
| --menu-item-disabled-color: var(--fg-3), |
| --menu-item-gap: .5rem, |
| --menu-item-padding-x: .75rem, |
| --menu-item-padding-y: .25rem, |
| --menu-item-border-radius: var(--radius-5), |
| --menu-icon-size: 1rem, |
| --menu-description-font-size: var(--font-size-xs), |
| --menu-check-color: currentcolor, |
| --menu-header-color: var(--fg-3), |
| --menu-header-padding-x: .75rem, |
| --menu-header-padding-y: .25rem, |
| --menu-transition-property: "opacity, transform, display", |
| --menu-transition-duration: .15s, |
| --menu-transition-timing: var(--transition-timing-overlay), |
| ), |
| $menu-tokens |
| ); |
| // scss-docs-end menu-tokens |
| |
| // stylelint-enable custom-property-no-missing-var-function, scss/dollar-variable-default |
| |
| @layer components { |
| .menu { |
| @include tokens($menu-tokens); |
| |
| position: absolute; |
| z-index: var(--menu-zindex); |
| display: none; |
| flex-direction: column; |
| gap: var(--menu-gap); |
| min-width: var(--menu-min-width); |
| max-height: var(--menu-max-height, none); |
| padding: var(--menu-padding-y) var(--menu-padding-x); |
| margin: 0; |
| overflow-y: var(--menu-overflow-y, initial); |
| overscroll-behavior: contain; |
| font-size: var(--menu-font-size); |
| color: var(--menu-color); |
| text-align: start; |
| list-style-type: ""; |
| background-color: var(--menu-bg); |
| background-clip: padding-box; |
| border: var(--menu-border-width, var(--border-width)) solid var(--menu-border-color, var(--border-color-translucent)); |
| @include border-radius(var(--menu-border-radius, var(--radius-7))); |
| @include box-shadow(var(--menu-box-shadow)); |
| opacity: 0; |
| transform: scale(.95); |
| transform-origin: top start; |
| |
| &[data-bs-placement^="top"] { |
| transform-origin: bottom start; |
| } |
| |
| &[data-bs-placement="bottom-end"] { |
| transform-origin: top end; |
| } |
| |
| &[data-bs-placement="top-end"] { |
| transform-origin: bottom end; |
| } |
| |
| &[data-bs-placement^="left"] { |
| transform-origin: top end; |
| } |
| |
| // `display` transitions discretely so the menu stays laid out until the |
| // fade-out finishes. Keep it in --menu-transition-property when you |
| // override the list. |
| @include transition-props( |
| var(--menu-transition-property), |
| var(--menu-transition-duration), |
| var(--menu-transition-timing), |
| allow-discrete |
| ); |
| |
| &.show { |
| display: flex; |
| opacity: 1; |
| transform: none; |
| } |
| } |
| |
| @starting-style { |
| .menu.show { |
| opacity: 0; |
| transform: scale(.95); |
| } |
| } |
| |
| .menu-scrollable { |
| --menu-max-height: 80dvh; |
| --menu-overflow-y: auto; |
| } |
| |
| .menu-translucent { |
| --menu-item-hover-bg-light: color-mix(in oklch, var(--bg-1) 90%, transparent); |
| --menu-item-hover-bg-dark: color-mix(in oklch, var(--bg-1) 80%, transparent); |
| |
| --menu-item-active-bg-light: color-mix(in oklch, var(--primary-bg) 80%, transparent); |
| --menu-item-active-bg-dark: color-mix(in oklch, var(--primary-bg) 70%, transparent); |
| |
| --menu-item-active-bg: light-dark(var(--menu-item-active-bg-light), var(--menu-item-active-bg-dark)); |
| --menu-item-hover-bg: light-dark(var(--menu-item-hover-bg-light), var(--menu-item-hover-bg-dark)); |
| |
| background-color: color-mix(in oklch, var(--menu-bg) 80%, transparent); |
| backdrop-filter: blur(5px) saturate(180%); |
| } |
| |
| .menu-divider { |
| height: 0; |
| margin: var(--menu-divider-margin-y) var(--menu-divider-margin-x); |
| overflow: hidden; |
| border-block-start: 1px solid var(--menu-divider-bg); |
| opacity: 1; |
| } |
| |
| .menu-item { |
| display: flex; |
| gap: var(--menu-item-gap); |
| align-items: center; |
| width: 100%; |
| padding: var(--menu-item-padding-y) var(--menu-item-padding-x); |
| font-weight: var(--menu-item-font-weight, var(--font-weight-normal)); |
| color: var(--theme-fg, var(--menu-item-color)); |
| text-align: inherit; |
| text-decoration: none; |
| white-space: nowrap; |
| cursor: pointer; |
| background-color: transparent; |
| border: 0; |
| outline: 0; |
| @include border-radius(var(--menu-item-border-radius, 0)); |
| |
| &:hover, |
| &:focus { |
| color: var(--theme-fg-emphasis, var(--menu-item-hover-color)); |
| background-color: var(--theme-bg-subtle, var(--menu-item-hover-bg)); |
| // @include gradient-bg(var(--theme-bg-subtle, var(--menu-item-hover-bg))); |
| } |
| |
| &.active, |
| &:active { |
| color: var(--theme-contrast, var(--menu-item-active-color)); |
| background-color: var(--theme-bg, var(--menu-item-active-bg)); |
| // @include gradient-bg(var(--theme-bg, var(--menu-item-active-bg))); |
| |
| .menu-item-icon { |
| color: inherit !important; // stylelint-disable-line declaration-no-important |
| } |
| } |
| |
| &.selected { |
| font-weight: var(--font-weight-semibold); |
| } |
| |
| &.disabled, |
| &:disabled { |
| color: var(--menu-item-disabled-color); |
| pointer-events: none; |
| background-color: transparent; |
| // stylelint-disable-next-line scss/at-function-named-arguments |
| background-image: if(sass($enable-gradients): none; else: null); |
| } |
| } |
| |
| .menu-item-icon { |
| flex-shrink: 0; |
| align-self: flex-start; |
| width: var(--menu-icon-size); |
| height: auto; |
| margin-top: .125rem; |
| } |
| |
| .menu-item-content { |
| display: flex; |
| flex: 1; |
| flex-direction: column; |
| min-width: fit-content; |
| } |
| |
| .menu-item-description { |
| font-size: var(--menu-description-font-size); |
| font-weight: var(--font-weight-normal); |
| color: color-mix(in oklch, currentcolor 65%, transparent); |
| } |
| |
| .menu-item-check { |
| flex-shrink: 0; |
| align-self: flex-start; |
| margin-block-start: .125rem; |
| margin-inline-start: auto; |
| color: var(--menu-check-color); |
| visibility: hidden; |
| |
| .selected > & { |
| visibility: visible; |
| } |
| } |
| |
| .menu-header { |
| display: block; |
| padding: var(--menu-header-padding-y) var(--menu-header-padding-x); |
| margin-bottom: 0; |
| font-size: var(--font-size-sm); |
| color: var(--menu-header-color); |
| white-space: nowrap; |
| } |
| |
| .menu-text { |
| display: block; |
| padding: var(--menu-item-padding-y) var(--menu-item-padding-x); |
| color: var(--fg-2); |
| } |
| |
| // scss-docs-start submenu |
| .submenu { |
| position: relative; |
| |
| > .menu-item { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| } |
| |
| > .menu-item::after { |
| display: inline-block; |
| flex-shrink: 0; |
| width: .375em; |
| height: .375em; |
| margin-inline-start: auto; |
| content: ""; |
| border-color: currentcolor; |
| border-style: solid; |
| border-width: 0 .125em .125em 0; |
| transform: rotate(-45deg); |
| |
| [dir="rtl"] & { |
| transform: rotate(135deg); |
| } |
| } |
| |
| > .menu { |
| top: 0; |
| margin-top: calc(-1 * var(--menu-padding-y)); |
| } |
| |
| &:hover > .menu-item, |
| &:focus-within > .menu-item { |
| color: var(--menu-item-hover-color); |
| background-color: var(--menu-item-hover-bg); |
| } |
| |
| &.show > .menu-item { |
| color: var(--menu-item-hover-color); |
| background-color: var(--menu-item-hover-bg); |
| } |
| } |
| // scss-docs-end submenu |
| } |