From 5f87af127558c5104e7983cc20997f5d670fafa6 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Fri, 7 May 2021 20:49:53 +0100 Subject: [PATCH 01/38] Add Tooltip component to common Will be used to provide backwards compatibility when we switch to CSS tooltips. All other methods of creating tooltips are deprecated and this component-based method should be used instead. --- js/src/common/components/Tooltip.tsx | 97 ++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 js/src/common/components/Tooltip.tsx diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx new file mode 100644 index 0000000000..04dcf1f956 --- /dev/null +++ b/js/src/common/components/Tooltip.tsx @@ -0,0 +1,97 @@ +import Component, { ComponentAttrs } from '../Component'; +import type Mithril from 'mithril'; +import classList from '../utils/classList'; + +export interface TooltipAttrs extends ComponentAttrs { + /** + * Tooltip textual content. + */ + text: string; + /** + * If inline, uses a `` container, else uses a `
`. + * + * Default: `false`. + */ + inline?: boolean; + /** + * Manually show tooltip. `false` will show based on cursor events. + * + * Default: `false`. + */ + tooltipVisible?: boolean; + /** + * Whether to show on focus. + * + * Default: `true`. + */ + showOnFocus?: boolean; + /** + * Tooltip position around element. + */ + position?: 'top' | 'bottom' | 'left' | 'right'; + /** + * Whether HTML content is allowed in the tooltip. + * + * **Warning:** this is a possible XSS attack vector. This option shouldn't + * be used wherever possible, and will not work when we migrate to CSS-only + * tooltips. + * + * @deprecated + */ + html?: boolean; +} + +/** + * The `Tooltip` component is used to create a tooltip for an element. It + * surrounds it with a div (or span) which has the required tooltip setup + * applied. + * + * You should use this for any tooltips you create to allow for backwards + * compatibility when we switch to pure CSS tooltips instead of Bootstrap + * tooltips. + * + * @example Correct use of Tooltip component + * + * + * + * + * @example Correct use of Tooltip component + * + *
3 replies
+ *
+ */ +export default class Tooltip extends Component { + view(vnode: Mithril.Vnode) { + const { children } = vnode; + + const { + text, + inline, + tooltipVisible, + showOnFocus = true, + position = 'top', + // This will have no effect when switching to CSS tooltips + html = false, + ...attrs + } = this.attrs; + + attrs['aria-label'] = text; + + // https://getbootstrap.com/docs/3.3/javascript/#tooltips-options + this.$.tooltip({ + html, + placement: position, + title: text, + // Fancy "hack" to assemble the trigger string + trigger: classList('hover', [showOnFocus && 'focus']), + }); + + if (inline) { + return {children}; + } + + return
{children}
; + } +} From c68fd51036aca8c38daf2c7894cb91f5e934bbfa Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Fri, 7 May 2021 20:50:29 +0100 Subject: [PATCH 02/38] Export Tooltip component --- js/src/common/compat.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/common/compat.js b/js/src/common/compat.js index c640038caa..5fe1017a95 100644 --- a/js/src/common/compat.js +++ b/js/src/common/compat.js @@ -62,6 +62,7 @@ import GroupBadge from './components/GroupBadge'; import TextEditor from './components/TextEditor'; import TextEditorButton from './components/TextEditorButton'; import EditUserModal from './components/EditUserModal'; +import Tooltip from './components/Tooltip'; import Model from './Model'; import Application from './Application'; import fullTime from './helpers/fullTime'; @@ -141,6 +142,7 @@ export default { 'components/GroupBadge': GroupBadge, 'components/TextEditor': TextEditor, 'components/TextEditorButton': TextEditorButton, + 'components/Tooltip': Tooltip, 'components/EditUserModal': EditUserModal, Model: Model, Application: Application, From 7d93c9d87db9ac71c9125cf7858cb5f0e28ffb35 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 18:17:50 +0100 Subject: [PATCH 03/38] WIP --- js/src/common/components/Badge.js | 15 ++++++++------ js/src/common/components/Tooltip.tsx | 31 +++++++++++++++++++++------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/js/src/common/components/Badge.js b/js/src/common/components/Badge.js index d9267fdf32..fbe05f7cd7 100644 --- a/js/src/common/components/Badge.js +++ b/js/src/common/components/Badge.js @@ -1,6 +1,6 @@ import Component from '../Component'; +import Tooltip from '../Tooltip'; import icon from '../helpers/icon'; -import extract from '../utils/extract'; /** * The `Badge` component represents a user/discussion badge, indicating some @@ -18,13 +18,16 @@ import extract from '../utils/extract'; export default class Badge extends Component { view() { const attrs = Object.assign({}, this.attrs); - const type = extract(attrs, 'type'); - const iconName = extract(attrs, 'icon'); - attrs.className = 'Badge ' + (type ? 'Badge--' + type : '') + ' ' + (attrs.className || ''); - attrs.title = extract(attrs, 'label') || ''; + const { type, icon: iconName, title = '' } = attrs; - return {iconName ? icon(iconName, { className: 'Badge-icon' }) : m.trust(' ')}; + const className = classList('Badge', [type && `Badge--${type}`], attrs.className); + + return ( + + {iconName ? icon(iconName, { className: 'Badge-icon' }) : m.trust(' ')} + + ); } oncreate(vnode) { diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx index 04dcf1f956..a5485062f7 100644 --- a/js/src/common/components/Tooltip.tsx +++ b/js/src/common/components/Tooltip.tsx @@ -63,9 +63,30 @@ export interface TooltipAttrs extends ComponentAttrs { * */ export default class Tooltip extends Component { - view(vnode: Mithril.Vnode) { + view(vnode) { const { children } = vnode; + // We remove these to get the remaining attrs to pass to the DOM element + const { text, inline, tooltipVisible, showOnFocus, position, html, ...attrs } = this.attrs; + + if (inline) { + return {children}; + } + + return
{children}
; + } + + oncreate(vnode: Mithril.VnodeDOM) { + super.oncreate(vnode); + + this.createTooltip(); + } + + onupdate(vnode: Mithril.VnodeDOM) { + this.createTooltip(); + } + + private createTooltip() { const { text, inline, @@ -77,7 +98,7 @@ export default class Tooltip extends Component { ...attrs } = this.attrs; - attrs['aria-label'] = text; + this.attrs['aria-label'] = text; // https://getbootstrap.com/docs/3.3/javascript/#tooltips-options this.$.tooltip({ @@ -87,11 +108,5 @@ export default class Tooltip extends Component { // Fancy "hack" to assemble the trigger string trigger: classList('hover', [showOnFocus && 'focus']), }); - - if (inline) { - return {children}; - } - - return
{children}
; } } From a38c3f6bb1521311ba81ed823848c562fb863633 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:31:24 +0100 Subject: [PATCH 04/38] Fix import --- js/src/common/components/Badge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/common/components/Badge.js b/js/src/common/components/Badge.js index fbe05f7cd7..0b260850f3 100644 --- a/js/src/common/components/Badge.js +++ b/js/src/common/components/Badge.js @@ -1,5 +1,5 @@ +import Tooltip from './Tooltip'; import Component from '../Component'; -import Tooltip from '../Tooltip'; import icon from '../helpers/icon'; /** From 983577301f636ce5dec0e75d03e121d98a49a395 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:32:43 +0100 Subject: [PATCH 05/38] Add missing import --- js/src/common/components/Badge.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/src/common/components/Badge.js b/js/src/common/components/Badge.js index 0b260850f3..8d077b3aca 100644 --- a/js/src/common/components/Badge.js +++ b/js/src/common/components/Badge.js @@ -1,6 +1,7 @@ import Tooltip from './Tooltip'; import Component from '../Component'; import icon from '../helpers/icon'; +import classList from '../utils/classList'; /** * The `Badge` component represents a user/discussion badge, indicating some From 80fc860720ecd120d05f489072386c983698ac1e Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:54:13 +0100 Subject: [PATCH 06/38] Move Tooltip jQuery helper types to separate typing file --- js/@types/tooltips/index.d.ts | 68 +++++++++++++++++++++++++++++++++++ js/shims.d.ts | 11 ++---- 2 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 js/@types/tooltips/index.d.ts diff --git a/js/@types/tooltips/index.d.ts b/js/@types/tooltips/index.d.ts new file mode 100644 index 0000000000..35c38ac89f --- /dev/null +++ b/js/@types/tooltips/index.d.ts @@ -0,0 +1,68 @@ +/** + * Selection of options accepted by [Bootstrap's tooltips](https://getbootstrap.com/docs/3.3/javascript/#tooltips-options). + * + * --- + * + * Not all options are present from Bootstrap to discourage the use of options + * that will be deprecated in the future. + * + * More commonly used options that will be deprecated remain, but are marked as + * such. + * + * @see https://getbootstrap.com/docs/3.3/javascript/#tooltips-options + */ +export interface TooltipOptions { + /** + * Whether HTML content is allowed in the tooltip. + * + * --- + * + * **Warning:** this is a possible XSS attack vector. This option shouldn't + * be used wherever possible, and will not work when we migrate to CSS-only + * tooltips. + * + * @deprecated + */ + html?: boolean; + /** + * Tooltip position around the target element. + */ + placement?: 'top' | 'bottom' | 'left' | 'right'; + /** + * Sets the delay between a trigger state occurring and the tooltip appearing + * on-screen. + * + * --- + * + * **Warning:** this option will be removed when we switch to CSS-only + * tooltips. + * + * @deprecated + */ + delay?: number; + /** + * Value used if no `title` attribute is present on the HTML element. + * + * If a function is given, it will be called with its `this` reference set to + * the element that the tooltip is attached to. + */ + title?: string; + /** + * How the tooltip is triggered. + * + * Either on `hover`, on `hover focus` (either of the two). + * + * --- + * + * **Warning:** `manual`, `click` and `focus` on its own are deprecated options + * which will not be supported in the future. + */ + trigger?: 'hover' | 'hover focus'; +} + +/** + * Creates a tooltip on a jQuery element reference. + * + * Returns the same jQuery reference to allow for method chaining. + */ +export type TooltipJQueryFunction = (tooltipOptions?: TooltipOptions) => JQuery; diff --git a/js/shims.d.ts b/js/shims.d.ts index 94fcf2c5fd..153944961a 100644 --- a/js/shims.d.ts +++ b/js/shims.d.ts @@ -8,6 +8,8 @@ import * as _$ from 'jquery'; // Globals from flarum/core import Application from './src/common/Application'; +import type { TooltipJQueryFunction } from './@types/tooltips/index'; + /** * flarum/core exposes several extensions globally: * @@ -25,14 +27,7 @@ declare global { // Extend JQuery with our custom functions, defined with $.fn interface JQuery { - /** - * Creates a tooltip on a jQuery element reference. - * - * Optionally accepts placement and delay options. - * - * Returns the same reference to allow for method chaining. - */ - tooltip: (tooltipOptions?: { placement?: 'top' | 'bottom' | 'left' | 'right'; delay?: number }) => JQuery; + tooltip: TooltipJQueryFunction; } } From fdb40e5779c39633831989c813ec362ec69d973e Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:58:59 +0100 Subject: [PATCH 07/38] Add `delay` attr, update docblocks --- js/src/common/components/Tooltip.tsx | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx index a5485062f7..47a7588687 100644 --- a/js/src/common/components/Tooltip.tsx +++ b/js/src/common/components/Tooltip.tsx @@ -1,6 +1,7 @@ import Component, { ComponentAttrs } from '../Component'; import type Mithril from 'mithril'; import classList from '../utils/classList'; +import { TooltipOptions } from '../../../@types/tooltips'; export interface TooltipAttrs extends ComponentAttrs { /** @@ -39,6 +40,16 @@ export interface TooltipAttrs extends ComponentAttrs { * @deprecated */ html?: boolean; + /** + * Sets the delay between a trigger state occurring and the tooltip appearing + * on-screen. + * + * **Warning:** this option will be removed when we switch to CSS-only + * tooltips. + * + * @deprecated + */ + delay?: number; } /** @@ -50,15 +61,15 @@ export interface TooltipAttrs extends ComponentAttrs { * compatibility when we switch to pure CSS tooltips instead of Bootstrap * tooltips. * - * @example Correct use of Tooltip component + * @example Basic usage * * * * - * @example Correct use of Tooltip component - * + * @example Use of `position` and `showOnFocus` attrs + * *
3 replies
*
*/ @@ -67,7 +78,7 @@ export default class Tooltip extends Component { const { children } = vnode; // We remove these to get the remaining attrs to pass to the DOM element - const { text, inline, tooltipVisible, showOnFocus, position, html, ...attrs } = this.attrs; + const { text, inline, tooltipVisible, showOnFocus, position, html, delay, ...attrs } = this.attrs; if (inline) { return {children}; @@ -93,6 +104,7 @@ export default class Tooltip extends Component { tooltipVisible, showOnFocus = true, position = 'top', + delay, // This will have no effect when switching to CSS tooltips html = false, ...attrs @@ -101,12 +113,13 @@ export default class Tooltip extends Component { this.attrs['aria-label'] = text; // https://getbootstrap.com/docs/3.3/javascript/#tooltips-options - this.$.tooltip({ + this.$().tooltip({ html, + delay, placement: position, title: text, // Fancy "hack" to assemble the trigger string - trigger: classList('hover', [showOnFocus && 'focus']), + trigger: classList('hover', [showOnFocus && 'focus']) as TooltipOptions['trigger'], }); } } From b475f5ccef259503f3e48f0d76f9408fd2937eca Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:28:58 +0000 Subject: [PATCH 08/38] Remove undeeded `index` on import --- js/shims.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/shims.d.ts b/js/shims.d.ts index 153944961a..9a1d9dd822 100644 --- a/js/shims.d.ts +++ b/js/shims.d.ts @@ -8,7 +8,7 @@ import * as _$ from 'jquery'; // Globals from flarum/core import Application from './src/common/Application'; -import type { TooltipJQueryFunction } from './@types/tooltips/index'; +import type { TooltipJQueryFunction } from './@types/tooltips'; /** * flarum/core exposes several extensions globally: From 6e13274bdae21d8ecd09d324c42a400c74b4115c Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:29:51 +0000 Subject: [PATCH 09/38] Add support for `destroy` option in tooltip function typings --- js/@types/tooltips/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/@types/tooltips/index.d.ts b/js/@types/tooltips/index.d.ts index 35c38ac89f..e3d26bbe43 100644 --- a/js/@types/tooltips/index.d.ts +++ b/js/@types/tooltips/index.d.ts @@ -11,7 +11,7 @@ * * @see https://getbootstrap.com/docs/3.3/javascript/#tooltips-options */ -export interface TooltipOptions { +export interface TooltipCreationOptions { /** * Whether HTML content is allowed in the tooltip. * @@ -65,4 +65,4 @@ export interface TooltipOptions { * * Returns the same jQuery reference to allow for method chaining. */ -export type TooltipJQueryFunction = (tooltipOptions?: TooltipOptions) => JQuery; +export type TooltipJQueryFunction = (tooltipOptions?: TooltipCreationOptions | 'destroy') => JQuery; From 21aa09282673c1b9f2b68c2301e6384cc4585d5d Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:34:07 +0000 Subject: [PATCH 10/38] Update type import --- js/src/common/components/Tooltip.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx index 47a7588687..eb7707058d 100644 --- a/js/src/common/components/Tooltip.tsx +++ b/js/src/common/components/Tooltip.tsx @@ -1,7 +1,7 @@ import Component, { ComponentAttrs } from '../Component'; import type Mithril from 'mithril'; import classList from '../utils/classList'; -import { TooltipOptions } from '../../../@types/tooltips'; +import { TooltipCreationOptions } from '../../../@types/tooltips'; export interface TooltipAttrs extends ComponentAttrs { /** @@ -119,7 +119,7 @@ export default class Tooltip extends Component { placement: position, title: text, // Fancy "hack" to assemble the trigger string - trigger: classList('hover', [showOnFocus && 'focus']) as TooltipOptions['trigger'], + trigger: classList('hover', [showOnFocus && 'focus']) as TooltipCreationOptions['trigger'], }); } } From 4e4f8989ed55f9963d51591254026bf263dd7a38 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:35:27 +0000 Subject: [PATCH 11/38] Recreate tooltip inside `onupdate` if `text` attr has changed --- js/src/common/components/Tooltip.tsx | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx index eb7707058d..006d860d9b 100644 --- a/js/src/common/components/Tooltip.tsx +++ b/js/src/common/components/Tooltip.tsx @@ -74,8 +74,16 @@ export interface TooltipAttrs extends ComponentAttrs { *
*/ export default class Tooltip extends Component { + /** + * Contains the old tooltip text. + * + * Used to determine whether the tooltip should be recreated. + */ + private oldText: string = ''; + view(vnode) { const { children } = vnode; + console.log(this.attrs); // We remove these to get the remaining attrs to pass to the DOM element const { text, inline, tooltipVisible, showOnFocus, position, html, delay, ...attrs } = this.attrs; @@ -90,24 +98,29 @@ export default class Tooltip extends Component { oncreate(vnode: Mithril.VnodeDOM) { super.oncreate(vnode); + this.oldText = this.attrs.text; + this.createTooltip(); } onupdate(vnode: Mithril.VnodeDOM) { - this.createTooltip(); + // In case the `text` attr was updated, we need to recreate the tooltip + if (this.attrs.text !== this.oldText) { + this.oldText = this.attrs.text; + + this.$().tooltip('destroy'); + this.createTooltip(); + } } private createTooltip() { const { text, - inline, - tooltipVisible, showOnFocus = true, position = 'top', delay, // This will have no effect when switching to CSS tooltips html = false, - ...attrs } = this.attrs; this.attrs['aria-label'] = text; From ba0b52893d7a1baa2d197467cc7538928f002ddc Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:52:18 +0000 Subject: [PATCH 12/38] Rewrite Badge to use Tooltip component; remove console.logs --- js/src/common/components/Badge.js | 28 +++++++++++++++++----------- js/src/common/components/Tooltip.tsx | 1 - 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/js/src/common/components/Badge.js b/js/src/common/components/Badge.js index 8d077b3aca..2771149250 100644 --- a/js/src/common/components/Badge.js +++ b/js/src/common/components/Badge.js @@ -2,6 +2,7 @@ import Tooltip from './Tooltip'; import Component from '../Component'; import icon from '../helpers/icon'; import classList from '../utils/classList'; +import extractText from '../utils/extractText'; /** * The `Badge` component represents a user/discussion badge, indicating some @@ -18,22 +19,27 @@ import classList from '../utils/classList'; */ export default class Badge extends Component { view() { - const attrs = Object.assign({}, this.attrs); - - const { type, icon: iconName, title = '' } = attrs; + const { type, icon: iconName, label, ...attrs } = this.attrs; const className = classList('Badge', [type && `Badge--${type}`], attrs.className); + const tooltipText = extractText(label); + + const iconChild = iconName ? icon(iconName, { className: 'Badge-icon' }) : m.trust(' '); + + const badgeAttrs = { + className, + ...attrs, + }; + + // If we don't have a tooltip label, don't render the tooltip component. + if (typeof tooltipText !== 'string') { + return
{iconChild}
; + } return ( - - {iconName ? icon(iconName, { className: 'Badge-icon' }) : m.trust(' ')} + + {iconChild} ); } - - oncreate(vnode) { - super.oncreate(vnode); - - if (this.attrs.label) this.$().tooltip(); - } } diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx index 006d860d9b..6061a35e33 100644 --- a/js/src/common/components/Tooltip.tsx +++ b/js/src/common/components/Tooltip.tsx @@ -83,7 +83,6 @@ export default class Tooltip extends Component { view(vnode) { const { children } = vnode; - console.log(this.attrs); // We remove these to get the remaining attrs to pass to the DOM element const { text, inline, tooltipVisible, showOnFocus, position, html, delay, ...attrs } = this.attrs; From ff17c09e469a613cef593bc4a0fc463b858b361e Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 8 May 2021 23:53:14 +0000 Subject: [PATCH 13/38] Simplify Tooltip component to use `title` attr --- js/src/common/components/Tooltip.tsx | 35 ++++++++-------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx index 6061a35e33..90de7f5a20 100644 --- a/js/src/common/components/Tooltip.tsx +++ b/js/src/common/components/Tooltip.tsx @@ -74,13 +74,6 @@ export interface TooltipAttrs extends ComponentAttrs { * */ export default class Tooltip extends Component { - /** - * Contains the old tooltip text. - * - * Used to determine whether the tooltip should be recreated. - */ - private oldText: string = ''; - view(vnode) { const { children } = vnode; @@ -88,33 +81,28 @@ export default class Tooltip extends Component { const { text, inline, tooltipVisible, showOnFocus, position, html, delay, ...attrs } = this.attrs; if (inline) { - return {children}; + return ( + + {children} + + ); } - return
{children}
; + return ( +
+ {children} +
+ ); } oncreate(vnode: Mithril.VnodeDOM) { super.oncreate(vnode); - this.oldText = this.attrs.text; - this.createTooltip(); } - onupdate(vnode: Mithril.VnodeDOM) { - // In case the `text` attr was updated, we need to recreate the tooltip - if (this.attrs.text !== this.oldText) { - this.oldText = this.attrs.text; - - this.$().tooltip('destroy'); - this.createTooltip(); - } - } - private createTooltip() { const { - text, showOnFocus = true, position = 'top', delay, @@ -122,14 +110,11 @@ export default class Tooltip extends Component { html = false, } = this.attrs; - this.attrs['aria-label'] = text; - // https://getbootstrap.com/docs/3.3/javascript/#tooltips-options this.$().tooltip({ html, delay, placement: position, - title: text, // Fancy "hack" to assemble the trigger string trigger: classList('hover', [showOnFocus && 'focus']) as TooltipCreationOptions['trigger'], }); From 66393ec99ee3dea6760f233ab9b9029f964aae02 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sun, 9 May 2021 00:25:41 +0000 Subject: [PATCH 14/38] Run `extractText` inside Tooltip component --- js/src/common/components/Badge.js | 4 +--- js/src/common/components/Tooltip.tsx | 12 +++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/js/src/common/components/Badge.js b/js/src/common/components/Badge.js index 2771149250..74759aa27e 100644 --- a/js/src/common/components/Badge.js +++ b/js/src/common/components/Badge.js @@ -2,7 +2,6 @@ import Tooltip from './Tooltip'; import Component from '../Component'; import icon from '../helpers/icon'; import classList from '../utils/classList'; -import extractText from '../utils/extractText'; /** * The `Badge` component represents a user/discussion badge, indicating some @@ -22,7 +21,6 @@ export default class Badge extends Component { const { type, icon: iconName, label, ...attrs } = this.attrs; const className = classList('Badge', [type && `Badge--${type}`], attrs.className); - const tooltipText = extractText(label); const iconChild = iconName ? icon(iconName, { className: 'Badge-icon' }) : m.trust(' '); @@ -37,7 +35,7 @@ export default class Badge extends Component { } return ( - + {iconChild} ); diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx index 90de7f5a20..ae002f179a 100644 --- a/js/src/common/components/Tooltip.tsx +++ b/js/src/common/components/Tooltip.tsx @@ -2,12 +2,16 @@ import Component, { ComponentAttrs } from '../Component'; import type Mithril from 'mithril'; import classList from '../utils/classList'; import { TooltipCreationOptions } from '../../../@types/tooltips'; +import extractText from '../utils/extractText'; export interface TooltipAttrs extends ComponentAttrs { /** * Tooltip textual content. + * + * String arrays, like those provided by the translator, will be flattened + * into strings. */ - text: string; + text: string | string[]; /** * If inline, uses a `` container, else uses a `
`. * @@ -80,16 +84,18 @@ export default class Tooltip extends Component { // We remove these to get the remaining attrs to pass to the DOM element const { text, inline, tooltipVisible, showOnFocus, position, html, delay, ...attrs } = this.attrs; + const realText = Array.isArray(text) ? extractText(text) : text; + if (inline) { return ( - + {children} ); } return ( -
+
{children}
); From c05badcca232df8c1d56ace6ea69b0ae7d5c5892 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sun, 9 May 2021 00:44:01 +0000 Subject: [PATCH 15/38] Use `inline-block` instead of `` for inline Tooltip component --- js/src/common/components/Tooltip.tsx | 12 ++---------- less/common/Tooltip.less | 4 ++++ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/js/src/common/components/Tooltip.tsx b/js/src/common/components/Tooltip.tsx index ae002f179a..906ce124da 100644 --- a/js/src/common/components/Tooltip.tsx +++ b/js/src/common/components/Tooltip.tsx @@ -82,20 +82,12 @@ export default class Tooltip extends Component { const { children } = vnode; // We remove these to get the remaining attrs to pass to the DOM element - const { text, inline, tooltipVisible, showOnFocus, position, html, delay, ...attrs } = this.attrs; + const { text, inline, tooltipVisible, showOnFocus, position, html, delay, className, class: classes, ...attrs } = this.attrs; const realText = Array.isArray(text) ? extractText(text) : text; - if (inline) { - return ( - - {children} - - ); - } - return ( -
+
{children}
); diff --git a/less/common/Tooltip.less b/less/common/Tooltip.less index 282c357363..7e7d014aa0 100644 --- a/less/common/Tooltip.less +++ b/less/common/Tooltip.less @@ -1,6 +1,10 @@ // ------------------------------------ // Tooltips +.tooltip-container--inline { + display: inline-block; +} + // Base class .tooltip { position: absolute; From 2203f9bc51d6cc931cf49c7ebd85060855f9177f Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sun, 9 May 2021 00:47:12 +0000 Subject: [PATCH 16/38] Use new Tooltip component for Preview post button --- js/src/common/components/TextEditor.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/js/src/common/components/TextEditor.js b/js/src/common/components/TextEditor.js index 105441ce2d..2b457725e8 100644 --- a/js/src/common/components/TextEditor.js +++ b/js/src/common/components/TextEditor.js @@ -4,6 +4,7 @@ import listItems from '../helpers/listItems'; import Button from './Button'; import BasicEditorDriver from '../utils/BasicEditorDriver'; +import Tooltip from './Tooltip'; /** * The `TextEditor` component displays a textarea with controls, including a @@ -108,13 +109,9 @@ export default class TextEditor extends Component { if (this.attrs.preview) { items.add( 'preview', - Button.component({ - icon: 'far fa-eye', - className: 'Button Button--icon', - onclick: this.attrs.preview, - title: app.translator.trans('core.forum.composer.preview_tooltip'), - oncreate: (vnode) => $(vnode.dom).tooltip(), - }) + +