Responsive support, JS edition

Dropdown menus and js interactiveness for people who like to pretend
we live in a modern era or something.

Does not actually support newfangled tapping and swiping stuff.
Does not properly support echo. (will follow up)

Change-Id: I27d50c320b1526b9d158016a0e8022567f78ccc1
This commit is contained in:
Isarra 2018-05-03 19:45:10 +00:00
parent 70d426d4fd
commit 0e2ee04c87
13 changed files with 369 additions and 70 deletions

View file

@ -50,6 +50,9 @@ class SkinMonoBook extends SkinTemplate {
'mediawiki.skinning.content.externallinks',
'skins.monobook.styles'
] );
$out->addModules( [
'skins.monobook.mobile'
] );
// TODO: Migrate all of these (get RL support for conditional IE)
// Force desktop styles in IE 8-; no support for @media widths

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 4.233 4.233">
<defs>
<radialGradient id="b" cx="2.117" cy="1.852" r="1.521" fx="2.117" fy="1.852" gradientTransform="matrix(1.04348 0 0 1 -.092 0)" gradientUnits="userSpaceOnUse" xlink:href="#a"/>
<linearGradient id="a">
<stop offset="0" stop-color="#f60f0f"/>
<stop offset=".696" stop-color="#f97e54"/>
<stop offset="1" stop-color="#f10000"/>
</linearGradient>
</defs>
<path fill="url(#b)" fill-rule="evenodd" d="M.794 1.323l.264-.53.53-.264c.264-.264.793-.264 1.058 0l.529.265.265.529c.264.264.264.794 0 1.058l-.265.53-.53.264c-.264.265-.793.265-1.058 0l-.529-.265-.264-.529c-.265-.264-.265-.794 0-1.058z"/>
<path fill="#fff" d="M1.588 1.323h.265v.265h-.265z"/>
<path fill="#fff" d="M1.852 1.587v.53h.529v-.53h-.264zM2.381 2.117h.265v.265h-.265z"/>
<path fill="#fff" d="M2.381 1.323h.265v.265h-.265zM1.588 2.117h.265v.265h-.265z"/>
<path fill="#faa" d="M1.587 1.058v.265h.265v-.265zm0 .265h-.264v.264h.264zm.794-.265v.265h.265v-.265zm.265.265v.264h.264v-.264zm-1.323.794v.264h.264v-.264zm.264.264v.265h.265V2.38zm1.059-.264v.264h.264v-.264zm0 .264H2.38v.265h.265z"/>
<path fill="#ffb5b5" d="M1.852 1.323v.264h.53v-.264zm.53.264v.53h.264v-.53zm0 .53h-.53v.264h.53zm-.53 0v-.53h-.265v.53z"/>
<path fill="#ffd5d5" d="M1.323 1.058v.265h.264v-.265zm1.323 0v.265h.264v-.265zM1.323 2.381v.265h.264V2.38zm1.323 0v.265h.264V2.38z"/>
<path fill="#8b8b8b" d="M1.587.265v.264h.794V.265zm0 .264h-.529v.265h.53zm-.529.265H.794v.529h.264zm-.264.529H.529V2.38h.265zm0 1.058v.53h.264v-.53zm.264.53v.264h.53V2.91zm.53.264v.265h.264v-.265z"/>
<path fill="#4e4e4e" d="M2.381.265v.264h.265V.265zm.265.264v.265h.529V.529zm.529.265v.529h.265v-.53zm.265.529V2.38h.264V1.323zm0 1.058h-.265v.53h.265zm-.265.53h-.53v.264h.53zm-.53.264h-.793v.265h.794z"/>
<path fill="#fff" fill-rule="evenodd" d="M1.587 1.058l-.264.265.53.53-.53.528.264.265.53-.53.529.53.264-.265-.529-.529.53-.53-.265-.264-.53.53z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 4.233 4.233">
<defs>
<linearGradient id="b">
<stop offset="0" stop-color="#fae7d1"/>
<stop offset="1" stop-color="#efaf67"/>
</linearGradient>
<linearGradient id="a">
<stop offset="0" stop-color="#f9dccc"/>
<stop offset="1" stop-color="#dd9873"/>
</linearGradient>
<linearGradient id="c">
<stop offset="0" stop-color="#faeca8"/>
<stop offset=".213" stop-color="#fcf4b3"/>
<stop offset=".299" stop-color="#f4d644"/>
<stop offset=".484" stop-color="#faee8e"/>
<stop offset="1" stop-color="#e4ba2f"/>
</linearGradient>
<linearGradient id="f" x1="2.873" x2="3.241" y1="1.013" y2="1.373" gradientUnits="userSpaceOnUse" xlink:href="#a"/>
<linearGradient id="e" x1="1.147" x2="1.323" y1="2.716" y2="3.175" gradientUnits="userSpaceOnUse" xlink:href="#b"/>
<linearGradient id="d" x1="1.587" x2="2.381" y1="1.587" y2="2.381" gradientUnits="userSpaceOnUse" xlink:href="#c"/>
</defs>
<path fill="url(#d)" fill-rule="evenodd" d="M1.058 2.117L2.25.926l.794.794-1.19 1.19z"/>
<path fill="url(#e)" fill-rule="evenodd" d="M1.19 2.249l-.396.132-.133.926.927-.132.132-.397z"/>
<path fill="#4e4e4e" d="M.794 3.175v.265h.794v-.265zm.794-.265h.265v.265h-.265z"/>
<path fill="#4e4e4e" d="M1.852 2.646h.265v.265h-.265zm.265-.265h.265v.265h-.265z"/>
<path fill="#4e4e4e" d="M2.381 2.117h.265v.265h-.265zm.265-.265h.265v.265h-.265z"/>
<path fill="url(#f)" fill-rule="evenodd" d="M2.249.926l.397-.397.397-.132.529.529-.132.397-.397.397z"/>
<path fill="#4e4e4e" d="M2.91 1.587h.265v.265H2.91z"/>
<path fill="#4e4e4e" d="M3.175 1.323h.265v.265h-.265zm.265-.265h.265v.265H3.44z"/>
<path fill="#8b8b8b" d="M2.646.265v.264h.529V.265zm.529.264v.265h.265V.529zm.265.265v.264h.264V.794zM2.646.529H2.38v.265h.265zM2.38.794h-.264v.264h.264zm-.264.264h-.265v.265h.265zm-.265.265h-.264v.264h.264zm-.264.264h-.265v.265h.265zm-.265.265h-.265v.265h.265zm-.265.265H.794v.264h.264zm-.264.264H.529V3.44h.265z"/>
<path fill="#a3a3a3" d="M2.91 3.175v.265H1.852v-.265z"/>
<path fill="#e6e6e6" d="M2.91 3.175v.265h.53v-.265z"/>
<path fill="#584013" d="M.794 2.91v.265h.264V2.91z"/>
<path fill="#e89840" d="M1.058 2.117v.264h.265v-.264zm.265.264v.265h.265V2.38z"/>
<path fill="#c26715" d="M1.588 2.646v.264h.264v-.264z"/>
<path fill="#f4c2a7" d="M2.91.53v.264h.265V.529zm-.529.528v.265h.265v-.265z"/>
<path fill="#dd9873" d="M3.175.794v.264h.265V.794zm-.53.529v.264h.265v-.264z"/>
<path fill="#d49c5d" d="M1.058 2.91v.265h.265V2.91z"/>
<path fill="#f6d4ad" d="M.794 2.646v.264h.264v-.264z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

