Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions includes/SkinCitizen.php
Original file line number Diff line number Diff line change
Expand Up @@ -337,5 +337,14 @@ private function buildSkinFeatures( array &$options ): void {
if ( $config->get( 'CitizenEnableARFonts' ) === true ) {
$options['styles'][] = 'skins.citizen.styles.fonts.ar';
}

// Header position
$headerPosition = $config->get( 'CitizenHeaderPosition' );

if ( !in_array( $headerPosition, [ 'left', 'right', 'top', 'bottom' ] ) ) {
$headerPosition = 'left';
}

$this->getOutput()->addHtmlClasses( 'citizen-header-position-' . $headerPosition );
}
}
10 changes: 9 additions & 1 deletion resources/mixins.less
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@
}

.mixin-citizen-sticky-header-element() {
top: var( --height-sticky-header ) !important;
--header-offset: var( --height-sticky-header );

@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-header-position-top & {
--header-offset: calc( var( --header-size ) + var( --height-sticky-header ) );
}
}

top: var( --header-offset ) !important;
transition-timing-function: var( --transition-timing-function-ease );
transition-duration: var( --transition-duration-medium );
transition-property: top;
Expand Down
28 changes: 27 additions & 1 deletion resources/skins.citizen.styles/components/Drawer.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,33 @@
transform-origin: var( --transform-origin-offset-start ) var( --transform-origin-offset-end );

@media ( min-width: @min-width-breakpoint-desktop ) {
transform-origin: var( --transform-origin-offset-start ) var( --transform-origin-offset-start );
.citizen-header-position-left & {
right: unset;
left: 100%;
transform-origin: var( --transform-origin-offset-start ) var( --transform-origin-offset-start );
}

.citizen-header-position-right & {
right: 100%;
left: unset;
transform-origin: var( --transform-origin-offset-end ) var( --transform-origin-offset-start );
}

.citizen-header-position-top & {
top: 100%;
right: unset;
left: 0;
bottom: unset;
transform-origin: var( --transform-origin-offset-start ) var( --transform-origin-offset-start );
}

.citizen-header-position-bottom & {
top: unset;
right: unset;
left: 0;
bottom: 100%;
transform-origin: var( --transform-origin-offset-start ) var( --transform-origin-offset-end );
}
}
}

Expand Down
30 changes: 28 additions & 2 deletions resources/skins.citizen.styles/components/Dropdown.less
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,34 @@
.mixin-citizen-header-card( end );
transform-origin: var( --transform-origin-offset-end ) var( --transform-origin-offset-end );

@media ( min-width: @min-width-breakpoint-desktop ) {
transform-origin: var( --transform-origin-offset-start ) var( --transform-origin-offset-end );
@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-header-position-left & {
right: unset;
left: 100%;
transform-origin: var( --transform-origin-offset-start ) var( --transform-origin-offset-end );
}

.citizen-header-position-right & {
right: 100%;
left: unset;
transform-origin: var( --transform-origin-offset-end ) var( --transform-origin-offset-end );
}

.citizen-header-position-top & {
top: 100%;
right: 0;
left: unset;
bottom: unset;
transform-origin: var( --transform-origin-offset-end ) var( --transform-origin-offset-start );
}

.citizen-header-position-bottom & {
top: unset;
right: 0;
left: unset;
bottom: 100%;
transform-origin: var( --transform-origin-offset-end ) var( --transform-origin-offset-end );
}
}
}

Expand Down
9 changes: 7 additions & 2 deletions resources/skins.citizen.styles/components/Footer.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@
clear: both;
padding: var( --space-xxl ) var( --padding-page );
margin-top: 8rem;
// Reserve space for header
margin-bottom: var( --header-size );
contain: content;
color: var( --color-subtle );
background-color: var( --color-surface-1 );
direction: ltr;
.mixin-citizen-font-styles( 'small' );

@media ( max-width: @min-width-breakpoint-desktop ) {
.citizen-feature-autohide-navigation-clientpref-0 & {
// Reserve space for header, add only if autohide is off to avoid empty space
margin-bottom: var( --header-size );
}
}

