@warp-ds/elements 2.11.0 → 2.12.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/custom-elements.json +323 -0
  2. package/dist/docs/index.md +1 -0
  3. package/dist/docs/textfield/api.md +12 -0
  4. package/dist/docs/textfield/textfield.md +12 -0
  5. package/dist/docs/tooltip/accessibility.md +9 -0
  6. package/dist/docs/tooltip/api.md +87 -0
  7. package/dist/docs/tooltip/examples.md +32 -0
  8. package/dist/docs/tooltip/styling.md +47 -0
  9. package/dist/docs/tooltip/tooltip.md +197 -0
  10. package/dist/docs/tooltip/usage.md +10 -0
  11. package/dist/entrypoint-react.d.ts +1 -0
  12. package/dist/entrypoint-react.js +1 -0
  13. package/dist/index.d.ts +159 -0
  14. package/dist/packages/affix/affix.js +3 -3
  15. package/dist/packages/affix/affix.js.map +2 -2
  16. package/dist/packages/affix/styles.js +1 -1
  17. package/dist/packages/attention/attention.stories.js +5 -1
  18. package/dist/packages/select/select.js +1 -1
  19. package/dist/packages/select/select.js.map +2 -2
  20. package/dist/packages/select/styles.js +1 -1
  21. package/dist/packages/tab/react.d.ts +1 -0
  22. package/dist/packages/tab/react.js +2 -1
  23. package/dist/packages/tabs/tabs.js +4 -4
  24. package/dist/packages/tabs/tabs.js.map +3 -3
  25. package/dist/packages/tabs/tabs.react.stories.js +5 -5
  26. package/dist/packages/textarea/styles.js +1 -1
  27. package/dist/packages/textarea/textarea.js +6 -6
  28. package/dist/packages/textarea/textarea.js.map +2 -2
  29. package/dist/packages/textfield/input-styles.js +1 -1
  30. package/dist/packages/textfield/react.d.ts +1 -1
  31. package/dist/packages/textfield/styles.js +1 -1
  32. package/dist/packages/textfield/textfield.d.ts +8 -0
  33. package/dist/packages/textfield/textfield.js +32 -15
  34. package/dist/packages/textfield/textfield.js.map +3 -3
  35. package/dist/packages/textfield/textfield.react.stories.d.ts +2 -2
  36. package/dist/packages/tooltip/locales/da/messages.d.mts +1 -0
  37. package/dist/packages/tooltip/locales/da/messages.mjs +1 -0
  38. package/dist/packages/tooltip/locales/en/messages.d.mts +1 -0
  39. package/dist/packages/tooltip/locales/en/messages.mjs +1 -0
  40. package/dist/packages/tooltip/locales/fi/messages.d.mts +1 -0
  41. package/dist/packages/tooltip/locales/fi/messages.mjs +1 -0
  42. package/dist/packages/tooltip/locales/nb/messages.d.mts +1 -0
  43. package/dist/packages/tooltip/locales/nb/messages.mjs +1 -0
  44. package/dist/packages/tooltip/locales/sv/messages.d.mts +1 -0
  45. package/dist/packages/tooltip/locales/sv/messages.mjs +1 -0
  46. package/dist/packages/tooltip/react.d.ts +16 -0
  47. package/dist/packages/tooltip/react.js +28 -0
  48. package/dist/packages/tooltip/styles.d.ts +1 -0
  49. package/dist/packages/tooltip/styles.js +66 -0
  50. package/dist/packages/tooltip/tooltip.d.ts +72 -0
  51. package/dist/packages/tooltip/tooltip.hydration.test.d.ts +1 -0
  52. package/dist/packages/tooltip/tooltip.hydration.test.js +13 -0
  53. package/dist/packages/tooltip/tooltip.js +2528 -0
  54. package/dist/packages/tooltip/tooltip.js.map +7 -0
  55. package/dist/packages/tooltip/tooltip.react.stories.d.ts +12 -0
  56. package/dist/packages/tooltip/tooltip.react.stories.js +12 -0
  57. package/dist/packages/tooltip/tooltip.stories.d.ts +17 -0
  58. package/dist/packages/tooltip/tooltip.stories.js +115 -0
  59. package/dist/packages/tooltip/tooltip.test.d.ts +2 -0
  60. package/dist/packages/tooltip/tooltip.test.js +130 -0
  61. package/dist/web-types.json +87 -1
  62. package/eik/index.js +19 -19
  63. package/package.json +2 -1
