diff --git a/.storybook/main.js b/.storybook/main.js
index 2d25cacb1..a65c3f634 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -4,10 +4,6 @@ const webpack = require( "webpack" );
module.exports = {
stories: ['./stories/*.stories.js' ],
webpackFinal: async (config, { configType }) => {
- config.module.rules.push({
- test: /\.css$/,
- use: ['style-loader', 'css-loader']
- });
config.module.rules.push({
test: /\.less$/,
use: ['style-loader', 'css-loader', {
diff --git a/.storybook/stories/index.stories.js b/.storybook/stories/index.stories.js
index ce36e6d36..0760ac637 100644
--- a/.storybook/stories/index.stories.js
+++ b/.storybook/stories/index.stories.js
@@ -21,6 +21,7 @@ import { storiesOf } from '@storybook/html';
* Popups dependencies
*/
import { createPointerMasks } from '../../src/ui/renderer.js';
+import '../../node_modules/@wikimedia/codex/dist/codex.style.css';
/**
* Popups helpers
diff --git a/extension.json b/extension.json
index 10d765535..bc14cc35c 100644
--- a/extension.json
+++ b/extension.json
@@ -25,7 +25,8 @@
"UserGetDefaultOptions": "PopupsHooks",
"MakeGlobalVariablesScript": "PopupsHooks",
"LocalUserCreated": "PopupsHooks",
- "GetBetaFeaturePreferences": "PopupsHooks"
+ "GetBetaFeaturePreferences": "PopupsHooks",
+ "ResourceLoaderRegisterModules": "PopupsHooks"
},
"HookHandlers": {
"PopupsHooks": {
@@ -229,12 +230,12 @@
"mediawiki.jqueryMsg",
"mediawiki.storage",
"mediawiki.Title",
- "mediawiki.ui.button",
"mediawiki.ui.checkbox",
"mediawiki.ui.icon",
"mediawiki.Uri",
"mediawiki.user",
- "mediawiki.util"
+ "mediawiki.util",
+ "codex-search-styles"
]
}
},
diff --git a/includes/PopupsHooks.php b/includes/PopupsHooks.php
index 49fed0ae9..2a3f47007 100644
--- a/includes/PopupsHooks.php
+++ b/includes/PopupsHooks.php
@@ -28,6 +28,8 @@ use MediaWiki\Hook\MakeGlobalVariablesScriptHook;
use MediaWiki\MediaWikiServices;
use MediaWiki\Preferences\Hook\GetPreferencesHook;
use MediaWiki\ResourceLoader\Hook\ResourceLoaderGetConfigVarsHook;
+use MediaWiki\ResourceLoader\Hook\ResourceLoaderRegisterModulesHook;
+use MediaWiki\ResourceLoader\ResourceLoader;
use MediaWiki\User\Hook\UserGetDefaultOptionsHook;
use MediaWiki\User\UserOptionsManager;
use OutputPage;
@@ -43,6 +45,7 @@ class PopupsHooks implements
GetPreferencesHook,
BeforePageDisplayHook,
ResourceLoaderGetConfigVarsHook,
+ ResourceLoaderRegisterModulesHook,
MakeGlobalVariablesScriptHook,
UserGetDefaultOptionsHook,
LocalUserCreatedHook
@@ -320,4 +323,25 @@ class PopupsHooks implements
}
}
+ /**
+ * ResourceLoaderRegisterModules hook handler.
+ *
+ * Provides support for MLEB where needed.
+ *
+ * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderRegisterModules
+ *
+ * @param ResourceLoader $resourceLoader
+ */
+ public function onResourceLoaderRegisterModules( ResourceLoader $resourceLoader ): void {
+ if ( !$resourceLoader->getModule( 'codex-search-styles' ) ) {
+ // We're running an older version of MediaWiki.
+ $resourceLoader->register( [
+ 'codex-search-styles' => [
+ 'localBasePath' => dirname( __DIR__ ),
+ 'remoteExtPath' => 'UniversalLanguageSelector',
+ 'styles' => 'resources/codex.mleb.css',
+ ]
+ ] );
+ }
+ }
}
diff --git a/package-lock.json b/package-lock.json
index 8473d0d90..fbd33d4af 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,8 +18,8 @@
"@wdio/local-runner": "7.4.6",
"@wdio/mocha-framework": "7.30.2",
"@wdio/sync": "7.4.6",
- "@wikimedia/codex": "0.11.0",
- "@wikimedia/codex-icons": "0.11.0",
+ "@wikimedia/codex": "0.14.0",
+ "@wikimedia/codex-icons": "0.14.0",
"@wikimedia/mw-node-qunit": "7.0.0",
"babel-loader": "8.0.4",
"browserslist-config-wikimedia": "0.2.0",
@@ -6550,9 +6550,9 @@
}
},
"node_modules/@wikimedia/codex": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@wikimedia/codex/-/codex-0.11.0.tgz",
- "integrity": "sha512-DYI9ewtEqNykzYp1nMcyrtbKpGbVPTWkbxV9QJIDIDe2GayA8XbfK/7u0V5cnTU90iqCLwqsEnQZiXX4QDvsWg==",
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@wikimedia/codex/-/codex-0.14.0.tgz",
+ "integrity": "sha512-qx3ADc2I5yDg448WVZ6TodGdV2vCs4SLgH6KdDx0obAr+1vsmBUyBhaVenJOL2WrMDq1rAxV1gx7YrbgOoU/MQ==",
"dev": true,
"engines": {
"node": ">=16",
@@ -6563,9 +6563,9 @@
}
},
"node_modules/@wikimedia/codex-icons": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@wikimedia/codex-icons/-/codex-icons-0.11.0.tgz",
- "integrity": "sha512-aXpGI5UsWiWk1uag5I2+YlJinflmUVEyFoDH8IOt+Nko7t/z6EbJCHoMV482pVl9Ygbk2/ukHQ3LOFyS0Dv8xQ==",
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@wikimedia/codex-icons/-/codex-icons-0.14.0.tgz",
+ "integrity": "sha512-xbHV+5OMhIXrtfweeDAXO/HN69fn+bSUZtns6hbMgWsAK8t3hYyhQRzUeFJxrS0tApG4X9NQxIQ6mOmjZwz/rA==",
"dev": true,
"engines": {
"node": ">=16",
@@ -32567,16 +32567,16 @@
}
},
"@wikimedia/codex": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@wikimedia/codex/-/codex-0.11.0.tgz",
- "integrity": "sha512-DYI9ewtEqNykzYp1nMcyrtbKpGbVPTWkbxV9QJIDIDe2GayA8XbfK/7u0V5cnTU90iqCLwqsEnQZiXX4QDvsWg==",
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@wikimedia/codex/-/codex-0.14.0.tgz",
+ "integrity": "sha512-qx3ADc2I5yDg448WVZ6TodGdV2vCs4SLgH6KdDx0obAr+1vsmBUyBhaVenJOL2WrMDq1rAxV1gx7YrbgOoU/MQ==",
"dev": true,
"requires": {}
},
"@wikimedia/codex-icons": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@wikimedia/codex-icons/-/codex-icons-0.11.0.tgz",
- "integrity": "sha512-aXpGI5UsWiWk1uag5I2+YlJinflmUVEyFoDH8IOt+Nko7t/z6EbJCHoMV482pVl9Ygbk2/ukHQ3LOFyS0Dv8xQ==",
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@wikimedia/codex-icons/-/codex-icons-0.14.0.tgz",
+ "integrity": "sha512-xbHV+5OMhIXrtfweeDAXO/HN69fn+bSUZtns6hbMgWsAK8t3hYyhQRzUeFJxrS0tApG4X9NQxIQ6mOmjZwz/rA==",
"dev": true
},
"@wikimedia/mw-node-qunit": {
diff --git a/package.json b/package.json
index 6dd3dbde9..f77cca6b8 100644
--- a/package.json
+++ b/package.json
@@ -39,8 +39,8 @@
"@wdio/local-runner": "7.4.6",
"@wdio/mocha-framework": "7.30.2",
"@wdio/sync": "7.4.6",
- "@wikimedia/codex": "0.11.0",
- "@wikimedia/codex-icons": "0.11.0",
+ "@wikimedia/codex": "0.14.0",
+ "@wikimedia/codex-icons": "0.14.0",
"@wikimedia/mw-node-qunit": "7.0.0",
"babel-loader": "8.0.4",
"browserslist-config-wikimedia": "0.2.0",
diff --git a/resources/dist/index.js b/resources/dist/index.js
index 24e2c9442..36cd466f0 100644
Binary files a/resources/dist/index.js and b/resources/dist/index.js differ
diff --git a/resources/dist/index.js.map.json b/resources/dist/index.js.map.json
index 3403433b9..433d6edc5 100644
Binary files a/resources/dist/index.js.map.json and b/resources/dist/index.js.map.json differ
diff --git a/src/ui/index.less b/src/ui/index.less
index 0033473ee..45981f625 100644
--- a/src/ui/index.less
+++ b/src/ui/index.less
@@ -9,3 +9,15 @@
position: absolute;
top: -1000px;
}
+
+.cdx-button.cdx-button--icon-only {
+ // Hide text in icon only buttons
+ span + span {
+ .mixin-screen-reader-text();
+ }
+}
+
+// FIXME: Remove after Iac69f7b14b732b0bbaa6ba265379ed4c4cdb3f7e is merged
+.cdx-button--fake-button {
+ justify-content: center;
+}
diff --git a/src/ui/renderer.js b/src/ui/renderer.js
index 4b5646a15..1631f7439 100644
--- a/src/ui/renderer.js
+++ b/src/ui/renderer.js
@@ -306,10 +306,10 @@ export function bindBehavior( preview, behavior ) {
preview.el.addEventListener( 'click', behavior.click );
- const icon = preview.el.querySelector( '.mwe-popups-settings-icon' );
- if ( icon ) {
- icon.href = behavior.settingsUrl;
- icon.addEventListener( 'click', ( event ) => {
+ const button = preview.el.querySelector( '.mwe-popups-settings-button' );
+ if ( button ) {
+ button.href = behavior.settingsUrl;
+ button.addEventListener( 'click', ( event ) => {
event.stopPropagation();
behavior.showSettings( event );
diff --git a/src/ui/templates/pagePreview/pagePreview.js b/src/ui/templates/pagePreview/pagePreview.js
index a142f90a4..5527ce564 100644
--- a/src/ui/templates/pagePreview/pagePreview.js
+++ b/src/ui/templates/pagePreview/pagePreview.js
@@ -3,7 +3,7 @@
*/
import { renderPopup } from '../popup/popup';
-import { createNodeFromTemplate } from '../templateUtil';
+import { escapeHTML, createNodeFromTemplate } from '../templateUtil';
const defaultExtractWidth = 215;
const templateHTML = `
@@ -11,8 +11,9 @@ const templateHTML = `
@@ -37,9 +38,14 @@ export function renderPagePreview(
extract.setAttribute( 'dir', model.languageDirection );
extract.setAttribute( 'lang', model.languageCode );
- el.querySelector( '.mwe-popups-settings-icon' )
+ el.querySelector( '.mwe-popups-settings-button' )
.setAttribute( 'title', linkTitle );
+ // Set label on settings icon button
+ const labelText = escapeHTML( mw.msg( 'popups-settings-icon-gear-title' ) );
+ const label = el.querySelector( '.mwe-popups-settings-button-label' );
+ label.textContent = labelText;
+
if ( thumbnail ) {
el.querySelector( '.mwe-popups-discreet' ).appendChild( thumbnail.el );
} else {
diff --git a/src/ui/templates/popup/popup.less b/src/ui/templates/popup/popup.less
index 5e4ce9f07..f1daaca34 100644
--- a/src/ui/templates/popup/popup.less
+++ b/src/ui/templates/popup/popup.less
@@ -62,25 +62,12 @@
}
}
- .mwe-popups-settings-icon {
- display: block;
+ .mwe-popups-settings-button {
float: right; // positions icon near bottom right corner
- border-radius: @border-radius-base;
- opacity: 0.67;
- transition: background-color 100ms, opacity 100ms;
-
- &:hover {
- // TODO: Replace by `@background-color-button-quiet--hover`
- // as soon as available in mediawiki.skin.variables.
- background-color: rgba( 0, 24, 73, 0.027 );
- }
-
- &:active {
- // TODO: Replace by `@background-color-button-quiet--active`
- // as soon as available in mediawiki.skin.variables.
- background-color: rgba( 0, 24, 73, 0.082 );
- opacity: 1;
- }
+ pointer-events: auto; // Overrides pointer-events: none on footer to ensure the button is interactive
+ // !important needed to override 'responsive' button styles on smaller viewports defined in Vector's Button.less
+ min-width: 32px !important; /* stylelint-disable-line declaration-no-important */
+ min-height: 32px !important; /* stylelint-disable-line declaration-no-important */
}
.mwe-popups-extract {
@@ -409,7 +396,7 @@
/* @noflip */
right: 0;
- .mwe-popups-settings-icon {
+ .mwe-popups-settings-button {
/* @noflip */
float: left;
}
diff --git a/src/ui/templates/referencePreview/referencePreview.js b/src/ui/templates/referencePreview/referencePreview.js
index 4f3fa00b0..05fda7df1 100644
--- a/src/ui/templates/referencePreview/referencePreview.js
+++ b/src/ui/templates/referencePreview/referencePreview.js
@@ -106,12 +106,15 @@ export function renderReferencePreview(
// TODO: Remove when not in Beta any more
if ( !mw.config.get( 'wgPopupsReferencePreviewsBetaFeature' ) ) {
// TODO: Do not remove this but move it up into the templateHTML constant!
- const settingsIconLink = document.createElement( 'a' );
- settingsIconLink.classList.add( 'mwe-popups-settings-icon' );
- const settingsIconLabel = document.createElement( 'span' );
- settingsIconLabel.classList.add( 'mw-ui-icon', 'mw-ui-icon-element', 'mw-ui-icon-small', 'mw-ui-icon-settings' );
- settingsIconLink.append( settingsIconLabel );
- el.querySelector( '.mwe-popups-settings' ).appendChild( settingsIconLink );
+ const settingsButton = document.createElement( 'button' );
+ settingsButton.classList.add( 'cdx-button', 'cdx-button--fake-button', 'cdx-button--fake-button--enabled', 'cdx-button--weight-quiet', 'cdx-button--icon-only', 'mwe-popups-settings-button' );
+ const settingsIcon = document.createElement( 'span' );
+ settingsIcon.classList.add( 'mw-ui-icon', 'mw-ui-icon-small', 'mw-ui-icon-settings' );
+ const settingsButtonLabel = document.createElement( 'span' );
+ settingsButtonLabel.textContent = mw.msg( 'popups-settings-icon-gear-title' );
+ settingsButton.append( settingsIcon );
+ settingsButton.append( settingsButtonLabel );
+ el.querySelector( '.mwe-popups-settings' ).appendChild( settingsButton );
} else {
// Change the styling when there is no content in the footer (to prevent empty space)
el.querySelector( '.mwe-popups-container' ).classList.add( 'footer-empty' );
diff --git a/src/ui/templates/settingsDialog/settingsDialog.js b/src/ui/templates/settingsDialog/settingsDialog.js
index 527af7c06..3da9d2cbd 100644
--- a/src/ui/templates/settingsDialog/settingsDialog.js
+++ b/src/ui/templates/settingsDialog/settingsDialog.js
@@ -58,12 +58,15 @@ export function renderSettingsDialog( model ) {
${heading}