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

Integration/tooltip #1257

Merged
merged 11 commits into from
Jan 30, 2024
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",
"@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
8 changes: 7 additions & 1 deletion packages/web-react/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,13 @@ module.exports = {
// allow reassign in properties
'no-param-reassign': ['warn', { props: false }],
// support monorepos
'import/no-extraneous-dependencies': ['error', { packageDir: ['./', '../../'] }],
'import/no-extraneous-dependencies': [
'error',
{
packageDir: ['./', '../../'],
peerDependencies: true,
},
],
// disable double quotes
quotes: ['warn', 'single'],
// use useIsomorphicLayoutEffect instead of useLayoutEffect
Expand Down
1 change: 1 addition & 0 deletions packages/web-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"module": "./index.js",
"types": "./index.d.ts",
"dependencies": {
"@floating-ui/react": "^0.26.5",
"@react-hook/resize-observer": "^1.2.6",
"classnames": "^2.3.1",
"react-transition-group": "^4.4.5"
Expand Down
73 changes: 71 additions & 2 deletions packages/web-react/src/components/Tooltip/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ const { getReferenceProps, getFloatingProps } = useInteractions([hover, focus, d
ref={refs.setReference}
{...getReferenceProps()}
>
I have a flipping tooltip!
I have a tooltip!
</button>
<Tooltip
placement="off"
Expand Down Expand Up @@ -200,7 +200,7 @@ const { getReferenceProps, getFloatingProps } = useInteractions([hover, focus, d
ref={refs.setReference}
{...getReferenceProps()}
>
I have a flipping tooltip!
I have a tooltip!
</button>
<Tooltip
placement="off"
Expand All @@ -220,4 +220,73 @@ const { getReferenceProps, getFloatingProps } = useInteractions([hover, focus, d
</div>;
```

# TooltipModern

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

## Usage

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

### Basic

```javascript
import { TooltipModern, TooltipTrigger, TooltipPopover, Button } from '@lmc-eu/spirit-web-react/components';

const [open, setOpen] = React.useState(false);

<div className="spirit-feature-tooltip-enable-data-placement">
<TooltipModern id="TooltipModern" isOpen={open} onToggle={setOpen}>
<TooltipTrigger>I have a tooltip!</TooltipTrigger>
<TooltipPopover>Hello there!</TooltipPopover>
</TooltipModern>
</div>;
```

### Dismissible

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

```javascript
import { TooltipModern, TooltipTrigger, TooltipPopover, Button } from '@lmc-eu/spirit-web-react/components';

const [open, setOpen] = React.useState(false);

<div className="spirit-feature-tooltip-enable-data-placement">
<TooltipModern id="TooltipModernDismissible" isOpen={open} onToggle={setOpen} placement="right" isDismissible>
<TooltipTrigger elementType={Button}>I have a tooltip 😎</TooltipTrigger>
<TooltipPopover>Close me</TooltipPopover>
</TooltipModern>
</div>;
```

## API

| Attribute | Type | Default | Required | Description |
| ------------------------------- | -------------------------------------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | `ReactNode` | — | ✔ | Tooltip children's nodes - `TooltipTrigger` and `TooltipPopover` |
| `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`. |
| `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 |
| `isOpen` | `bool` | - | ✔ | Open state |
| `onToggle` | `() => void` | - | ✔ | Function for toggle open state of dropdown |
| `placement` | [Placement Dictionary][dictionary-placement] | "bottom" | ✕ | Placement of tooltip |

[dictionary-placement]: https://github.com/lmc-eu/spirit-design-system/tree/main/docs/DICTIONARIES.md#placement
[example]: https://spirit-design-system-demo.netlify.app/src/scss/components/tooltip/#advanced-positioning
[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-deprecations]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#deprecations
[readme-feature-flags]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/README.md#feature-flags
57 changes: 57 additions & 0 deletions packages/web-react/src/components/Tooltip/TooltipContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { MiddlewareData, Placement } from '@floating-ui/react';
import { HTMLProps, MutableRefObject, createContext, useContext } from 'react';

type refType = ((node: HTMLElement | null) => void) & ((node: HTMLElement | null) => void);

type TooltipContextType = {
anchorRef: refType;
arrowRef: MutableRefObject<HTMLElement | null>;
getFloatingProps: (userProps?: HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
getReferenceProps: (userProps?: HTMLProps<Element> | undefined) => Record<string, unknown>;
id: string;
isDismissible?: boolean;
isOpen: boolean;
middlewareData: MiddlewareData;
onToggle: (isOpen: boolean) => void;
placement?: Placement | undefined;
sizeMaxWidth?: number;
tooltipMaxWidth?: number;
tooltipRef: refType;
triggerRef: refType;
x: number;
y: number;
};

const defaultContext: TooltipContextType = {
anchorRef: () => {},
arrowRef: { current: null },
getReferenceProps: () => ({
id: '',
ref: () => {},
}),
getFloatingProps: () => ({
id: '',
ref: () => {},
}),
id: '',
isDismissible: false,
isOpen: false,
middlewareData: {},
onToggle: () => {},
placement: 'bottom',
sizeMaxWidth: undefined,
tooltipMaxWidth: undefined,
tooltipRef: () => {},
triggerRef: () => {},
x: 0,
y: 0,
};

const TooltipContext = createContext<TooltipContextType>(defaultContext);
const TooltipProvider = TooltipContext.Provider;
const TooltipConsumer = TooltipContext.Consumer;
const useTooltipContext = (): TooltipContextType => useContext(TooltipContext);

export default TooltipContext;
export { TooltipConsumer, TooltipProvider, useTooltipContext };
export type { TooltipContextType };
Loading
Loading