diff --git a/src/styles/_mixins.scss b/src/styles/_mixins.scss index aaacf7e225..578bc0b6eb 100644 --- a/src/styles/_mixins.scss +++ b/src/styles/_mixins.scss @@ -10,3 +10,11 @@ #{$property}: max($max-value, $default); } } + +/** + * Helper mixin to add properties using css variables with fallback values. + */ +@mixin var($property, $variable, $default, $important: false) { + #{$property}: $default if($important, !important, null); + #{$property}: var($variable) if($important, !important, null); +} diff --git a/src/styles/librarybrowser.scss b/src/styles/librarybrowser.scss index 1a82a2de76..2448c4adae 100644 --- a/src/styles/librarybrowser.scss +++ b/src/styles/librarybrowser.scss @@ -1017,16 +1017,6 @@ div.itemDetailGalleryLink.defaultCardBackground { } } -.emby-button.detailFloatingButton { - font-size: 1.4em; - margin-right: 0.5em !important; - color: rgba(255, 255, 255, 0.76); -} - -.emby-button.detailFloatingButton .material-icons { - font-size: 3.5em; -} - @media all and (max-width: 62.5em) { .parentName { margin-bottom: 0; diff --git a/src/themes/dark/theme.scss b/src/themes/dark/theme.scss index 64e75a6b20..6a7d641f52 100644 --- a/src/themes/dark/theme.scss +++ b/src/themes/dark/theme.scss @@ -1,3 +1,39 @@ +@use '../../styles/mixins' as *; + +// Theme options +$dark: true !default; + +// Color palette +$common-white: #fff !default; +$background-default: #101010 !default; +$background-paper: #202020 !default; +$primary-main: #00a4dc !default; +$primary-dark: #00729a !default; +$primary-light: #33b6e3 !default; +$primary-hover: rgba(0, 164, 220, 0.2) !default; +$primary-contrastText: rgba(0, 0, 0, 0.87) !default; +$error-main: #c62828 !default; +$error-dark: #8a1c1c !default; +$error-light: #d15353 !default; +$error-contrastText: #fff !default; +$text-primary: #fff !default; +$text-secondary: rgba(255, 255, 255, 0.7) !default; +$action-focus: rgba(255, 255, 255, 0.12) !default; +$action-hover: rgba(255, 255, 255, 0.08) !default; +$divider: rgba(255, 255, 255, 0.12) !default; + +// Components +$appBar-defaultBg: #202020 !default; +// NOTE: This color is not part of the MUI theme +$appBar-transparentBg: rgba(0, 0, 0, 0.4) !default; +$filledInput-bg: rgba(255, 255, 255, 0.09) !default; +$alert-infoFilledBg: #0288d1 !default; +$alert-infoFilledColor: #fff !default; +$button-inheritContainedBg: #424242 !default; +$button-inheritContainedHoverBg: #616161 !default; +$snackbarContent-bg: #303030 !default; +$snackbarContent-color: rgba(255, 255, 255, 0.87) !default; + * { scrollbar-width: thin; scrollbar-color: #3b3b3b #202020; @@ -5,40 +41,38 @@ .skinHeader, html { - color: #ddd; - color: rgba(255, 255, 255, 0.8); + @include var(color, --jf-palette-text-secondary, $text-secondary); } .wizardStartForm, .ui-corner-all, .ui-shadow { - background-color: #101010; + @include var(background-color, --jf-palette-background-default, $background-default); } .emby-collapsible-button { - border-color: #383838; - border-color: rgba(255, 255, 255, 0.135); + @include var(border-color, --jf-palette-divider, $divider); } .skinHeader-withBackground { - background-color: #202020; + @include var(background-color, --jf-palette-AppBar-defaultBg, $appBar-defaultBg); } .skinHeader.semiTransparent { + @include var(background-color, --jf-palette-AppBar-transparentBg, $appBar-transparentBg); backdrop-filter: none !important; - background-color: rgba(0, 0, 0, 0.4); -} -.layout-tv .skinHeader.semiTransparent { - background: none; + .layout-tv & { + background: none; + } } .pageTitleWithDefaultLogo { - background-image: url(@jellyfin/ux-web/banner-light.png); -} + background-image: if($dark, url(@jellyfin/ux-web/banner-light.png), url(@jellyfin/ux-web/banner-dark.png)); -.layout-tv .pageTitleWithDefaultLogo { - background-image: url(@jellyfin/ux-web/icon-transparent.png); + .layout-tv & { + background-image: url(@jellyfin/ux-web/icon-transparent.png); + } } .backgroundContainer, @@ -46,53 +80,54 @@ html { .nowPlayingPlaylist, .nowPlayingContextMenu, html { - background-color: #101010; + @include var(background-color, --jf-palette-background-default, $background-default); } .backgroundContainer.withBackdrop { - background-color: rgba(0, 0, 0, 0.86); + opacity: 0.86; } @media (hover: hover) and (pointer: fine) { .paper-icon-button-light:hover:not(:disabled) { - color: #00a4dc; - background-color: rgba(0, 164, 220, 0.2); + @include var(color, --jf-palette-primary-main, $primary-main); + background-color: $primary-hover; + background-color: rgba(var(--jf-palette-primary-mainChannel) / var(--jf-palette-action-selectedOpacity)); } } .paper-icon-button-light:active:not(:disabled) { - color: #00a4dc; - background-color: rgba(0, 164, 220, 0.2); + @include var(color, --jf-palette-primary-main, $primary-main); + background-color: $primary-hover; + background-color: rgba(var(--jf-palette-primary-mainChannel) / var(--jf-palette-action-selectedOpacity)); } .paper-icon-button-light.show-focus:focus { - color: #00a4dc; + @include var(color, --jf-palette-primary-main, $primary-main); } .fab, .raised { - background: #303030; - color: rgba(255, 255, 255, 0.87); -} + @include var(background, --jf-palette-Button-inheritContainedBg, $button-inheritContainedBg); + @include var(color, --jf-palette-text-secondary, $text-secondary); -.fab:focus, -.raised:focus { - background: #383838; + &:focus, + &:hover { + @include var(background, --jf-palette-Button-inheritContainedHoverBg, $button-inheritContainedHoverBg); + } } .button-submit { - background: #00a4dc; - color: #fff; -} + @include var(background, --jf-palette-primary-main, $primary-main); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText); -.button-submit:focus { - background: #0cb0e8; - color: #fff; + &:focus { + @include var(background, --jf-palette-primary-light, $primary-light); + } } .button-delete { - background: #cb272a; - color: #fff; + @include var(background, --jf-palette-error-main, $error-main); + @include var(color, --jf-palette-error-contrastText, $error-contrastText); } .checkboxLabel { @@ -104,14 +139,13 @@ html { .inputLabelUnfocused, .paperListLabel, .textareaLabelUnfocused { - color: #bbb; - color: rgba(255, 255, 255, 0.7); + @include var(color, --jf-palette-text-secondary, $text-secondary); } .inputLabelFocused, .selectLabelFocused, .textareaLabelFocused { - color: #00a4dc; + @include var(color, --jf-palette-primary-main, $primary-main); } .checkboxOutline { @@ -123,7 +157,7 @@ html { .formDialogHeader:not(.formDialogHeader-clear), .paperList, .visualCardBox { - background-color: #202020; + @include var(background-color, --jf-palette-background-paper, $background-paper); } .layout-tv .formDialogFooter:not(.formDialogFooter-clear) { @@ -157,13 +191,11 @@ html { .nowPlayingBarSecondaryText, .programSecondaryTitle, .secondaryText { - color: #999; - color: rgba(255, 255, 255, 0.5); + @include var(color, --jf-palette-text-secondary, $text-secondary); } .actionsheetDivider { - background: #444; - background: rgba(255, 255, 255, 0.14); + @include var(background, --jf-palette-divider, $divider); } .cardFooter-vibrant .cardText-secondary { @@ -172,53 +204,48 @@ html { } .toast { - background: #303030; - color: #fff; - color: rgba(255, 255, 255, 0.87); + @include var(background, --jf-palette-SnackbarContent-bg, $snackbarContent-bg); + @include var(color, --jf-palette-SnackbarContent-color, $snackbarContent-color); } .appfooter, .playlistSectionButton { - background: #202020; - color: #ccc; - color: rgba(255, 255, 255, 0.78); + @include var(background, --jf-palette-background-paper, $background-paper); + @include var(color, --jf-palette-text-secondary, $text-secondary); } .itemSelectionPanel { - border: 1px solid #00a4dc; + @include var(border-color, --jf-palette-primary-main, $primary-main); + border-width: 1px; + border-style: solid; } .selectionCommandsPanel { - background: #00a4dc; - color: #fff; + @include var(background, --jf-palette-primary-main, $primary-main); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText); } .upNextDialog-countdownText { - color: #00a4dc; + @include var(color, --jf-palette-primary-main, $primary-main); } .alphaPickerButton { - color: #999; - color: rgba(255, 255, 255, 0.5); + @include var(color, --jf-palette-text-secondary, $text-secondary); background-color: transparent; -} -.alphaPickerButton-selected { - color: #fff; -} + &-selected { + @include var(color, --jf-palette-text-primary, $text-primary); + } -.alphaPickerButton-tv:focus { - background-color: #00a4dc; - color: #fff !important; -} - -.detailTableBodyRow-shaded:nth-child(even) { - background: #1c1c1c; - background: rgba(30, 30, 30, 0.9); + &-tv:focus { + @include var(background-color, --jf-palette-primary-main, $primary-main); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText); + } } .detailRibbon { background: rgba(32, 32, 32, 0.8); + background: rgba(var(--jf-palette-background-paperChannel) / 0.8); } .layout-tv .detailRibbon { @@ -227,136 +254,134 @@ html { .noBackdropTransparency .detailPagePrimaryContainer, .noBackdropTransparency .detailPageSecondaryContainer { - background-color: #101010; + @include var(background-color, --jf-palette-background-default, $background-default); } .listItem-border { - border-color: rgba(34, 34, 34, 0.9) !important; + @include var(border-color, --jf-palette-divider, $divider); } .listItem:focus { - background: #333; + @include var(background-color, --jf-palette-action-focus, $action-focus); } .listItem:hover { - background: #242424; + @include var(background-color, --jf-palette-action-hover, $action-hover); } .progressring-spiner { - border-color: #00a4dc; + @include var(border-color, --jf-palette-primary-main, $primary-main); } .button-flat:hover { - color: #00a4dc; + @include var(color, --jf-palette-primary-main, $primary-main); } .button-link { - color: #00a4dc; + @include var(color, --jf-palette-primary-main, $primary-main); } .mediaInfoText { - color: #ddd; - background: rgba(170, 170, 190, 0.2); + @include var(border-color, --jf-palette-text-secondary, $text-secondary); + border-style: solid; + border-width: 1px; } .emby-input, .emby-textarea { + @include var(background, --jf-palette-FilledInput-bg, $filledInput-bg); + @include var(border-color, --jf-palette-FilledInput-bg, $filledInput-bg); color: inherit; - background: #292929; - border: 0.16em solid #292929; + border-width: 0.16em; + border-style: solid; border-radius: 0.2em; -} -.emby-input:focus, -.emby-textarea:focus { - border-color: #00a4dc; + &:focus { + @include var(border-color, --jf-palette-primary-main, $primary-main); + } } .emby-select-withcolor { + @include var(background, --jf-palette-FilledInput-bg, $filledInput-bg); + @include var(border-color, --jf-palette-FilledInput-bg, $filledInput-bg); color: inherit; - background: #292929; - border: 0.07em solid #292929; + border-width: 0.07em; + border-style: solid; } .emby-select-withcolor > option { + @include var(background, --jf-palette-background-paper, $background-paper); color: inherit; - background: #222; } .emby-select-withcolor:focus { - border-color: #00a4dc !important; + @include var(border-color, --jf-palette-primary-main, $primary-main, true); } .emby-select-tv-withcolor:focus { - background-color: #00a4dc !important; - color: #fff !important; + @include var(background-color, --jf-palette-primary-main, $primary-main, true); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText, true); } .emby-checkbox:checked + span + .checkboxOutline { - border-color: #00a4dc; + @include var(border-color, --jf-palette-primary-main, $primary-main); } .emby-checkbox:focus + span + .checkboxOutline { - border-color: #fff; + @include var(border-color, --jf-palette-common-white, $common-white); } .emby-checkbox:checked + span + .checkboxOutline, .itemProgressBarForeground { - background-color: #00a4dc; + @include var(background-color, --jf-palette-primary-main, $primary-main); } .emby-checkbox:focus:not(:checked) + span + .checkboxOutline { - border-color: #00a4dc; + @include var(border-color, --jf-palette-primary-main, $primary-main); } .itemProgressBarForeground-recording { - background-color: #cb272a; + @include var(background-color, --jf-palette-error-light, $error-light); } .countIndicator, .fullSyncIndicator, .mediaSourceIndicator, .playedIndicator { - background: #00a4dc; -} - -.fullSyncIndicator { - color: #fff; + @include var(background, --jf-palette-primary-main, $primary-main); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText); } .mainDrawer, .drawer-open { - background-color: #101010; + @include var(background-color, --jf-palette-background-default, $background-default); } .navMenuOption:hover { - background: #252528; + @include var(background, --jf-palette-action-hover, $action-hover); } .navMenuOption-selected { - background: #00a4dc !important; - color: #fff; + @include var(background, --jf-palette-primary-main, $primary-main, true); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText); } .emby-button.show-focus:focus { - background: #00a4dc; - color: #fff; + @include var(background, --jf-palette-primary-main, $primary-main); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText); } .emby-tab-button { - color: #999; + @include var(color, --jf-palette-text-secondary, $text-secondary); } .emby-tab-button-active { - color: #fff; -} - -.emby-tab-button.show-focus:focus { - color: #00a4dc; + @include var(color, --jf-palette-text-primary, $text-primary); } +.emby-tab-button.show-focus:focus, .emby-tab-button:hover { - color: #00a4dc; + @include var(color, --jf-palette-primary-main, $primary-main); } .channelPrograms, @@ -387,8 +412,8 @@ html { .guide-channelHeaderCell:focus, .programCell:focus { - background-color: #00a4dc !important; - color: #fff !important; + @include var(background-color, --jf-palette-primary-main, $primary-main, true); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText, true); } .guide-programTextIcon { @@ -400,48 +425,35 @@ html { color: inherit; } -.guide-date-tab-button { - color: #555; - color: rgba(255, 255, 255, 0.3); -} - .guide-date-tab-button.emby-tab-button-active, .guide-date-tab-button:focus { - color: #00a4dc; + @include var(color, --jf-palette-primary-main, $primary-main); } .guide-date-tab-button.show-focus:focus { - background-color: #00a4dc; - color: #fff; + @include var(background-color, --jf-palette-primary-main, $primary-main); + @include var(color, --jf-palette-primary-contrastText, $primary-contrastText); } .infoBanner { - color: #ddd; - background: #111; + @include var(background, --jf-palette-Alert-infoFilledBg, $alert-infoFilledBg); + @include var(color, --jf-palette-Alert-infoFilledColor, $alert-infoFilledColor); padding: 1em; border-radius: 0.25em; } -.ratingbutton-icon-withrating { - color: #c33; -} - -.downloadbutton-icon-complete, -.downloadbutton-icon-on { - color: #4285f4; -} - +.ratingbutton-icon-withrating, .playstatebutton-icon-played { - color: #c33; + @include var(background-color, --jf-palette-error-light, $error-light); } .buttonActive { - color: #00a4dc !important; + @include var(color, --jf-palette-primary-main, $primary-main, true); } .card:focus .cardBox.visualCardBox, .card:focus .cardBox:not(.visualCardBox) .cardScalable { - border-color: #00a4dc !important; + @include var(border-color, --jf-palette-primary-main, $primary-main, true); } ::-webkit-scrollbar-track { @@ -469,56 +481,36 @@ html { } .metadataSidebarIcon { - color: #00a4dc; -} - -.emby-button.detailFloatingButton { - background-color: #00a4dc; - color: #fff; -} - -.layout-tv .emby-button.detailFloatingButton:focus { - background-color: #f2f2f2; - color: #00a4dc; + @include var(color, --jf-palette-primary-main, $primary-main); } #comicsPlayer, #bookPlayer, #pdfPlayer { - background: #101010; + @include var(background-color, --jf-palette-background-default, $background-default); } #comicsPlayer .swiper-pagination { - background: #101010; - color: #fff; -} - -#bookPlayer .topButtons { - color: #fff; + @include var(background-color, --jf-palette-background-default, $background-default); + @include var(color, --jf-palette-text-primary, $text-primary); } +#bookPlayer .topButtons, #comicsPlayer .actionButtonIcon, #pdfPlayer .actionButtonIcon { - color: #fff; + @include var(color, --jf-palette-text-primary, $text-primary); } #dialogToc { - background-color: #101010; + @include var(background-color, --jf-palette-background-default, $background-default); } +#dialogToc .toc li a, #dialogToc .bookplayerButtonIcon { - color: #ccc; -} + @include var(color, --jf-palette-text-secondary, $text-secondary); -#dialogToc .bookplayerButtonIcon:hover { - color: #00a4dc; -} - -#dialogToc .toc li a:link { - color: #ccc; -} - -#dialogToc .toc li a:active, -#dialogToc .toc li a:hover { - color: #00a4dc; + &:active, + &:hover { + @include var(color, --jf-palette-primary-main, $primary-main); + } } diff --git a/src/themes/defaults.ts b/src/themes/defaults.ts index 5523652c8c..4c8a27a09f 100644 --- a/src/themes/defaults.ts +++ b/src/themes/defaults.ts @@ -25,6 +25,9 @@ export const DEFAULT_COLOR_SCHEME: ColorSystemOptions = { }, error: { main: '#c62828' // Red color + }, + AppBar: { + defaultBg: '#202020' } } }; diff --git a/src/themes/themes.ts b/src/themes/themes.ts index 0af1cdc975..0092409f09 100644 --- a/src/themes/themes.ts +++ b/src/themes/themes.ts @@ -64,6 +64,16 @@ const blueradiance = buildCustomColorScheme({ } }); +/** The default "Dark" color scheme. */ +const dark = merge({}, DEFAULT_COLOR_SCHEME, { + palette: { + SnackbarContent: { + bg: '#303030', + color: 'rgba(255, 255, 255, 0.87)' + } + } +}); + /** The "Light" color scheme. */ const light = merge({}, DEFAULT_COLOR_SCHEME, { palette: { @@ -115,7 +125,7 @@ const wmc = buildCustomColorScheme({ export const COLOR_SCHEMES = { appletv, blueradiance, - dark: DEFAULT_COLOR_SCHEME, + dark, light, purplehaze, wmc