diff --git a/.storybook/icons.less b/.storybook/icons.less
index 4c1c710..9da1d46 100644
--- a/.storybook/icons.less
+++ b/.storybook/icons.less
@@ -18,6 +18,22 @@
url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2220%22 height=%2220%22 viewBox=%220 0 20 20%22%3E%3Ctitle%3Etray%3C/title%3E%3Cpath d=%22M3 1a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2zm14 12h-4l-1 2H8l-1-2H3V3h14z%22/%3E%3C/svg%3E");
}
+.mw-ui-icon-add:before {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Ctitle%3Elanguage%3C/title%3E%3Cg fill='%2354595d'%3E%3Cpath d='M11 9V4H9v5H4v2h5v5h2v-5h5V9z'/%3E%3C/g%3E%3C/svg%3E");
+}
+
+.mw-ui-icon-add-invert:before {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Ctitle%3Elanguage%3C/title%3E%3Cg fill='white'%3E%3Cpath d='M11 9V4H9v5H4v2h5v5h2v-5h5V9z'/%3E%3C/g%3E%3C/svg%3E");
+}
+
+.mw-ui-icon-add-progressive:before {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Ctitle%3Elanguage%3C/title%3E%3Cg fill='%23447ff5'%3E%3Cpath d='M11 9V4H9v5H4v2h5v5h2v-5h5V9z'/%3E%3C/g%3E%3C/svg%3E");
+}
+
+.mw-ui-icon-add-destructive:before {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Ctitle%3Elanguage%3C/title%3E%3Cg fill='%23ff4242'%3E%3Cpath d='M11 9V4H9v5H4v2h5v5h2v-5h5V9z'/%3E%3C/g%3E%3C/svg%3E");
+}
+
.uls-trigger {
background-image: linear-gradient(transparent,transparent),
url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2220%22 height=%2220%22 viewBox=%220 0 20 20%22%3E %3Ctitle%3E language %3C/title%3E %3Cpath d=%22M20 18h-1.44a.61.61 0 0 1-.4-.12.81.81 0 0 1-.23-.31L17 15h-5l-1 2.54a.77.77 0 0 1-.22.3.59.59 0 0 1-.4.14H9l4.55-11.47h1.89zm-3.53-4.31L14.89 9.5a11.62 11.62 0 0 1-.39-1.24q-.09.37-.19.69l-.19.56-1.58 4.19zm-6.3-1.58a13.43 13.43 0 0 1-2.91-1.41 11.46 11.46 0 0 0 2.81-5.37H12V4H7.31a4 4 0 0 0-.2-.56C6.87 2.79 6.6 2 6.6 2l-1.47.5s.4.89.6 1.5H0v1.33h2.15A11.23 11.23 0 0 0 5 10.7a17.19 17.19 0 0 1-5 2.1q.56.82.87 1.38a23.28 23.28 0 0 0 5.22-2.51 15.64 15.64 0 0 0 3.56 1.77zM3.63 5.33h4.91a8.11 8.11 0 0 1-2.45 4.45 9.11 9.11 0 0 1-2.46-4.45z%22/%3E %3C/svg%3E") !important;
diff --git a/includes/Hooks.php b/includes/Hooks.php
index d14f168..870edd0 100644
--- a/includes/Hooks.php
+++ b/includes/Hooks.php
@@ -227,7 +227,7 @@ class Hooks {
* @param string $name
* @return string of HTML
*/
- public static function makeButtonIcon( $name ) {
+ public static function makeIcon( $name ) {
// Html::makeLink will pass this through rawElement
return '';
}
@@ -256,7 +256,7 @@ class Hooks {
if ( $hideText ) {
$item['link-class'][] = 'mw-ui-icon mw-ui-icon-element mw-ui-icon-' . $icon;
} else {
- $item['link-html'] = self::makeButtonIcon( $icon );
+ $item['link-html'] = self::makeIcon( $icon );
}
}
$content_navigation[$menu][$key] = $item;
diff --git a/includes/SkinVector.php b/includes/SkinVector.php
index 8f3c5e7..8a1c8d9 100644
--- a/includes/SkinVector.php
+++ b/includes/SkinVector.php
@@ -516,7 +516,7 @@ class SkinVector extends SkinMustache {
'label' => $label,
// ext.uls.interface attaches click handler to this selector.
'checkbox-class' => ' mw-interlanguage-selector ',
- 'html-vector-heading-icon' => Hooks::makeButtonIcon( 'wikimedia-language' ),
+ 'html-vector-heading-icon' => Hooks::makeIcon( 'wikimedia-language' ),
'heading-class' =>
' vector-menu-heading ' .
' mw-ui-button mw-ui-quiet'
diff --git a/package-lock.json b/package-lock.json
index bfd46b8..8f7ec84 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2329,6 +2329,12 @@
"integrity": "sha512-H2MbvBt7DTROqm6kCRNdK6nUZuBvSYjq/7k01ZI5/uR9mj8FzxsMQcH4joh8kFVQ2LpDPXNsaPq/P5hqIDtSAw==",
"dev": true
},
+ "@wikimedia/wvui": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@wikimedia/wvui/-/wvui-0.3.0.tgz",
+ "integrity": "sha512-RiVvKReEn7KtvPzYghLr+e5FOYh71BWzaT1/uG/A2d8D6QM+0U5arF0MKJnB6drNvkQZPM/YcWu/IbV3zItcOA==",
+ "dev": true
+ },
"@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
diff --git a/package.json b/package.json
index 53f068c..49dcc76 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"@types/mustache": "4.0.1",
"@types/node-fetch": "2.5.7",
"@wikimedia/types-wikimedia": "0.2.0",
+ "@wikimedia/wvui": "0.3.0",
"babel-loader": "8.0.6",
"bundlesize": "0.18.1",
"eslint-config-wikimedia": "0.20.0",
diff --git a/stories/ButtonsAndIcons.stories.js b/stories/ButtonsAndIcons.stories.js
new file mode 100644
index 0000000..114bbbf
--- /dev/null
+++ b/stories/ButtonsAndIcons.stories.js
@@ -0,0 +1,145 @@
+import wvui from '@wikimedia/wvui';
+import Vue from 'vue';
+import '@wikimedia/wvui/dist/wvui.css';
+const wvuiIconAdd = 'M11 9V4H9v5H4v2h5v5h2v-5h5V9z';
+
+export default {
+ title: 'Icon and Buttons'
+};
+
+/**
+ *
+ * @typedef {Object} ButtonProps
+ * @property {string} type
+ * @property {string} action
+ */
+/**
+ * @param {ButtonProps} props
+ * @param {string} text
+ * @return {string}
+ */
+function makeButtonLegacy( props, text ) {
+ let typeClass = '';
+ let iconClass = 'mw-ui-icon-add';
+ switch ( props.type ) {
+ case 'quiet':
+ typeClass += ' mw-ui-quiet';
+ break;
+ }
+ switch ( props.action ) {
+ case 'progressive':
+ typeClass += ' mw-ui-progressive';
+ iconClass += '-progressive';
+ break;
+ case 'destructive':
+ typeClass += ' mw-ui-destructive';
+ iconClass += '-destructive';
+ break;
+ }
+ if ( props.type === 'primary' ) {
+ iconClass = 'mw-ui-icon-add-invert';
+ }
+ return ``;
+}
+
+/**
+ * @param {ButtonProps} props
+ * @param {string} text
+ * @param {string} icon
+ * @return {string}
+ */
+function makeButton( props, text, icon ) {
+ const el = document.createElement( 'div' );
+ const vm = new Vue( {
+ el,
+ render: function ( createElement ) {
+ return createElement( wvui.WvuiButton, {
+ props
+ }, [
+ createElement( wvui.WvuiIcon, {
+ props: {
+ icon
+ }
+ } ),
+ text
+ ] );
+ }
+ } );
+ return `
+
+ ${makeButtonLegacy( props, text )} |
+ ${vm.$el.outerHTML} |
+
`;
+}
+
+/**
+ * @return {string}
+ */
+function makeIcon() {
+ return `
+
+
+
+ |
+ N/A |
+
+
+
+
+ |
+ N/A |
+
`;
+}
+
+/**
+ *
+ * @param {string[]} btns
+ * @return {string}
+ */
+function makeButtons( btns ) {
+ return `
+
+
+ Legacy |
+ WVUI |
+
+ ${btns.join( '\n' )}
+
+
`;
+}
+
+/**
+ * @return {string}
+ */
+export const Button = () => makeButtons( [
+ makeButton( {
+ action: 'default',
+ type: 'quiet'
+ }, 'Quiet button', wvuiIconAdd ),
+ makeButton( {
+ action: 'progressive',
+ type: 'quiet'
+ }, 'Quiet progressive', wvuiIconAdd ),
+ makeButton( {
+ action: 'destructive',
+ type: 'quiet'
+ }, 'Quiet destructive', wvuiIconAdd ),
+ makeButton( {
+ action: 'default',
+ type: 'normal'
+ }, 'Normal', wvuiIconAdd ),
+ makeButton( {
+ type: 'primary',
+ action: 'progressive'
+ }, 'Progressive primary', wvuiIconAdd ),
+ makeButton( {
+ type: 'primary',
+ action: 'destructive'
+ }, 'Destructive primary', wvuiIconAdd ),
+ makeIcon()
+] );
diff --git a/stories/LanguageButton.stories.data.js b/stories/LanguageButton.stories.data.js
index cfa8d9f..f530da2 100644
--- a/stories/LanguageButton.stories.data.js
+++ b/stories/LanguageButton.stories.data.js
@@ -1,7 +1,8 @@
/**
* @external MenuDefinition
*/
-import { placeholder, htmlUserLanguageAttributes, portletAfter } from './utils';
+import { placeholder, htmlUserLanguageAttributes,
+ makeIcon, portletAfter } from './utils';
/**
* @type {MenuDefinition}
@@ -12,8 +13,9 @@ export const languageData = {
class: 'mw-portlet-lang vector-menu-dropdown',
// mw-interlanguage-selector must be present to operate in ULS mode.
// icon classes and button classes
- 'heading-class': 'vector-menu-heading mw-interlanguage-selector ' +
- 'mw-ui-icon mw-ui-icon-before mw-ui-icon-wikimedia-language ' +
+ 'checkbox-class': 'mw-interlanguage-selector',
+ 'html-vector-heading-icon': makeIcon( 'wikimedia-language' ),
+ 'heading-class': 'vector-menu-heading ' +
'mw-ui-button mw-ui-quiet',
'html-tooltip': 'A message tooltip-p-lang must exist for this to appear',
label: '10 languages',
diff --git a/stories/LanguageButton.stories.js b/stories/LanguageButton.stories.js
index 89e2a66..0d1ce38 100644
--- a/stories/LanguageButton.stories.js
+++ b/stories/LanguageButton.stories.js
@@ -7,38 +7,4 @@ export default {
title: 'LanguageButton'
};
-// mw-page-container is needed to enable the 20x20 icon
-// mw-body-header can be removed when VectorLanguageInHeader is true and
-// old language inside portal in modern Vector is no longer supported.
-const CONTAINER_CLASS_MODERN_VECTOR = 'mw-body-header mw-page-container';
-
-/**
- * It allows us to support old and new renderings.
- *
- * @param {string|HTMLElement} htmlOrElement
- * @param {string} className of containing element
- * @return {HTMLElement}
- */
-const wrapLanguageButton = ( htmlOrElement, className ) => {
- const node = document.createElement( 'div' );
- node.setAttribute( 'class', className );
- if ( typeof htmlOrElement === 'string' ) {
- node.innerHTML = htmlOrElement;
- } else {
- node.appendChild( htmlOrElement );
- }
- return node;
-};
-
export const languageButton = () => mustache.render( vectorMenuTemplate, languageData );
-
-export const languageButtonWhenULSEnabled = () => wrapLanguageButton(
- wrapLanguageButton(
- wrapLanguageButton(
- mustache.render( vectorMenuTemplate, languageData ),
- 'vector-menu-hide-dropdown'
- ),
- CONTAINER_CLASS_MODERN_VECTOR
- ),
- 'client-js'
-);
diff --git a/stories/MenuDropdown.stories.data.js b/stories/MenuDropdown.stories.data.js
index 123283d..35abb73 100644
--- a/stories/MenuDropdown.stories.data.js
+++ b/stories/MenuDropdown.stories.data.js
@@ -12,7 +12,7 @@ export { vectorMenuTemplate };
*/
export const moreData = {
'is-dropdown': true,
- class: 'vector-menu-dropdown',
+ class: 'vector-menu-dropdown vector-menu-dropdown-noicon',
label: 'More',
id: 'p-cactions',
'html-user-language-attributes': htmlUserLanguageAttributes,
@@ -35,7 +35,7 @@ export const moreData = {
*/
export const variantsData = {
'is-dropdown': true,
- class: 'vector-menu-dropdown',
+ class: 'vector-menu-dropdown vector-menu-dropdown-noicon',
label: '新加坡简体',
id: 'p-variants',
'html-user-language-attributes': htmlUserLanguageAttributes,
diff --git a/stories/UserLinks.stories.data.js b/stories/UserLinks.stories.data.js
index d878f70..1d8a41f 100644
--- a/stories/UserLinks.stories.data.js
+++ b/stories/UserLinks.stories.data.js
@@ -83,6 +83,7 @@ const additionalUserMoreData = {
const userMoreHtmlItems = ( isAnon = true ) => mustache.render( userLinksMoreTemplate, {
'is-anon': isAnon,
+ 'is-create-account-allowed': isAnon,
'html-create-account': `Create account`,
'data-user-page': helperMakeMenuData( 'user-page', `
@@ -95,7 +96,7 @@ const userMoreHtmlItems = ( isAnon = true ) => mustache.render( userLinksMoreTem
const loggedInData = {
class: 'vector-user-menu vector-menu-dropdown vector-user-menu-logged-in',
'is-dropdown': true,
- 'heading-class': 'mw-ui-icon mw-ui-icon-element mw-ui-icon-wikimedia-userAvatar',
+ 'heading-class': 'mw-ui-button mw-ui-quiet mw-ui-icon mw-ui-icon-element mw-ui-icon-wikimedia-userAvatar',
'is-anon': false,
'html-after-portal': mustache.render( userLinksLogoutTemplate, {
htmlLogout: ``
@@ -105,7 +106,7 @@ const loggedInData = {
const loggedOutData = {
class: 'vector-user-menu vector-menu-dropdown vector-user-menu-logged-out',
'is-dropdown': true,
- 'heading-class': 'mw-ui-icon mw-ui-icon-element mw-ui-icon-wikimedia-ellipsis',
+ 'heading-class': 'mw-ui-button mw-ui-quiet mw-ui-icon mw-ui-icon-element mw-ui-icon-wikimedia-ellipsis',
'is-anon': true,
'html-before-portal': mustache.render( userLinksLoginTemplate, {
htmlCreateAccount: ``,
diff --git a/stories/types.js b/stories/types.js
index c5167c0..0b80363 100644
--- a/stories/types.js
+++ b/stories/types.js
@@ -57,6 +57,8 @@
* @property {string} id
* @property {string} label
* @property {string} html-items
+ * @property {string} [checkbox-class]
+ * @property {string} [html-vector-heading-icon]
* @property {string} [heading-class]
* @property {string} [html-tooltip]
* @property {string} [class] of menu
diff --git a/stories/utils.js b/stories/utils.js
index 9a5a28a..37665aa 100644
--- a/stories/utils.js
+++ b/stories/utils.js
@@ -2,6 +2,14 @@
* @external MenuDefinition
*/
+/**
+ * @param {string} name
+ * @return {string}
+ */
+function makeIcon( name ) {
+ return ``;
+}
+
/**
* @param {string} msg
* @param {number} [height=200]
@@ -64,6 +72,7 @@ function helperMakeMenuData( name, htmlItems, additionalData = {} ) {
}
export {
+ makeIcon,
placeholder,
htmlUserLanguageAttributes,
portletAfter,
diff --git a/tsconfig.json b/tsconfig.json
index 0103319..2e8b45f 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -9,6 +9,7 @@
"noImplicitReturns": true,
"newLine": "lf",
"forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true,
"pretty": true,
"target": "es5",
"lib": [ "dom" ],