Add css var support for dark theme

This commit is contained in:
Bill Thornton
2025-10-31 09:41:04 -04:00
parent ac2d059219
commit 99fea57a95
5 changed files with 182 additions and 179 deletions

View File

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

View File

@@ -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;

View File

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

View File

@@ -25,6 +25,9 @@ export const DEFAULT_COLOR_SCHEME: ColorSystemOptions = {
},
error: {
main: '#c62828' // Red color
},
AppBar: {
defaultBg: '#202020'
}
}
};

View File

@@ -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