Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(web-twig): Introduce advanced Tooltip usage supported by FloatingUI #1246

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions apps/web-twig-demo/assets/scripts/tooltip-advanced-usage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Tooltip } from '@lmc-eu/spirit-web/src/js/index.esm';

const checkboxFlip = document.getElementById('my-advanced-flip') as HTMLInputElement;
const checkboxFlipCrossAxis = document.getElementById('my-advanced-flip-cross-axis') as HTMLInputElement;
const checkboxShift = document.getElementById('my-advanced-shift') as HTMLInputElement;
const checkboxSize = document.getElementById('my-advanced-size') as HTMLInputElement;
const select = document.getElementById('my-advanced-select') as HTMLSelectElement;
const selectFallback = document.getElementById('my-advanced-select-fallback') as HTMLSelectElement;

const tooltip = Tooltip.getOrCreateInstance(document.getElementById('my-advanced-tooltip'));

tooltip.show();

checkboxFlip.addEventListener('change', () => tooltip.updateConfig({ enableFlipping: checkboxFlip.checked }));

checkboxFlipCrossAxis.addEventListener('change', () => {
tooltip.updateConfig({ enableFlippingCrossAxis: checkboxFlipCrossAxis.checked });
});

checkboxShift.addEventListener('change', () => {
tooltip.updateConfig({ enableShifting: checkboxShift.checked });
});

checkboxSize.addEventListener('change', () => {
tooltip.updateConfig({ enableSizing: checkboxSize.checked });
});

select.addEventListener('change', () => {
tooltip.updateConfig({ placement: select.value });
});

selectFallback.addEventListener('change', () => {
tooltip.updateConfig({ flipFallbackPlacements: selectFallback.value });
});

const viewport = document.getElementById('my-advanced-viewport');
const content = document.getElementById('my-advanced-content');

viewport.scrollLeft = (content.offsetWidth - viewport.offsetWidth) / 2;
viewport.scrollTop = (content.offsetHeight - viewport.offsetHeight) / 2;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Tooltip from '@lmc-eu/spirit-web/src/js/Tooltip';
import { Tooltip } from '@lmc-eu/spirit-web/src/js/index.esm';

const myTooltipEl = document.getElementById('my-dismissible-tooltip2');
const myTooltip = new Tooltip(myTooltipEl);
Expand Down
5 changes: 3 additions & 2 deletions apps/web-twig-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
"@babel/core": "7.23.7",
"@babel/preset-env": "7.23.7",
"@csstools/normalize.css": "12.1.1",
"@floating-ui/dom": "^1.5.4",
literat marked this conversation as resolved.
Show resolved Hide resolved
"@hotwired/stimulus": "3.2.2",
"@lmc-eu/spirit-web": "1.6.0",
"@lmc-eu/spirit-form-validations": "1.0.9",
"@lmc-eu/spirit-demo": "0.1.0",
"@lmc-eu/spirit-form-validations": "1.0.9",
"@lmc-eu/spirit-web": "1.6.0",
"@symfony/stimulus-bridge": "3.2.2",
"@symfony/webpack-encore": "4.5.0",
"core-js": "3.35.0",
Expand Down
10 changes: 9 additions & 1 deletion apps/web-twig-demo/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const path = require('path');
// eslint-disable-next-line import/no-unresolved
const Encore = require('@symfony/webpack-encore');
// eslint-disable-next-line import/no-extraneous-dependencies
Expand Down Expand Up @@ -28,6 +29,7 @@ Encore
.addEntry('fileUploaderMetaData', './assets/scripts/file-uploader-meta-data.ts')
.addEntry('formValidations', './assets/scripts/form-validations.ts')
.addEntry('tooltipDismissibleViaJS', './assets/scripts/tooltip-dismissible-via-js.ts')
.addEntry('tooltipAdvancedUsage', './assets/scripts/tooltip-advanced-usage.ts')

// enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
// .enableStimulusBridge('./assets/controllers.json')
Expand Down Expand Up @@ -93,4 +95,10 @@ Encore
// .enableIntegrityHashes(Encore.isProduction())
;

module.exports = Encore.getWebpackConfig();
const config = Encore.getWebpackConfig();

config.resolve.alias = {
'@floating-ui/dom': path.resolve(__dirname, 'node_modules/@floating-ui/dom'),
literat marked this conversation as resolved.
Show resolved Hide resolved
};

module.exports = config;
43 changes: 24 additions & 19 deletions apps/web-twig-demo/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,26 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==