92
resources/mobile.js Normal file
View file

@ -0,0 +1,92 @@
( function ( mw, $ ) {
$( function () {
var mobileCutoffWidth = 850,
// Track if DOM has been set up for mobile fanciness yet
monobookMobileElements = false,
// Toggles and targets for popouts
toggles = {
'#sidebar-toggle': '#sidebar-mobilejs',
'#p-personal-toggle': '#p-personal',
'#ca-more a': '#p-cactions',
'#ca-languages a': '#p-lang',
'#ca-tools a': '#p-tb'
};
// Close menus
function closeMenus() {
$( '.mobile-menu-active' ).removeClass( 'mobile-menu-active' );
$( '.menus-cover' ).removeClass( 'visible' );
}
// Set up DOM for mobile fanciness
// We don't automatically do this because MonoBook; most users will be on desktop
function setupMonoBookMobile() {
if ( !monobookMobileElements && $( window ).width() <= mobileCutoffWidth ) {
// Duplicate nav
$( '#column-one' ).append(
$( '#sidebar' ).clone().find( '*' ).addBack().each( function () {
if ( this.id ) {
this.id = this.id + '-mobilejs';
}
} ).end().end()
);
// Thing to fade out the content while menus are active
$( '#column-one' ).append( $( '<div id="menus-cover-background" class="menus-cover">' ) );
$( '#column-one' ).append( $( '<div id="menus-cover" class="menus-cover">' ) );
// Add extra cactions tabs - edit, editsource, contributions
// Wrap in function to keep jenkins from whining
$( function () {
var newTabs = [
'ca-edit',
// 'ca-ve-edit', // TODO when VE is more usable to begin with here
// 'ca-watch', 'ca-unwatch', // Maybe?
't-contributions'
];
$.each( newTabs, function ( i, item ) {
var a = $( '#' + item + ' a' );
if ( a.length ) {
mw.util.addPortletLink(
'p-cactions-mobile',
a.attr( 'href' ),
a.text(),
a.parent().attr( 'id' ) + '-mobile',
a.attr( 'tooltip' ),
a.attr( 'accesskey' ),
'#ca-more'
);
}
} );
} );
// Add close buttons
$.each( toggles, function ( toggle, target ) {
$( target ).append( $( '<div class="mobile-close-button">' ) );
} );
// Open menus
$.each( toggles, function ( toggle, target ) {
$( toggle ).on( 'click', function () {
if ( $( window ).width() <= mobileCutoffWidth ) {
$( target ).addClass( 'mobile-menu-active' );
$( '.menus-cover' ).addClass( 'visible' );
}
// Don't still link to # targets
return false;
} );
} );
$( '.mobile-close-button, .menus-cover' ).click( closeMenus );
// TODO: tap events on same (if not already included in 'click') - also close
// TODO: appropriate swipe event(s) - also close
monobookMobileElements = true;
}
}
$( window ).resize( setupMonoBookMobile );
setupMonoBookMobile();
} );
}( mediaWiki, jQuery ) );