&__container {
max-width: var( --width-page );
margin-inline: auto;
Expand Down
46 changes: 38 additions & 8 deletions resources/skins.citizen.styles/components/Header.less
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
gap: var( --space-xxs );
padding: ~'var( --space-xs ) max( env( safe-area-inset-right ), var( --space-xs ) ) max( env( safe-area-inset-bottom ), var( --space-xs ) ) max( env( safe-area-inset-left ), var( --space-xs ) )';
background-color: var( --color-surface-0 );
border-top: var( --border-base );
border: 0 solid var( --border-color-base );
border-top-width: var( --border-width-base );

&__item {
display: flex;
Expand Down Expand Up @@ -69,7 +70,8 @@
&__logo {
padding: 0 var( --space-xs ) 0 0;
margin: 0 var( --space-xxs );
border-right: var( --border-subtle );
border: 0 solid var( --border-color-subtle );
border-right-width: var( --border-width-base );

img {
margin: auto;
Expand Down Expand Up @@ -157,18 +159,46 @@

@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-header {
--header-direction: column;
top: 0;
right: unset;
left: 0;
border-top: 0;
border-right: var( --border-base );

&__logo {

.citizen-header-position-left &__logo,
.citizen-header-position-right &__logo {
padding: 0 0 var( --space-xs ) 0;
margin: var( --space-xxs ) 0;
border-right: 0;
border-bottom: var( --border-subtle );
border-bottom-width: var( --border-width-base );
}

.citizen-header-position-left & {
--header-direction: column;
right: unset;
left: 0;
border-right-width: var( --border-width-base );
}

.citizen-header-position-right & {
--header-direction: column;
right: 0;
left: unset;
border-left-width: var( --border-width-base );
}

.citizen-header-position-top & {
top: 0;
right: 0;
bottom: unset;
left: 0;
border-bottom-width: var( --border-width-base );
}

.citizen-header-position-bottom & {
top: unset;
right: 0;
bottom: 0;
left: 0;
border-top-width: var( --border-width-base );
}
}
}
18 changes: 17 additions & 1 deletion resources/skins.citizen.styles/components/StickyHeader.less
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,17 @@
transition-property: transform, visibility;

@media ( min-width: @min-width-breakpoint-desktop ) {
margin-left: var( --header-size );
.citizen-header-position-left & {
margin-left: var( --header-size );
}

.citizen-header-position-right & {
margin-right: var( --header-size );
}

.citizen-header-position-top & {
transform: translateY( calc( var( --header-size ) - 100% ) );
}
}
}

Expand Down Expand Up @@ -168,6 +178,12 @@
&-container {
visibility: visible;
transform: none;

@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-header-position-top & {
transform: translateY( calc( var( --header-size ) + var( --border-width-base ) ) );
}
}
}
}
}
Expand Down
18 changes: 16 additions & 2 deletions resources/skins.citizen.styles/components/TableOfContents.less
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,24 @@