@@ -0,0 +1,12 @@
1
+ import { StoryObj } from "@storybook/react";
2
+ import React from "react";
3
+ import { Tooltip } from "./react";
4
+ declare const _default: {
5
+ title: string;
6
+ component: React.ForwardRefExoticComponent<Omit<Omit<React.HTMLAttributes<import("./tooltip").WarpTooltip>, "open" | "renderRoot" | "isUpdatePending" | "hasUpdated" | "addController" | "removeController" | "connectedCallback" | "disconnectedCallback" | "attributeChangedCallback" | "requestUpdate" | "updateComplete" | "firstUpdated" | "render" | "renderOptions" | "show" | "hide" | "placement" | "noArrow" | "for" | "showDelay" | "hideDelay"> & {} & Partial<Omit<import("./tooltip").WarpTooltip, keyof HTMLElement>> & React.RefAttributes<import("./tooltip").WarpTooltip>, "ref"> & {
7
+ htmlFor?: string;
8
+ } & React.RefAttributes<import("./tooltip").WarpTooltip>>;
9
+ };
10
+ export default _default;
11
+ export type Story = StoryObj<typeof Tooltip>;
12
+ export declare const Default: Story;
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ import { Button } from "../button/react";
3
+ import { Tooltip } from "./react";
4
+ export default {
5
+ title: "Overlays/Tooltip",
6
+ component: Tooltip,
7
+ };
8
+ export const Default = {
9
+ render: () => (React.createElement(React.Fragment, null,
10
+ React.createElement(Button, { id: "my-button", "aria-labelledby": "my-tooltip" }, "Hover over me"),
11
+ React.createElement(Tooltip, { id: "my-tooltip", htmlFor: "my-button" }, "Check out this tooltip"))),
12
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/web-components-vite";
2
+ import "virtual:uno.css";
3
+ import "../button/button.js";
4
+ import "../textfield/textfield.js";
5
+ import "./tooltip.js";
6
+ declare const args: {
7
+ "no-arrow": boolean;
8
+ placement: string;
9
+ "show-delay": number;
10
+ "hide-delay": number;
11
+ };
12
+ declare const meta: Meta;
13
+ export default meta;
14
+ type Story = StoryObj<typeof args>;
15
+ export declare const Default: Story;
16
+ export declare const Placement: Story;
17
+ export declare const Textfield: Story;
@@ -0,0 +1,115 @@
1
+ import { spread } from "@open-wc/lit-helpers";
2
+ import { html } from "lit";
3
+ // @ts-expect-error You'll find no types here, TypeScript the Grey
4
+ import "virtual:uno.css";
5
+ import { prespread } from "../../.storybook/utilities.js";
6
+ import "../button/button.js";
7
+ import "../textfield/textfield.js";
8
+ import "./tooltip.js";
9
+ const args = {
10
+ "no-arrow": false,
11
+ placement: "top",
12
+ "show-delay": 150,
13
+ "hide-delay": 0,
14
+ };
15
+ const meta = {
16
+ title: "Overlays/Tooltip",
17
+ args,
18
+ argTypes: {
19
+ placement: {
20
+ control: { type: "select" },
21
+ options: ["top", "bottom", "left", "right"],
22
+ },
23
+ },
24
+ };
25
+ export default meta;
26
+ export const Default = {
27
+ render(args) {
28
+ return html `
29
+ <w-button id="my-button" aria-labelledby="my-tooltip">
30
+ Hover over me
31
+ </w-button>
32
+ <w-tooltip id="my-tooltip" for="my-button" ${spread(prespread(args))}>
33
+ Check out this tooltip
34
+ </w-tooltip>
35
+ `;
36
+ },
37
+ };
38
+ export const Placement = {
39
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
40
+ render({ placement, ...rest }) {
41
+ return html `
42
+ <div style="display: flex; gap: 32px; flex-direction: column;">
43
+ <div>
44
+ <w-button id="top-button" aria-labelledby="top-tooltip">
45
+ Top
46
+ </w-button>
47
+ <w-tooltip
48
+ id="top-tooltip"
49
+ for="top-button"
50
+ placement="top"
51
+ ${spread(prespread(rest))}
52
+ >
53
+ Placement top
54
+ </w-tooltip>
55
+ </div>
56
+ <div>
57
+ <w-button id="right-button" aria-labelledby="right-tooltip"
58
+ >Right</w-button
59
+ >
60
+ <w-tooltip
61
+ id="right-tooltip"
62
+ for="right-button"
63
+ placement="right"
64
+ ${spread(prespread(rest))}
65
+ >
66
+ Placement right
67
+ </w-tooltip>
68
+ </div>
69
+ <div>
70
+ <w-button id="bottom-button" aria-labelledby="bottom-tooltip">
71
+ Bottom
72
+ </w-button>
73
+ <w-tooltip
74
+ id="bottom-tooltip"
75
+ for="bottom-button"
76
+ placement="bottom"
77
+ ${spread(prespread(rest))}
78
+ >
79
+ Placement bottom
80
+ </w-tooltip>
81
+ </div>
82
+ <div>
83
+ <w-button id="left-button" aria-labelledby="left-tooltip">
84
+ Left
85
+ </w-button>
86
+ <w-tooltip
87
+ id="left-tooltip"
88
+ for="left-button"
89
+ placement="left"
90
+ ${spread(prespread(rest))}
91
+ >
92
+ Placement left
93
+ </w-tooltip>
94
+ </div>
95
+ </div>
96
+ `;
97
+ },
98
+ };
99
+ export const Textfield = {
100
+ args: {},
101
+ argTypes: {},
102
+ parameters: {},
103
+ render() {
104
+ return html `
105
+ <w-textfield
106
+ name="tooltip-demo"
107
+ label="Needs an explanation"
108
+ placeholder="Placeholder"
109
+ help-text="Help text is available, but might not be enough, or the added context is not important enough that we use help-text"
110
+ tooltip="This tooltip adds supplementary information"
111
+ optional
112
+ ></w-textfield>
113
+ `;
114
+ },
115
+ };
@@ -0,0 +1,2 @@
1
+ import "../button/button.js";
2
+ import "./tooltip.js";
@@ -0,0 +1,130 @@
1
+ import { html } from "lit";
2
+ import { expect, test } from "vitest";
3
+ import { server, userEvent } from "vitest/browser";
4
+ import { render } from "vitest-browser-lit";
5
+ import "../button/button.js";
6
+ import "./tooltip.js";
7
+ test("tooltip is not shown by default", async () => {
8
+ // We wrap the contents in a span here so the test Locator can find an element
9
+ // that is not the w-tooltip itself for visibility testsing.
10
+ const component = html `
11
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
12
+ <w-tooltip id="test-tooltip" for="test-button">
13
+ <span>Tooltip contents</span>
14
+ </w-tooltip>
15
+ `;
16
+ const page = render(component);
17
+ expect(page.getByText("Tooltip contents")).not.toBeVisible();
18
+ });
19
+ test("tooltip with open property is shown by default", async () => {
20
+ // We wrap the contents in a span here so the test Locator can find an element
21
+ // that is not the w-tooltip itself for visibility testsing.
22
+ const component = html `
23
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
24
+ <w-tooltip id="test-tooltip" for="test-button" open>
25
+ <span>Tooltip contents</span>
26
+ </w-tooltip>
27
+ `;
28
+ const page = render(component);
29
+ await expect.element(page.getByText("Tooltip contents")).toBeVisible();
30
+ });
31
+ test("tooltip has an accessible description of its appearance and arrow direction", async () => {
32
+ const component = html `
33
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
34
+ <w-tooltip id="test-tooltip" for="test-button" open>
35
+ Tooltip contents
36
+ </w-tooltip>
37
+ `;
38
+ const page = render(component);
39
+ await expect
40
+ .element(page.getByRole("tooltip"))
41
+ .toHaveAccessibleDescription("A black speech bubble providing complementary information pointing down");
42
+ });
43
+ test("tooltip's accessible description does not include arrow direction if the tooltip has the no-arrow property", async () => {
44
+ const component = html `
45
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
46
+ <w-tooltip id="test-tooltip" for="test-button" open no-arrow>
47
+ Tooltip contents
48
+ </w-tooltip>
49
+ `;
50
+ const page = render(component);
51
+ await expect
52
+ .element(page.getByRole("tooltip"))
53
+ .toHaveAccessibleDescription("A black speech bubble providing complementary information");
54
+ });
55
+ test("tooltip opens when its target gets hovered", async () => {
56
+ // We wrap the contents in a span here so the test Locator can find an element
57
+ // that is not the w-tooltip itself for visibility testsing.
58
+ const component = html `
59
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
60
+ <w-tooltip id="test-tooltip" for="test-button">
61
+ <span>Tooltip contents</span>
62
+ </w-tooltip>
63
+ `;
64
+ const page = render(component);
65
+ await expect.element(page.getByText("Tooltip contents")).not.toBeVisible();
66
+ await userEvent.hover(page.getByRole("button"));
67
+ await expect.element(page.getByText("Tooltip contents")).toBeVisible();
68
+ });
69
+ test("tooltip closes when its target gets unhovered, except when the tooltip itself gets hovered", async () => {
70
+ // We wrap the contents in a span here so the test Locator can find an element
71
+ // that is not the w-tooltip itself for visibility testsing.
72
+ const component = html `
73
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
74
+ <w-tooltip id="test-tooltip" for="test-button">
75
+ <span data-testid="contents">Tooltip contents</span>
76
+ </w-tooltip>
77
+ `;
78
+ const page = render(component);
79
+ await expect.element(page.getByText("Tooltip contents")).not.toBeVisible();
80
+ await userEvent.hover(page.getByRole("button"));
81
+ await expect.element(page.getByText("Tooltip contents")).toBeVisible();
82
+ await userEvent.hover(page.getByTestId("contents"));
83
+ await expect.element(page.getByText("Tooltip contents")).toBeVisible();
84
+ await userEvent.unhover(page.getByTestId("contents"));
85
+ await expect.element(page.getByText("Tooltip contents")).not.toBeVisible();
86
+ });
87
+ test("tooltip opens when its target gets focus", async () => {
88
+ // We wrap the contents in a span here so the test Locator can find an element
89
+ // that is not the w-tooltip itself for visibility testsing.
90
+ const component = html `
91
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
92
+ <w-tooltip id="test-tooltip" for="test-button">
93
+ <span>Tooltip contents</span>
94
+ </w-tooltip>
95
+ `;
96
+ const page = render(component);
97
+ await expect.element(page.getByText("Tooltip contents")).not.toBeVisible();
98
+ await userEvent.keyboard("[Tab]"); // focus!
99
+ await expect.element(page.getByText("Tooltip contents")).toBeVisible();
100
+ });
101
+ // tested OK manually in Firefox 152
102
+ test.skipIf(server.browser === "firefox")("tooltip hides on blur", async () => {
103
+ // We wrap the contents in a span here so the test Locator can find an element
104
+ // that is not the w-tooltip itself for visibility testsing.
105
+ const component = html `
106
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
107
+ <w-tooltip id="test-tooltip" for="test-button">
108
+ <span>Tooltip contents</span>
109
+ </w-tooltip>
110
+ `;
111
+ const page = render(component);
112
+ await expect.element(page.getByText("Tooltip contents")).not.toBeVisible();
113
+ await userEvent.keyboard("[Tab]"); // focus!
114
+ await userEvent.keyboard("[Tab]"); // blur!
115
+ await expect.element(page.getByText("Tooltip contents")).not.toBeVisible();
116
+ });
117
+ test("tooltip can be dismissed with the Escape key", async () => {
118
+ // We wrap the contents in a span here so the test Locator can find an element
119
+ // that is not the w-tooltip itself for visibility testsing.
120
+ const component = html `
121
+ <w-button id="test-button" aria-labelledby="test-tooltip">Button</w-button>
122
+ <w-tooltip id="test-tooltip" for="test-button" open>
123
+ <span>Tooltip contents</span>
124
+ </w-tooltip>
125
+ `;
126
+ const page = render(component);
127
+ await expect.element(page.getByText("Tooltip contents")).toBeVisible();
128
+ await userEvent.keyboard("[Escape]");
129
+ await expect.element(page.getByText("Tooltip contents")).not.toBeVisible();
130
+ });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
3
3
  "name": "@warp-ds/elements",
4
- "version": "2.11.0-next.1",
4
+ "version": "2.11.0",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -113,6 +113,11 @@
113
113
  "value": {
114
114
  "type": "HTMLInputElement[\"autocomplete\"] | undefined"
115
115
  }
116
+ },
117
+ {
118
+ "name": "tooltip",
119
+ "description": "Suplementary information that should show in a tooltip behind an information icon after the label.\n\nUse the `tooltip` slot if you need markup and not just text.\n\nYou must provide a label to be able to show an info icon with a tooltip.",
120
+ "value": { "type": "string | undefined" }
116
121
  }