107
resources/mobile.js.less Normal file
View file

@ -0,0 +1,107 @@
@import 'variables.less';
// remove duplicates we're not using here; this is cleaner and/or easier than in js
#sidebar .generated-sidebar,
*[ id^='ca-nstab-' ],
#ca-talk,
#ca-edit,
#t-contributions,
#p-search-mobilejs,
#p-tb-mobilejs,
#p-lang-mobilejs {
display: none;
}
// popouts
#p-cactions,
#p-personal,
#p-tb,
#p-lang,
#sidebar-mobilejs {
display: none;
&.mobile-menu-active {
display: block;
}
}
.mobile-menu-active {
position: absolute;
z-index: 10000;
top: 2em;
left: 0;
background: @content-background;
border: solid 1px @orange-border;
border-left: 0;
padding: 2em 2em 0 1.5em;
font-size: 125%;
ul {
padding-top: 1em;
}
li {
white-space: nowrap;
}
a {
display: block;
padding: 0.65em 0;
}
h3:first-child {
margin-right: 2em;
}
.pBody {
margin-bottom: 2em;
}
.mobile-close-button {
width: 20px;
height: 20px;
.background-image-svg( 'images/icon-close.svg', 'images/icon-close.gif' );
background-position: 0 0;
background-repeat: no-repeat;
position: absolute;
top: 1em;
right: 0.75em;
cursor: pointer;
}
}
.menus-cover {
display: none;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
&.visible {
display: block;
}
}
#menus-cover {
position: fixed;
opacity: 0.45;
background-color: @content-background;
}
#menus-cover-background {
position: absolute;
background-color: @background;
.background-image-svg( 'images/headbg.svg', 'images/headbg.jpg' );
background-position: 0 0;
background-repeat: no-repeat;
opacity: 0.55;
}
#p-cactions-mobile li {
&#ca-edit-mobile a {
.background-image-svg( 'images/icon-edit.svg', 'images/icon-edit.gif' );
}
&#t-contributions-mobile a {
.background-image-svg( 'images/icon-user.svg', 'images/icon-user.gif' );
}
}

View file