@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-toc {
--header-offset: var( --height-sticky-header );

.citizen-header-position-top & {
--header-offset: calc( var( --header-size ) + var( --height-sticky-header ) );
}

.ve-active & {
--header-offset: 48px;
}

.citizen-header-position-top.ve-active & {
--header-offset: calc( var( --header-size ) + 48px );
}

position: -webkit-sticky;
position: sticky;
top: var( --height-sticky-header );
max-height: ~'calc( 100vh - var( --height-sticky-header ) )';
top: var( --header-offset );
max-height: ~'calc( 100vh - var( --header-offset ) )';
padding: var( --space-xs ) 0;
overflow-y: auto;
overscroll-behavior: contain;
Expand Down
16 changes: 15 additions & 1 deletion resources/skins.citizen.styles/layout.less
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,21 @@
@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-page-container {
// Reserve space for header
margin-left: var( --header-size );
.citizen-header-position-left & {
margin-left: var( --header-size );
}

.citizen-header-position-right & {
margin-right: var( --header-size );
}

.citizen-header-position-top & {
margin-top: var( --header-size );
}

.citizen-header-position-bottom & {
margin-bottom: var( --header-size );
}
}

.citizen-toc-enabled {
Expand Down
6 changes: 6 additions & 0 deletions skin.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,12 @@
"description": "Enables or disable the command palette. Disable to use the old search module.",
"descriptionmsg": "citizen-config-enablecommandpalette",
"public": true
},
"HeaderPosition": {
"value": "left",
"description": "Position of the header on the desktop layout. Possible values: 'left', 'right', 'top' and 'bottom'",
"descriptionmsg": "citizen-config-headerposition",
"public": true
}
Comment on lines +897 to 902
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

New public config entry HeaderPosition looks correct; verify i18n and server-side hookup

The declaration is fine. Please verify:

  • The i18n message key citizen-config-headerposition exists.
  • Server-side code normalizes/validates the value and emits citizen-header-position-{left|right|top|bottom} on the root element.

Run this script to confirm wiring and i18n presence:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching for i18n message citizen-config-headerposition…"
rg -nP '"citizen-config-headerposition"\s*:' i18n -S || { echo "MISSING: i18n message"; exit 1; }

echo "Searching for server-side usage of HeaderPosition…"
rg -nP '\bHeaderPosition\b' includes -S || echo "WARN: No direct HeaderPosition usage found under includes/"

echo "Searching for emission of citizen-header-position-* class…"
rg -nP 'citizen-header-position-(left|right|top|bottom)' includes resources -n -S

Length of output: 79


Add missing i18n key and verify server-side hookup

  • The i18n message key citizen-config-headerposition is not defined.
  • Add this key in your locale files.
  • Ensure the server normalizes/validates the new HeaderPosition config and emits the citizen-header-position-{left|right|top|bottom} class on the root element.

},
"manifest_version": 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@

@media only screen and ( min-width: @min-width-breakpoint-desktop ) {
right: unset;
left: var( --header-size );
left: 0;

.citizen-header-position-left & {
left: var( --header-size );
}
}

.citizen-header-position-bottom & {
bottom: var( --header-size );
}

.mw-cookiewarning-text {
Expand Down
33 changes: 31 additions & 2 deletions skinStyles/extensions/Echo/ext.echo.ui.less
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,30 @@
box-shadow: var( --box-shadow-large );

@media ( min-width: @min-width-breakpoint-desktop ) {
bottom: 0 !important;
left: var( --header-size ) !important;
.citizen-header-position-left & {
right: unset !important;
left: var( --header-size ) !important;
bottom: 0 !important;
}

.citizen-header-position-right & {
right: var( --header-size ) !important;
left: unset !important;
bottom: 0 !important;
}

.citizen-header-position-top & {
right: 0 !important;
left: unset !important;
top: var( --header-size ) !important;
bottom: unset !important;
}

.citizen-header-position-bottom & {
right: 0 !important;
left: unset !important;
bottom: var( --header-size ) !important;
}
}

.oo-ui-popupWidget-body {
Expand Down Expand Up @@ -84,6 +106,13 @@
bottom: 0;
z-index: @z-index-overlay; // Higher than header

@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-header-position-top & {
top: 0;
bottom: unset;
}
}

// Add dismiss affordnance backdrop
@media ( max-width: @max-width-breakpoint-tablet ) {
&::before {
Expand Down
4 changes: 4 additions & 0 deletions skinStyles/extensions/MediaSearch/mediasearch.styles.less
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,10 @@
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}

.citizen-header-position-bottom & {
padding-bottom: var( --header-size );
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions skinStyles/extensions/VisualEditor/ext.visualEditor.core.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
/* Fix weird gap between save button and toolbar bottom */
border-bottom: 0;
box-shadow: 0 1px 0 0 var( --border-color-base );

@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-header-position-top .ve-ui-toolbar-floating& {
top: var( --header-size );
}
}
}

/* ve.ce.BranchNode.css */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@
&-bar {
border-bottom-color: var( --border-color-base );
box-shadow: none;

@media ( min-width: @min-width-breakpoint-desktop ) {
.citizen-header-position-top & {
top: var( --header-size );
}
}
}
}

Expand Down
Loading
Loading