"@floating-ui/core@^1.5.3":
version "1.5.3"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.5.3.tgz#b6aa0827708d70971c8679a16cf680a515b8a52a"
integrity sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==
dependencies:
"@floating-ui/utils" "^0.2.0"

"@floating-ui/dom@^1.5.4":
version "1.5.4"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.4.tgz#28df1e1cb373884224a463235c218dcbd81a16bb"
integrity sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==
dependencies:
"@floating-ui/core" "^1.5.3"
"@floating-ui/utils" "^0.2.0"

"@floating-ui/utils@^0.2.0":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2"
integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==

"@hotwired/stimulus-webpack-helpers@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.1.tgz#4cd74487adeca576c9865ac2b9fe5cb20cef16dd"
Expand Down Expand Up @@ -1966,25 +1986,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"

caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001449:
version "1.0.30001481"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz#f58a717afe92f9e69d0e35ff64df596bfad93912"
integrity sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==

caniuse-lite@^1.0.30001503:
version "1.0.30001517"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz#90fabae294215c3495807eb24fc809e11dc2f0a8"
integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==

caniuse-lite@^1.0.30001541:
version "1.0.30001553"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001553.tgz#e64e7dc8fd4885cd246bb476471420beb5e474b5"
integrity sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==

caniuse-lite@^1.0.30001565:
version "1.0.30001570"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca"
integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001503, caniuse-lite@^1.0.30001541, caniuse-lite@^1.0.30001565:
version "1.0.30001579"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz"
integrity sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==

chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.2:
version "2.4.2"
Expand Down
93 changes: 90 additions & 3 deletions packages/web-twig/src/Resources/components/Tooltip/README.md
literat marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,89 @@ These attributes will be passed to the topmost HTML element of the component.

### TooltipWrapper

⚠️ `TooltipWrapper` component is [deprecated] and will be renamed to the `Tooltip` in the next major version.

You can add `id`, `data-*` or `aria-*` attributes to further extend the component's
descriptiveness and accessibility. Also, UNSAFE styling props are available,
see the [Escape hatches][escape-hatches] section in README to learn how and when to use them.

### TooltipPopover

#### Usage with the Advanced Floating Functionality

To enable the advanced floating functionality, you need to have activated feature flag `spirit-feature-tooltip-enable-data-placement` on any parent element.
pavelklibani marked this conversation as resolved.
Show resolved Hide resolved
This requirement will be removed in future major version.

For more info about feature flags, see main [README][readme-feature-flags].

Advanced floating functionality is provided by JavaScript plugin and by [Floating UI][floating-ui] library.

#### Basic

```html
<div className="spirit-feature-tooltip-enable-data-placement">
<TooltipWrapper>
<button>I have a tooltip!</button>
<TooltipPopover>Hello there!</TooltipPopover>
</TooltipWrapper>
</div>
;
```

#### Dismissible

