@trimble-oss/moduswebcomponents
Version:
Modus Web Components is a modern, accessible UI library built with Stencil JS that provides reusable web components following Trimble's Modus design system. This updated version focuses on improved flexibility, enhanced theming options, comprehensive cust
193 lines (187 loc) • 6.86 kB
JavaScript
import { html } from "lit";
import { ifDefined } from "lit/directives/if-defined.js";
const meta = {
title: 'Components/Tooltip',
component: 'modus-wc-tooltip',
args: {
content: 'Tooltip content',
position: 'auto',
},
argTypes: {
position: {
control: { type: 'select' },
options: ['auto', 'top', 'right', 'bottom', 'left'],
},
},
parameters: {
docs: {
description: {
component: `
A customizable tooltip component used to create tooltips with different content.
### Features
- **Escape Key Dismissal**: Tooltips can be dismissed by pressing the Escape key
- **Auto-positioning**: Automatically positions the tooltip to avoid viewport edges
- **Customizable**: Supports custom CSS classes and positioning
### Keyboard Interaction
- Press **Escape** to dismiss the tooltip while it's visible
- The tooltip will automatically re-enable on mouse enter
`,
},
},
},
};
export default meta;
const Template = {
parameters: {
actions: {
handles: ['dismissEscape'],
},
},
render: (args) => {
// prettier-ignore
return html `
<modus-wc-tooltip
content=${ifDefined(args.content)}
custom-class="${ifDefined(args['custom-class'])}"
?disabled="${args.disabled}"
?force-open="${args['force-open']}"
tooltip-id="${ifDefined(args['tooltip-id'])}"
position=${ifDefined(args.position)}
>
<modus-wc-badge>Hover</modus-wc-badge>
</modus-wc-tooltip>
`;
},
};
export const Default = Object.assign({}, Template);
const defaultRichHtml = `<div style="display:flex;flex-direction:column;gap:0.25rem;text-align:start">
<div style="align-items:center;display:flex;gap:0.375rem">
<modus-wc-icon decorative name="thumbs_up" size="sm"></modus-wc-icon>
<span>First line of multiline content.</span>
</div>
<p>Second line of multiline content.</p>
</div>`;
function buildRichTooltipContent(html) {
const el = document.createElement('div');
el.innerHTML = html;
return el;
}
export const ContentElement = {
parameters: {
docs: {
description: {
story: `
Use \`contentElement\` to pass rich HTML (icons, multiple lines, formatting) as the tooltip body. It takes precedence over the \`content\` string prop. Your original node is not moved or mutated.
To update the tooltip content, reassign \`contentElement\` with a new element.
`,
},
source: {
transform: (_src, { args }) => {
var _a;
return `<modus-wc-tooltip
position="${(_a = args.position) !== null && _a !== void 0 ? _a : 'auto'}"
custom-class="tooltip-rich-html-demo"
>
<modus-wc-badge>Hover</modus-wc-badge>
</modus-wc-tooltip>
<script>
const el = document.createElement('div');
el.innerHTML = '<div style="display:flex;flex-direction:column;gap:0.25rem;text-align:start"><div style="align-items:center;display:flex;gap:0.375rem"><modus-wc-icon decorative name="thumbs_up" size="sm"></modus-wc-icon><span>First line of multiline content.</span></div><p>Second line of multiline content.</p></div>';
document.querySelector('modus-wc-tooltip').contentElement = el;
</script>`;
},
},
},
},
args: {
position: 'top',
'custom-class': 'tooltip-rich-html-demo',
},
render: (args) => {
const contentElement = buildRichTooltipContent(defaultRichHtml);
// prettier-ignore
return html `
<modus-wc-tooltip
.contentElement=${contentElement}
content=${ifDefined(args.content)}
custom-class="${ifDefined(args['custom-class'])}"
?disabled="${args.disabled}"
?force-open="${args['force-open']}"
tooltip-id="${ifDefined(args['tooltip-id'])}"
position=${ifDefined(args.position)}
>
<modus-wc-badge>Hover</modus-wc-badge>
</modus-wc-tooltip>
`;
},
};
export const ShadowDomParent = {
render: (args) => {
if (!customElements.get('tooltip-shadow-host')) {
class TooltipShadowHost extends HTMLElement {
constructor() {
super();
this.sr = this.attachShadow({ mode: 'open' });
}
connectedCallback() {
if (this.tooltipEl)
return;
this.renderContent();
}
set props(v) {
this._props = v;
if (this.tooltipEl)
this.applyProps();
}
renderContent() {
this.sr.innerHTML = '';
this.tooltipEl = document.createElement('modus-wc-tooltip');
const badge = document.createElement('modus-wc-badge');
badge.textContent = 'Hover';
this.tooltipEl.appendChild(badge);
this.sr.appendChild(this.tooltipEl);
void Promise.resolve().then(() => this.applyProps());
}
applyProps() {
var _a, _b, _c, _d, _e;
const v = this._props;
const tooltip = this.tooltipEl;
if (!v || !tooltip)
return;
tooltip.content = (_a = v.content) !== null && _a !== void 0 ? _a : 'Tooltip content';
tooltip.customClass = (_b = v['custom-class']) !== null && _b !== void 0 ? _b : '';
tooltip.disabled = Boolean(v.disabled);
tooltip.forceOpen = (_c = v['force-open']) !== null && _c !== void 0 ? _c : false;
tooltip.tooltipId = (_d = v['tooltip-id']) !== null && _d !== void 0 ? _d : '';
tooltip.position = (_e = v.position) !== null && _e !== void 0 ? _e : 'auto';
}
}
customElements.define('tooltip-shadow-host', TooltipShadowHost);
}
return html `<tooltip-shadow-host
.props=${Object.assign({}, args)}
></tooltip-shadow-host>`;
},
};
export const Migration = {
parameters: {
docs: {
description: {
story: `
#### Breaking Changes
- The \`text\` prop has been renamed to \`content\`.
#### Prop Mapping
| 1.0 Prop | 2.0 Prop | Notes |
| :--- | :--- | :--- |
| aria-label | aria-label | |
| disabled | disabled | |
| position | position | Added \`auto\` option as default value |
| text | content | |
`,
},
},
controls: { disable: true },
canvas: { disable: true },
},
render: () => html `<div></div>`,
};