117
122
  ],
118
123
  "slots": [
@@ -226,6 +231,11 @@
226
231
  "description": "A space-separated string that hints to browsers [what type of content it can suggest](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete#value) to autofill.",
227
232
  "type": "HTMLInputElement[\"autocomplete\"] | undefined"
228
233
  },
234
+ {
235
+ "name": "tooltip",
236
+ "description": "Suplementary information that should show in a tooltip behind an information icon after the label.\n\nUse the `tooltip` slot if you need markup and not just text.\n\nYou must provide a label to be able to show an info icon with a tooltip.",
237
+ "type": "string | undefined"
238
+ },
229
239
  {
230
240
  "name": "formatter",
231
241
  "description": "Function to format value when the input field.\n\nOnly active when the input field does not have focus,\nsimilar to the accessible input [masking example from Filament Group](https://filamentgroup.github.io/politespace/demo/demo.html).",
@@ -2839,6 +2849,82 @@
2839
2849
  ],
2840
2850
  "events": []
2841
2851
  }
2852
+ },
2853
+ {
2854
+ "name": "w-tooltip",
2855
+ "description": "A tooltip is a message box that is displayed when a user hovers over or gives focus to a UI element.\n\nTooltips should be used sparingly and contain succinct, supplementary information.\n---\n",
2856
+ "doc-url": "",
2857
+ "attributes": [
2858
+ {
2859
+ "name": "for",
2860
+ "description": "ID of the element that triggers the tooltip on hover or focus.",
2861
+ "value": { "type": "string", "default": "\"\"" }
2862
+ },
2863
+ {
2864
+ "name": "no-arrow",
2865
+ "description": "Hide the arrow pointing toward the tooltip target.",
2866
+ "value": { "type": "boolean", "default": "false" }
2867
+ },
2868
+ {
2869
+ "name": "open",
2870
+ "description": "Indicates whether the tooltip is visible or not.",
2871
+ "value": { "type": "boolean", "default": "false" }
2872
+ },
2873
+ {
2874
+ "name": "placement",
2875
+ "description": "Sets the placement of the tooltip relative to its target.\n\nThe tooltip will try to position itself at the given placement. If there is no room it will flip to the opposite side automatically.",
2876
+ "value": {
2877
+ "type": "'top' | 'right' | 'bottom' | 'left'",
2878
+ "default": "\"top\""
2879
+ }
2880
+ },
2881
+ {
2882
+ "name": "show-delay",
2883
+ "description": "Milliseconds to wait before showing the tooltip on hover.\n\nKeep at a non-zero value to avoid flickering the tooltip on and off when cursors move quickly past the target element.\n\nFocusing the target element shows the tooltip immediately.",
2884
+ "value": { "type": "number", "default": "150" }
2885
+ },
2886
+ {
2887
+ "name": "hide-delay",
2888
+ "description": "Milliseconds to wait before hiding the tooltip on mouseout.",
2889
+ "value": { "type": "number", "default": "0" }
2890
+ }
2891
+ ],
2892
+ "events": [],
2893
+ "js": {
2894
+ "properties": [
2895
+ {
2896
+ "name": "for",
2897
+ "description": "ID of the element that triggers the tooltip on hover or focus.",
2898
+ "type": "string"
2899
+ },
2900
+ {
2901
+ "name": "noArrow",
2902
+ "description": "Hide the arrow pointing toward the tooltip target.",
2903
+ "type": "boolean"
2904
+ },
2905
+ {
2906
+ "name": "open",
2907
+ "description": "Indicates whether the tooltip is visible or not.",
2908
+ "type": "boolean"
2909
+ },
2910
+ {
2911
+ "name": "placement",
2912
+ "description": "Sets the placement of the tooltip relative to its target.\n\nThe tooltip will try to position itself at the given placement. If there is no room it will flip to the opposite side automatically.",
2913
+ "type": "'top' | 'right' | 'bottom' | 'left'"
2914
+ },
2915
+ {
2916
+ "name": "showDelay",
2917
+ "description": "Milliseconds to wait before showing the tooltip on hover.\n\nKeep at a non-zero value to avoid flickering the tooltip on and off when cursors move quickly past the target element.\n\nFocusing the target element shows the tooltip immediately.",
2918
+ "type": "number"
2919
+ },
2920
+ {
2921
+ "name": "hideDelay",
2922
+ "description": "Milliseconds to wait before hiding the tooltip on mouseout.",
2923
+ "type": "number"
2924
+ }
2925
+ ],
2926
+ "events": []
2927
+ }
2842
2928
  }
2843
2929
  ]
2844
2930
  },