Add `isDismissible` prop to `TooltipPopover` component.
there will be automatically displayed close button in `TooltipPopover`` component

```html
<div className="spirit-feature-tooltip-enable-data-placement">
<TooltipWrapper>
<button data-spirit-toggle="tooltip" data-spirit-target="my-tooltip-dismissible">I have a tooltip 😎</button>
<TooltipPopover id="my-tooltip-dismissible" placement="right" isDismissible> Close me </TooltipPopover>
</TooltipWrapper>
</div>
```

#### Full Advanced Usage

```html
<div className="spirit-feature-tooltip-enable-data-placement">
<TooltipWrapper>
<button data-spirit-toggle="tooltip" data-spirit-target="my-tooltip-advanced">I have a tooltip 😎</button>
<TooltipPopover
closeLabel="Close tooltip"
id="my-tooltip-advanced"
isDismissible
enableControlledPlacement
enableFlipping
enableFlippingCrossAxis
enableShifting
enableSizing
flipFallbackAxisSideDirection="top, left, right, bottom"
flipFallbackPlacements="left-start"
placement="right-start"
>
Close me
</TooltipPopover>
</TooltipWrapper>
</div>
```

#### API

| Attribute | Type | Default | Required | Description |
| ------------------------------- | -------------------------------------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `closeLabel` | `string` | `Close` | ✕ | Close label |
| `enableFlipping` | `bool` | true | ✕ | Enables [flipping][floating-ui-flip] of the element’s placement when it starts to overflow its boundary area. For example `top` can be flipped to `bottom`. |
| `enableFlippingCrossAxis` | `bool` | true | ✕ | Enables flipping on the [cross axis][floating-ui-flip-cross-axis], the axis perpendicular to main axis. For example `top-end` can be flipped to the `top-start`. |
literat marked this conversation as resolved.
Show resolved Hide resolved
| `enableShifting` | `bool` | true | ✕ | Enables [shifting][floating-ui-shift] of the element to keep it inside the boundary area by adjusting its position. |
| `enableSizing` | `bool` | true | ✕ | Enables [sizing][floating-ui-size] of the element to keep it inside the boundary area by setting the max width. |
| `flipFallbackAxisSideDirection` | ["none" \| "start" \| "end"] | "none" | ✕ | Whether to allow [fallback to the opposite axis][floating-ui-flip-fallback-axis-side-direction] if no placements along the preferred placement axis fit, and if so, which side direction along that axis to choose. If necessary, it will fallback to the other direction. |
| `flipFallbackPlacements` | `string` | - | ✕ | This describes a list of [explicit placements][floating-ui-flip-fallback-placements] to try if the initial placement doesn’t fit on the axes in which overflow is checked. For example you can set `"top, right, bottom"` |
| `id` | `string` | - | ✔ | Tooltip id |
| `isDismissible` | `bool` | false | ✕ | Make tooltip dismissible |
| `placement` | [Placement Dictionary][dictionary-placement] | "bottom" | ✕ | Placement of tooltip |

## JavaScript Plugin

For full functionality, you need to provide Spirit JavaScript:
Expand All @@ -90,8 +169,16 @@ Or, feel free to write the controlling script yourself.

👉 Check the [component's docs in the web package][web-js-api] to see the full documentation and API of the plugin.

[dictionary-placement]: https://github.com/lmc-eu/spirit-design-system/blob/main/docs/DICTIONARIES.md#placement
[escape-hatches]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-twig/README.md#escape-hatches
[floating-ui-flip-cross-axis]: https://floating-ui.com/docs/flip#crossaxis
[floating-ui-flip-fallback-axis-side-direction]: https://floating-ui.com/docs/flip#fallbackaxissidedirection
[floating-ui-flip-fallback-placements]: https://floating-ui.com/docs/flip#fallbackplacements
[floating-ui-flip]: https://floating-ui.com/docs/flip
[floating-ui-shift]: https://floating-ui.com/docs/shift
[floating-ui-size]: https://floating-ui.com/docs/size
[floating-ui]: https://floating-ui.com
[readme-feature-flags]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/README.md#feature-flags
[tooltip]: https://github.com/lmc-eu/spirit-design-system/tree/main/packages/web/src/scss/components/Tooltip
[web-js-api]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/src/scss/components/Tooltip/README.md#javascript-api
[web-readme]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/README.md
[tooltip]: https://github.com/lmc-eu/spirit-design-system/tree/main/packages/web/src/scss/components/Tooltip
[dictionary-placement]: https://github.com/lmc-eu/spirit-design-system/tree/main/docs/DICTIONARIES.md#placement
[escape-hatches]: https://github.com/lmc-eu/spirit-design-system/tree/main/packages/web-twig/README.md#escape-hatches
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
{% include '@components/Tooltip/stories/TooltipOnHover.twig' %}
</DocsSection>

<DocsSection title="Tooltip with JS plugin">
{% include '@components/Tooltip/stories/TooltipWithJsPlugin.twig' %}
</DocsSection>

<DocsSection title="Tooltip on Click (JavaScript)">
{% include '@components/Tooltip/stories/TooltipClickable.twig' %}
</DocsSection>
Expand All @@ -22,11 +26,11 @@
{% include '@components/Tooltip/stories/TooltipDismissible.twig' %}
</DocsSection>

<DocsSection title="Dismissible Tooltip via JS API">
<DocsSection title="Dismissible Tooltip via JS API and Floating UI">
{% include '@components/Tooltip/stories/TooltipDismissibleViaJS.twig' %}
</DocsSection>

<DocsSection title="Full Floating UI Usage">
<DocsSection title="Advanced Floating Functionality">
{% include '@components/Tooltip/stories/TooltipFloatingUI.twig' %}
</DocsSection>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
{% deprecated 'Tooltip: Non-flow-relative values (eg. "' ~ _placement ~ '") in "placement" property are deprecated and will be removed in the next major version. Use flow-relative (eg. "' ~ deprecatedPlacements[_placement] ~ '") instead.' %}
{% endif %}

{% deprecated 'Tooltip: Implmentation of this component is deprecated and will be replaced with the implementation of the TooltipPopover in the next major version. Please, use it instead.' %}

<div
{{ mainProps(_mainPropsWithoutId) }}
{{ styleProp(_styleProps) }}
Expand Down
Loading
Loading