@ -162,9 +162,7 @@ table.rimage {
background: transparent;
display: inline;
height: 1em;
text-transform: lowercase;
font-size: 91%;
font-weight: normal;
white-space: nowrap;
}
@ -215,23 +213,11 @@ table.rimage {
font-weight: bold;
}
/* Don't lowercase username */
li#pt-userpage {
text-transform: none;
}
/* "Not logged in" text in gray */
li#pt-anonuserpage {
color: @text-grey;
}
/* Override text-transform on languages where capitalization is significant */
.capitalize-all-nouns .portlet h3,
.capitalize-all-nouns #p-personal ul,
.capitalize-all-nouns #p-cactions ul li a {
text-transform: none;
}
/*
** footer
*/
@ -382,11 +368,6 @@ div.mw-lag-warn-high {
}
}
/* Sometimes people don't want personal tools to be lowercase! */
.no-text-transform {
text-transform: none;
}
/* Tooltips are outside of the normal body code, so this helps make the size of the text sensible */
.tipsy {
font-size: 127%;

View file

@ -46,6 +46,8 @@ div#column-one {
.portlet h3 {
padding: 0 1em 0 0.5em;
text-transform: lowercase;
font-weight: normal;
}
.pBody {
@ -54,6 +56,23 @@ div#column-one {
padding: 0 0.8em 0.3em 0.5em;
}
/* Don't lowercase username */
li#pt-userpage {
text-transform: none;
}
/* Override text-transform on languages where capitalization is significant */
.capitalize-all-nouns .portlet h3,
.capitalize-all-nouns #p-personal ul,
.capitalize-all-nouns #p-cactions ul li a {
text-transform: none;
}
/* Sometimes people don't want personal tools to be lowercase! */
.no-text-transform {
text-transform: none;
}
/*
** Logo properties
*/
@ -308,7 +327,10 @@ li#ca-print {
** mobile toggles; not used here
*/
#p-cactions-mobile,
.menu-toggle {
#sidebar-mobilejs,
.mobile-close-button,
.menu-toggle,
.menus-cover {
display: none;
}

View file

@ -16,19 +16,8 @@ div#column-content {
/*
** Navigation
*/
@top-position: 5px;
@block-size: 35px;
.menu-toggle {
display: block;
width: @block-size;
height: @block-size;
background: @content-background;
border: solid 1px @orange-border;
box-sizing: border-box;
background-position: 50% 50%;
background-repeat: no-repeat;
z-index: 4;
.menu-button();
}
#sidebar-toggle {
@ -110,11 +99,12 @@ div#column-content {
}
/*
** site nav
** site nav, nojs layout
*/
.client-nojs {
#p-cactions,
#p-personal,
.generated-sidebar,
#sidebar .generated-sidebar,
#p-tb,
#p-lang {
margin: 1em;
@ -155,6 +145,11 @@ div#column-content {
}
}
}
h3 {
font-weight: normal;
}
}
}
/*
@ -252,8 +247,8 @@ div#column-content {
#f-poweredbyico,
#f-copyrightico {
display: inline;
margin: 0 0.5em;
display: inline-block;
margin: 0 0.5em 1em;
}
/*

View file

@ -0,0 +1,6 @@
#pt-uls a.uls-trigger {
background-size: 16px;
}
div.uls-menu {
margin-top: -2.5em;
}

View file

@ -14,6 +14,22 @@
@link-visited: #5a3696;
@link-new: #c20;
// mobile objects
@top-position: 5px;
@block-size: 35px;
.menu-button() {
display: block;
width: @block-size;
height: @block-size;
background: @content-background;
border: solid 1px @orange-border;
box-sizing: border-box;
background-position: 50% 50%;
background-repeat: no-repeat;
z-index: 4;
}
// To hide objects, but keep them accessible for screen-readers
.hidden() {
position: absolute;

View file

@ -38,6 +38,20 @@
"media": "screen and (max-width: 850px)"
}
}
},
"skins.monobook.mobile": {
"targets": [ "desktop", "mobile" ],
"scripts": [
"resources/mobile.js"
],
"styles": {
"resources/mobile.js.less": {
"media": "screen and (max-width: 850px)"
}
},
"dependencies": [
"mediawiki.util"
]
}
},
"ResourceFileModulePaths": {
@ -49,7 +63,8 @@
"+mediawiki.action.view.redirectPage": "resources/skinStyles/mediawiki.action.view.redirectPage.css",
"+mediawiki.special.preferences.styles": "resources/skinStyles/mediawiki.special.preferences.styles.less",
"+mediawiki.notification": "resources/skinStyles/mediawiki.notification.less",
"+oojs-ui-core.styles": "resources/skinStyles/ooui.less"
"+oojs-ui-core.styles": "resources/skinStyles/ooui.less",
"+ext.uls.interface": "resources/skinStyles/ext.uls.interface.less"
}
},
"AutoloadClasses": {