diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeGraphicsController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeGraphicsController.cs index 11c9a36e2545..3dc491b714e8 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeGraphicsController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeGraphicsController.cs @@ -19,6 +19,7 @@ namespace Umbraco.Cms.Api.Management.Controllers.Security; public class BackOfficeGraphicsController : Controller { public const string LogoRouteName = nameof(BackOfficeGraphicsController) + "." + nameof(Logo); + public const string LogoAlternativeRouteName = nameof(BackOfficeGraphicsController) + "." + nameof(LogoAlternative); public const string LoginBackGroundRouteName = nameof(BackOfficeGraphicsController) + "." + nameof(LoginBackground); public const string LoginLogoRouteName = nameof(BackOfficeGraphicsController) + "." + nameof(LoginLogo); public const string LoginLogoAlternativeRouteName = nameof(BackOfficeGraphicsController) + "." + nameof(LoginLogoAlternative); @@ -44,6 +45,11 @@ public BackOfficeGraphicsController(IOptions contentSettings, I [MapToApiVersion("1.0")] public IActionResult Logo() => HandleFileRequest(_contentSettings.Value.BackOfficeLogo); + [HttpGet("logo-alternative", Name = LogoAlternativeRouteName)] + [AllowAnonymous] + [MapToApiVersion("1.0")] + public IActionResult LogoAlternative() => HandleFileRequest(_contentSettings.Value.BackOfficeLogoAlternative); + [HttpGet("login-logo", Name = LoginLogoRouteName)] [AllowAnonymous] [MapToApiVersion("1.0")] diff --git a/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_blue.svg b/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_blue.svg new file mode 100644 index 000000000000..213e629228a1 --- /dev/null +++ b/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_blue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_dark.svg b/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_dark.svg index 578bf592f68e..5a06848ca273 100644 --- a/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_dark.svg +++ b/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_dark.svg @@ -1,51 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_light.svg b/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_light.svg index 01f7260cd3b4..2cf6f016b5e4 100644 --- a/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_light.svg +++ b/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/assets/logo_light.svg @@ -1,51 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs index 28c9ad142747..0b2789180ede 100644 --- a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs @@ -23,6 +23,7 @@ public class ContentSettings internal const string StaticLoginLogoImage = "assets/logo_light.svg"; internal const string StaticLoginLogoImageAlternative = "assets/logo_dark.svg"; internal const string StaticBackOfficeLogo = "assets/logo.svg"; + internal const string StaticBackOfficeLogoAlternative = "assets/logo_blue.svg"; internal const bool StaticHideBackOfficeLogo = false; internal const bool StaticDisableDeleteWhenReferenced = false; internal const bool StaticDisableUnpublishWhenReferenced = false; @@ -88,9 +89,18 @@ public class ContentSettings /// /// Gets or sets a value for the path to the backoffice logo. /// + /// The alternative version of this logo can be found at . [DefaultValue(StaticBackOfficeLogo)] public string BackOfficeLogo { get; set; } = StaticBackOfficeLogo; + /// + /// Gets or sets a value for the path to the alternative backoffice logo, which can be shown + /// on top of a light background. + /// + /// This is the alternative version to the regular logo found at . + [DefaultValue(StaticBackOfficeLogoAlternative)] + public string BackOfficeLogoAlternative { get; set; } = StaticBackOfficeLogoAlternative; + /// /// Gets or sets a value indicating whether to hide the backoffice umbraco logo or not. /// diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-logo.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-logo.element.ts index 6c885e274fa6..ee1b7557f78b 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/app/app-logo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-logo.element.ts @@ -1,17 +1,59 @@ import { UMB_APP_CONTEXT } from './app.context.js'; +import { customElement, html, nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { customElement, html, nothing, state } from '@umbraco-cms/backoffice/external/lit'; +import { UMB_THEME_CONTEXT } from '@umbraco-cms/backoffice/themes'; @customElement('umb-app-logo') export class UmbAppLogoElement extends UmbLitElement { + /** + * The loading attribute of the image. + * @type {'lazy' | 'eager'} + * @default 'eager' + */ + @property() + loading: 'lazy' | 'eager' = 'lazy'; + + /** + * The type of logo to display. Mark will display the mark logo, and logo will display the full logo with text. + * @type {'mark' | 'logo'} + * @default 'mark' + */ + @property({ type: String, attribute: 'logo-type' }) + logoType: 'mark' | 'logo' = 'mark'; + + /** + * Override the application theme, for example if you want to display the dark theme logo on a light theme. + * @example 'umb-dark-theme' + * @type {string} + * @default undefined + */ + @property({ attribute: 'override-theme' }) + overrideTheme?: string; + @state() - private _logoUrl?: string; + private _serverUrl?: string; + + /** + * The theme of the application. + */ + @state() + private _theme?: string; constructor() { super(); this.consumeContext(UMB_APP_CONTEXT, (instance) => { - this._logoUrl = `${instance.getServerUrl()}/umbraco/management/api/v1/security/back-office/graphics/logo`; + this._serverUrl = instance.getServerUrl(); + }); + + this.consumeContext(UMB_THEME_CONTEXT, (context) => { + this.observe( + context.theme, + (theme) => { + this._theme = theme; + }, + '_observeTheme', + ); }); } @@ -24,11 +66,23 @@ export class UmbAppLogoElement extends UmbLitElement { } override render() { - if (!this._logoUrl) { + if (!this._serverUrl) { return nothing; } - return html``; + /** + * This is a temporary solution until we have a better way to define the logo characteristics. + * TODO: The characteristics of the logo are not defined in any theme meta data, so we have to hardcode the logo file names. + */ + let logoFile = (this.overrideTheme ?? this._theme) === 'umb-dark-theme' ? 'logo' : 'logo-alternative'; + + if (this.logoType === 'logo') { + logoFile = `login-${logoFile}`; + } + + const logoUrl = `${this._serverUrl}/umbraco/management/api/v1/security/back-office/graphics/${logoFile}`; + + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts index fe4c3af09acf..03af4fdac547 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts @@ -1,13 +1,22 @@ import { UMB_BACKOFFICE_CONTEXT } from '../backoffice.context.js'; -import { isCurrentUserAnAdmin } from '@umbraco-cms/backoffice/current-user'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { isCurrentUserAnAdmin } from '@umbraco-cms/backoffice/current-user'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_NEWVERSION_MODAL, UMB_SYSINFO_MODAL } from '@umbraco-cms/backoffice/sysinfo'; import type { UmbServerUpgradeCheck } from '@umbraco-cms/backoffice/sysinfo'; +/** + * The backoffice header logo element. + * @cssprop --umb-header-logo-display - The display property of the header logo. + * @cssprop --umb-header-logo-margin - The margin of the header logo. + * @cssprop --umb-header-logo-width - The width of the header logo. + * @cssprop --umb-header-logo-height - The height of the header logo. + * @cssprop --umb-logo-display - The display property of the logo. + * @cssprop --umb-logo-width - The width of the logo. + * @cssprop --umb-logo-height - The height of the logo. + */ @customElement('umb-backoffice-header-logo') export class UmbBackofficeHeaderLogoElement extends UmbLitElement { @state() @@ -19,9 +28,6 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement { @state() private _serverUpgradeCheck: UmbServerUpgradeCheck | null = null; - @state() - private _serverUrl = ''; - #backofficeContext?: typeof UMB_BACKOFFICE_CONTEXT.TYPE; constructor() { @@ -39,10 +45,6 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement { this.#backofficeContext = context; }); - - this.consumeContext(UMB_APP_CONTEXT, (context) => { - this._serverUrl = context.getServerUrl(); - }); } protected override async firstUpdated() { @@ -59,19 +61,13 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement { override render() { return html` -