playbook_ui 14.22.0.pre.alpha.PLAY22578709 → 14.22.0.pre.alpha.PLAY22958842

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_badge/_badge.scss +5 -6
  3. data/app/pb_kits/playbook/pb_bar_graph/barGraphTheme.ts +106 -0
  4. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_colors.jsx +33 -15
  5. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_default.jsx +33 -15
  6. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_height.jsx +52 -22
  7. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_height.md +3 -0
  8. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_horizontal.jsx +12 -16
  9. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_legend.jsx +31 -15
  10. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_legend_non_clickable.jsx +39 -16
  11. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_legend_position.jsx +86 -38
  12. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_negative_numbers.jsx +32 -15
  13. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_secondary_y_axis.jsx +72 -22
  14. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_secondary_y_axis.md +1 -1
  15. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_spline.jsx +31 -15
  16. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_stacked.jsx +37 -16
  17. data/app/pb_kits/playbook/pb_bar_graph/docs/_description.md +1 -3
  18. data/app/pb_kits/playbook/pb_bar_graph/docs/example.yml +1 -3
  19. data/app/pb_kits/playbook/pb_bar_graph/docs/index.js +0 -2
  20. data/app/pb_kits/playbook/pb_circle_chart/circleChartTheme.ts +36 -1
  21. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_block.jsx +71 -26
  22. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_colors.jsx +29 -16
  23. data/app/pb_kits/playbook/pb_circle_chart/docs/{_circle_chart_colors.md → _circle_chart_colors_rails.md} +1 -1
  24. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_colors_react.md +2 -0
  25. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_custom_tooltip.jsx +28 -16
  26. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_custom_tooltip.md +4 -2
  27. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_default.jsx +23 -15
  28. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_inner_sizes.jsx +81 -51
  29. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_legend_position.jsx +103 -75
  30. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_legend_position.md +3 -6
  31. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_live_data.jsx +19 -13
  32. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_rounded.jsx +30 -17
  33. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_with_labels.jsx +34 -20
  34. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_with_legend_kit.jsx +29 -20
  35. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_with_title.jsx +28 -20
  36. data/app/pb_kits/playbook/pb_circle_chart/docs/_description.md +1 -0
  37. data/app/pb_kits/playbook/pb_circle_chart/docs/example.yml +0 -1
  38. data/app/pb_kits/playbook/pb_circle_chart/docs/index.js +0 -1
  39. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +4 -12
  40. data/app/pb_kits/playbook/pb_draggable/context/types.ts +2 -5
  41. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_click_open.html.erb +14 -0
  42. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_click_open_rails.md +1 -0
  43. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +1 -0
  44. data/app/pb_kits/playbook/pb_tooltip/index.js +59 -36
  45. data/app/pb_kits/playbook/pb_tooltip/tooltip.rb +9 -2
  46. data/dist/chunks/_circle_chart-BjcInQNv.js +1 -0
  47. data/dist/chunks/{_typeahead-BZsshVoi.js → _typeahead-CuwY9iVi.js} +3 -3
  48. data/dist/chunks/{_weekday_stacked-DO4S-plL.js → _weekday_stacked-C3EeTZ8D.js} +1 -1
  49. data/dist/chunks/{lib-Carqm8Ip.js → lib-DYpq0k8j.js} +1 -1
  50. data/dist/chunks/{pb_form_validation-DqRmTS8m.js → pb_form_validation-BUOKwfvW.js} +1 -1
  51. data/dist/chunks/vendor.js +1 -1
  52. data/dist/menu.yml +68 -8
  53. data/dist/playbook-doc.js +1 -1
  54. data/dist/playbook-rails-react-bindings.js +1 -1
  55. data/dist/playbook-rails.js +1 -1
  56. data/dist/playbook.css +1 -1
  57. data/lib/playbook/version.rb +1 -1
  58. metadata +15 -14
  59. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_custom.jsx +0 -72
  60. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_custom.md +0 -6
  61. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_pb_styles.jsx +0 -64
  62. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_pb_styles.md +0 -1
  63. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_pb_styles.jsx +0 -38
  64. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_pb_styles.md +0 -1
  65. /data/app/pb_kits/playbook/pb_tooltip/docs/{_tooltip_click_open.md → _tooltip_click_open_react.md} +0 -0
@@ -1,36 +1,37 @@
1
1
  import React, { useState } from 'react'
2
-
3
- import CircleChart from '../_circle_chart'
2
+ import circleChartTheme from '../circleChartTheme'
3
+ import Highcharts from "highcharts"
4
+ import HighchartsReact from "highcharts-react-official"
4
5
  import Button from '../../pb_button/_button'
5
6
 
6
7
  const CircleChartLiveData = (props) => {
7
8
  const [data, setData] = useState([
8
9
  {
9
10
  name: 'Waiting for Calls',
10
- value: 41,
11
+ y: 41,
11
12
  },
12
13
  {
13
14
  name: 'On Call',
14
- value: 49,
15
+ y: 49,
15
16
  },
16
17
  {
17
18
  name: 'After Call',
18
- value: 10,
19
+ y: 10,
19
20
  },
20
21
  ])
21
22
 
22
23
  const data2 = [
23
24
  {
24
25
  name: 'Waiting for Calls',
25
- value: 48,
26
+ y: 48,
26
27
  },
27
28
  {
28
29
  name: 'On Call',
29
- value: 12,
30
+ y: 12,
30
31
  },
31
32
  {
32
33
  name: 'After Call',
33
- value: 140,
34
+ y: 140,
34
35
  },
35
36
  ]
36
37
 
@@ -38,6 +39,12 @@ const CircleChartLiveData = (props) => {
38
39
  setData(data2)
39
40
  }
40
41
 
42
+ const chartOptions = {
43
+ series: [{ data: data }],
44
+ }
45
+
46
+ const options = Highcharts.merge({}, circleChartTheme, chartOptions)
47
+
41
48
  return (
42
49
  <div>
43
50
  <Button
@@ -45,13 +52,12 @@ const CircleChartLiveData = (props) => {
45
52
  text="Update Value"
46
53
  {...props}
47
54
  />
48
- <CircleChart
49
- chartData={data}
50
- id="circle-chart-live-data"
51
- {...props}
55
+ <HighchartsReact
56
+ highcharts={Highcharts}
57
+ options={options}
52
58
  />
53
59
  </div>
54
60
  )
55
61
  }
56
62
 
57
- export default CircleChartLiveData
63
+ export default CircleChartLiveData
@@ -1,32 +1,45 @@
1
1
  import React from 'react'
2
-
3
- import CircleChart from '../_circle_chart'
2
+ import circleChartTheme from '../circleChartTheme'
3
+ import Highcharts from "highcharts"
4
+ import HighchartsReact from "highcharts-react-official"
4
5
 
5
6
  const dataRounded = [
6
7
  {
7
8
  name: 'Waiting for Calls',
8
- value: 41,
9
+ y: 41,
9
10
  },
10
11
  {
11
12
  name: 'On Call',
12
- value: 49,
13
+ y: 49,
13
14
  },
14
15
  {
15
16
  name: 'After Call',
16
- value: 10,
17
+ y: 10,
17
18
  },
18
19
  ]
19
20
 
20
- const CircleChartRounded = (props) => (
21
- <div>
22
- <CircleChart
23
- chartData={dataRounded}
24
- id="default-test-rounded"
25
- innerSize="lg"
26
- rounded
27
- {...props}
28
- />
29
- </div>
30
- )
21
+ const CircleChartRounded = () => {
22
+ const chartOptions = {
23
+ series: [{ data: dataRounded }],
24
+ plotOptions: {
25
+ pie: {
26
+ borderColor: null,
27
+ borderWidth: 20,
28
+ innerSize: '100%',
29
+ },
30
+ },
31
+ }
32
+
33
+ const options = Highcharts.merge({}, circleChartTheme, chartOptions)
34
+
35
+ return (
36
+ <div>
37
+ <HighchartsReact
38
+ highcharts={Highcharts}
39
+ options={options}
40
+ />
41
+ </div>
42
+ )
43
+ }
31
44
 
32
- export default CircleChartRounded
45
+ export default CircleChartRounded
@@ -1,47 +1,61 @@
1
1
  import React from 'react'
2
-
3
- import CircleChart from '../_circle_chart'
2
+ import circleChartTheme from '../circleChartTheme'
3
+ import Highcharts from "highcharts"
4
+ import HighchartsReact from "highcharts-react-official"
4
5
 
5
6
  const dataWithLabels = [
6
7
  {
7
8
  name: 'Facebook',
8
- value: 2498,
9
+ y: 2498,
9
10
  },
10
11
  {
11
12
  name: 'YouTube',
12
- value: 2000,
13
+ y: 2000,
13
14
  },
14
15
  {
15
16
  name: 'WhatsApp',
16
- value: 2000,
17
+ y: 2000,
17
18
  },
18
19
  {
19
20
  name: 'Facebook Messenger',
20
- value: 1300,
21
+ y: 1300,
21
22
  },
22
23
  {
23
24
  name: 'WeChat',
24
- value: 1165,
25
+ y: 1165,
25
26
  },
26
27
  {
27
28
  name: 'Instagram',
28
- value: 1000,
29
+ y: 1000,
29
30
  },
30
31
  {
31
32
  name: 'Tik Tok',
32
- value: 800,
33
+ y: 800,
33
34
  },
34
35
  ]
35
36
 
36
- const CircleChartWithLabels = (props) => (
37
- <div>
38
- <CircleChart
39
- chartData={dataWithLabels}
40
- dataLabels
41
- id="with-labels-example"
42
- {...props}
43
- />
44
- </div>
45
- )
37
+ const CircleChartWithLabels = () => {
38
+ const chartOptions = {
39
+ series: [{ data: dataWithLabels }],
40
+ plotOptions: {
41
+ pie: {
42
+ dataLabels: {
43
+ enabled: true,
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ const options = Highcharts.merge({}, circleChartTheme, chartOptions)
50
+
51
+ return (
52
+ <div>
53
+ <HighchartsReact
54
+ highcharts={Highcharts}
55
+ options={options}
56
+ />
57
+ </div>
58
+ )
59
+ }
46
60
 
47
- export default CircleChartWithLabels
61
+ export default CircleChartWithLabels
@@ -1,32 +1,41 @@
1
1
  import React from 'react'
2
-
3
- import CircleChart from '../_circle_chart'
2
+ import circleChartTheme from '../circleChartTheme'
3
+ import Highcharts from "highcharts"
4
+ import HighchartsReact from "highcharts-react-official"
4
5
 
5
6
  const dataWithLegend = [{
6
7
  name: 'Bugs',
7
- value: 8,
8
-
8
+ y: 8,
9
9
  },
10
10
  {
11
11
  name: 'Chores',
12
- value: 1,
13
-
12
+ y: 1,
14
13
  },
15
14
  {
16
15
  name: 'Stories',
17
- value: 12,
18
- },
19
- ]
16
+ y: 12,
17
+ }]
18
+
19
+ const CircleChartWithLegendKit = () => {
20
+ const chartOptions = {
21
+ series: [{ data: dataWithLegend }],
22
+ plotOptions: {
23
+ pie: {
24
+ showInLegend: true
25
+ }
26
+ }
27
+ }
28
+
29
+ const options = Highcharts.merge({}, circleChartTheme, chartOptions)
20
30
 
21
- const CircleChartWithLegendKit = (props) => (
22
- <div>
23
- <CircleChart
24
- chartData={dataWithLegend}
25
- id="with-legend-example"
26
- legend
27
- {...props}
28
- />
29
- </div>
30
- )
31
+ return (
32
+ <div>
33
+ <HighchartsReact
34
+ highcharts={Highcharts}
35
+ options={options}
36
+ />
37
+ </div>
38
+ )
39
+ }
31
40
 
32
- export default CircleChartWithLegendKit
41
+ export default CircleChartWithLegendKit
@@ -1,47 +1,55 @@
1
1
  import React from 'react'
2
-
3
- import CircleChart from '../_circle_chart'
2
+ import circleChartTheme from '../circleChartTheme'
3
+ import Highcharts from "highcharts"
4
+ import HighchartsReact from "highcharts-react-official"
4
5
 
5
6
  const dataWithTitle = [
6
7
  {
7
8
  name: 'Facebook',
8
- value: 2498,
9
+ y: 2498,
9
10
  },
10
11
  {
11
12
  name: 'YouTube',
12
- value: 2000,
13
+ y: 2000,
13
14
  },
14
15
  {
15
16
  name: 'WhatsApp',
16
- value: 2000,
17
+ y: 2000,
17
18
  },
18
19
  {
19
20
  name: 'Facebook Messenger',
20
- value: 1300,
21
+ y: 1300,
21
22
  },
22
23
  {
23
24
  name: 'WeChat',
24
- value: 1165,
25
+ y: 1165,
25
26
  },
26
27
  {
27
28
  name: 'Instagram',
28
- value: 1000,
29
+ y: 1000,
29
30
  },
30
31
  {
31
32
  name: 'Tik Tok',
32
- value: 800,
33
+ y: 800,
33
34
  },
34
35
  ]
35
36
 
36
- const CircleChartWithLegendKit = (props) => (
37
- <div>
38
- <CircleChart
39
- chartData={dataWithTitle}
40
- id="with-title-example"
41
- title="Active Users on Social Media"
42
- {...props}
43
- />
44
- </div>
45
- )
37
+ const CircleChartWithTitle = () => {
38
+ const chartOptions = {
39
+ title: { text: "Active Users on Social Media" },
40
+ series: [{ data: dataWithTitle }],
41
+ }
42
+
43
+ const options = Highcharts.merge({}, circleChartTheme, chartOptions)
44
+
45
+ return (
46
+ <div>
47
+ <HighchartsReact
48
+ highcharts={Highcharts}
49
+ options={options}
50
+ />
51
+ </div>
52
+ )
53
+ }
46
54
 
47
- export default CircleChartWithLegendKit
55
+ export default CircleChartWithTitle
@@ -0,0 +1 @@
1
+ **Important Note for the React Kit**: In order to leverage this kit, you must install `highcharts` and `highcharts-react-official` into your project as shown below. To then apply Playbook styles to your Highchart, import circleChartTheme.ts from playbook-ui and merge it with your Highchart options. Then, pass the merged value to the options prop. Playbook’s styling will be applied automatically. See the examples in the documentation below.
@@ -14,7 +14,6 @@ examples:
14
14
 
15
15
  react:
16
16
  - circle_chart_default: Default Style
17
- - circle_chart_pb_styles: Playbook Styles
18
17
  - circle_chart_live_data: Live Data
19
18
  - circle_chart_rounded: Rounded Corners
20
19
  - circle_chart_block: Accepts Any Block
@@ -9,4 +9,3 @@ export { default as CircleChartLegendPosition } from './_circle_chart_legend_pos
9
9
  export { default as CircleChartWithTitle } from './_circle_chart_with_title.jsx'
10
10
  export { default as CircleChartInnerSizes } from './_circle_chart_inner_sizes.jsx'
11
11
  export { default as CircleChartCustomTooltip } from "./_circle_chart_custom_tooltip.jsx"
12
- export { default as CircleChartPbStyles } from "./_circle_chart_pb_styles.jsx"
@@ -3,7 +3,7 @@ import { InitialStateType, ActionType, DraggableProviderType } from "./types";
3
3
 
4
4
  const initialState: InitialStateType = {
5
5
  items: [],
6
- dragData: { id: "", initialGroup: "", originId: "" },
6
+ dragData: { id: "", initialGroup: "" },
7
7
  isDragging: "",
8
8
  activeContainer: ""
9
9
  };
@@ -60,8 +60,7 @@ export const DraggableProvider = ({
60
60
  onDragEnd,
61
61
  onDrop,
62
62
  onDragOver,
63
- dropZone = { type: 'ghost', color: 'neutral', direction: 'vertical' },
64
- providerId = 'default', // fallback provided for backward compatibility, so this does not become a required prop
63
+ dropZone = { type: 'ghost', color: 'neutral', direction: 'vertical' }
65
64
  }: DraggableProviderType) => {
66
65
  const [state, dispatch] = useReducer(reducer, initialState);
67
66
 
@@ -94,17 +93,15 @@ export const DraggableProvider = ({
94
93
  }, [state.items]);
95
94
 
96
95
  const handleDragStart = (id: string, container: string) => {
97
- dispatch({ type: 'SET_DRAG_DATA', payload: { id: id, initialGroup: container, originId: providerId } });
96
+ dispatch({ type: 'SET_DRAG_DATA', payload: { id: id, initialGroup: container } });
98
97
  dispatch({ type: 'SET_IS_DRAGGING', payload: id });
99
98
  if (onDragStart) onDragStart(id, container);
100
99
  };
101
100
 
102
101
  const handleDragEnter = (id: string, container: string) => {
103
- if (state.dragData.originId !== providerId) return; // Ignore drag events from other providers
104
-
105
102
  if (state.dragData.id !== id) {
106
103
  dispatch({ type: 'REORDER_ITEMS', payload: { dragId: state.dragData.id, targetId: id } });
107
- dispatch({ type: 'SET_DRAG_DATA', payload: { id: state.dragData.id, initialGroup: container, originId: providerId } });
104
+ dispatch({ type: 'SET_DRAG_DATA', payload: { id: state.dragData.id, initialGroup: container } });
108
105
  }
109
106
  if (onDragEnter) onDragEnter(id, container);
110
107
  };
@@ -112,7 +109,6 @@ export const DraggableProvider = ({
112
109
  const handleDragEnd = () => {
113
110
  dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
114
111
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
115
- dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
116
112
  if (onDragEnd) onDragEnd();
117
113
  };
118
114
 
@@ -121,8 +117,6 @@ export const DraggableProvider = ({
121
117
  };
122
118
 
123
119
  const handleDrop = (container: string) => {
124
- if (state.dragData.originId !== providerId) return; // Ignore drop events from other providers
125
-
126
120
  dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
127
121
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
128
122
  changeCategory(state.dragData.id, container);
@@ -130,8 +124,6 @@ export const DraggableProvider = ({
130
124
  };
131
125
 
132
126
  const handleDragOver = (e: Event, container: string) => {
133
- if (state.dragData.originId !== providerId) return; // Ignore drag over events from other providers
134
-
135
127
  e.preventDefault();
136
128
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: container });
137
129
  if (onDragOver) onDragOver(e, container);
@@ -6,16 +6,14 @@ export interface ItemType {
6
6
 
7
7
  export interface InitialStateType {
8
8
  items: ItemType[];
9
- dragData: { id: string; initialGroup: string, originId?: string };
9
+ dragData: { id: string; initialGroup: string };
10
10
  isDragging: string;
11
11
  activeContainer: string;
12
12
  }
13
13
 
14
14
  export type ActionType =
15
15
  | { type: 'SET_ITEMS'; payload: ItemType[] }
16
- | { type: 'SET_DRAG_DATA'; payload: {
17
- originId: string; id: string; initialGroup: string
18
- } }
16
+ | { type: 'SET_DRAG_DATA'; payload: { id: string; initialGroup: string } }
19
17
  | { type: 'SET_IS_DRAGGING'; payload: string }
20
18
  | { type: 'SET_ACTIVE_CONTAINER'; payload: string }
21
19
  | { type: 'CHANGE_CATEGORY'; payload: { itemId: string; container: string } }
@@ -37,5 +35,4 @@ export type ActionType =
37
35
  onDrop?: (container: string) => void;
38
36
  onDragOver?: (e: Event, container: string) => void;
39
37
  dropZone?: DropZoneConfig | string; // Can accept string for backward compatibility
40
- providerId?: string;
41
38
  }
@@ -0,0 +1,14 @@
1
+ <%= pb_rails("button", props: {
2
+ text: "Click to Open",
3
+ id: "click-tooltip-trigger-1",
4
+ variant: "primary"
5
+ }) %>
6
+
7
+ <%= pb_rails("tooltip", props: {
8
+ trigger_element_selector: "#click-tooltip-trigger-1",
9
+ tooltip_id: "click-tooltip-1",
10
+ position: "top",
11
+ use_click_to_open: true
12
+ }) do %>
13
+ Tooltip opened by click! Click trigger again to close.
14
+ <% end %>
@@ -0,0 +1 @@
1
+ Set the prop `use_click_to_open` as `true` so that the tooltip will only appear when an item is clicked rather than hovered over.
@@ -9,6 +9,7 @@ examples:
9
9
  - tooltip_with_icon_circle: Icon Circle Tooltip
10
10
  - tooltip_delay_rails: Delay
11
11
  - tooltip_show_tooltip: Show Tooltip
12
+ - tooltip_click_open: Click to Open
12
13
 
13
14
  react:
14
15
  - tooltip_default_react: Default
@@ -19,60 +19,75 @@ export default class PbTooltip extends PbEnhancedElement {
19
19
  }
20
20
 
21
21
  this.triggerElements.forEach((trigger) => {
22
- const method = this.triggerMethod
22
+ const method = this.effectiveTriggerMethod
23
23
  const interactionEnabled = this.tooltipInteraction
24
24
 
25
25
  if (method === 'click') {
26
- trigger.addEventListener('click', () => {
27
- this.showTooltip(trigger)
28
- })
29
- } else {
30
- trigger.addEventListener('mouseenter', () => {
31
- clearSafeZoneListener(this)
32
- clearTimeout(this.mouseleaveTimeout)
33
- this.currentTrigger = trigger
34
- const delayOpen = this.delayOpen ? parseInt(this.delayOpen) : TOOLTIP_TIMEOUT
35
- this.mouseenterTimeout = setTimeout(() => {
36
- this.showTooltip(trigger)
37
- if (interactionEnabled) {
38
- this.checkCloseTooltip(trigger)
26
+ trigger.addEventListener('click', (e) => {
27
+ if (this.useClickToOpen) {
28
+ e.preventDefault()
29
+ if (this.isTooltipVisible()) {
30
+ this.hideTooltip()
31
+ } else {
32
+ this.showTooltip(trigger)
39
33
  }
40
- }, delayOpen)
34
+ } else {
35
+ this.showTooltip(trigger)
36
+ }
41
37
  })
38
+ } else {
39
+ if (!this.useClickToOpen) {
40
+ trigger.addEventListener('mouseenter', () => {
41
+ clearSafeZoneListener(this)
42
+ clearTimeout(this.mouseleaveTimeout)
43
+ this.currentTrigger = trigger
44
+ const delayOpen = this.delayOpen ? parseInt(this.delayOpen) : TOOLTIP_TIMEOUT
45
+ this.mouseenterTimeout = setTimeout(() => {
46
+ this.showTooltip(trigger)
47
+ if (interactionEnabled) {
48
+ this.checkCloseTooltip(trigger)
49
+ }
50
+ }, delayOpen)
51
+ })
42
52
 
43
- trigger.addEventListener('mouseleave', () => {
44
- clearTimeout(this.mouseenterTimeout)
45
- if (this.delayClose) {
46
- const delayClose = parseInt(this.delayClose)
47
- this.mouseleaveTimeout = setTimeout(() => {
53
+ trigger.addEventListener('mouseleave', () => {
54
+ clearTimeout(this.mouseenterTimeout)
55
+ if (this.delayClose) {
56
+ const delayClose = parseInt(this.delayClose)
57
+ this.mouseleaveTimeout = setTimeout(() => {
58
+ if (interactionEnabled) {
59
+ this.attachSafeZoneListener()
60
+ } else {
61
+ this.hideTooltip()
62
+ }
63
+ }, delayClose)
64
+ } else {
48
65
  if (interactionEnabled) {
49
66
  this.attachSafeZoneListener()
50
67
  } else {
51
68
  this.hideTooltip()
52
69
  }
53
- }, delayClose)
54
- } else {
55
- if (interactionEnabled) {
56
- this.attachSafeZoneListener()
57
- } else {
58
- this.hideTooltip()
59
70
  }
60
- }
61
- })
62
-
63
- if (interactionEnabled) {
64
- this.tooltip.addEventListener('mouseenter', () => {
65
- clearSafeZoneListener(this)
66
71
  })
67
72
 
68
- this.tooltip.addEventListener('mouseleave', () => {
69
- this.attachSafeZoneListener()
70
- })
73
+ if (interactionEnabled) {
74
+ this.tooltip.addEventListener('mouseenter', () => {
75
+ clearSafeZoneListener(this)
76
+ })
77
+
78
+ this.tooltip.addEventListener('mouseleave', () => {
79
+ this.attachSafeZoneListener()
80
+ })
81
+ }
71
82
  }
72
83
  }
73
84
  })
74
85
  }
75
86
 
87
+ isTooltipVisible() {
88
+ return this.tooltip && this.tooltip.classList.contains('show')
89
+ }
90
+
76
91
  attachSafeZoneListener() {
77
92
  clearSafeZoneListener(this)
78
93
  this.safeZoneHandler = (e) => {
@@ -145,7 +160,7 @@ export default class PbTooltip extends PbEnhancedElement {
145
160
 
146
161
  this.tooltip.classList.add('show')
147
162
 
148
- if (this.triggerMethod === 'click') {
163
+ if (this.effectiveTriggerMethod === 'click' && !this.useClickToOpen) {
149
164
  clearTimeout(this.autoHideTimeout)
150
165
  this.autoHideTimeout = setTimeout(() => {
151
166
  this.hideTooltip()
@@ -224,6 +239,14 @@ export default class PbTooltip extends PbEnhancedElement {
224
239
  return this.element.dataset.pbTooltipTriggerMethod || 'hover'
225
240
  }
226
241
 
242
+ get useClickToOpen() {
243
+ return this.element.dataset.pbTooltipUseClickToOpen === 'true'
244
+ }
245
+
246
+ get effectiveTriggerMethod() {
247
+ return this.useClickToOpen ? 'click' : this.triggerMethod
248
+ }
249
+
227
250
  get tooltipInteraction() {
228
251
  return this.element.dataset.pbTooltipInteraction === 'true'
229
252
  }
@@ -21,6 +21,8 @@ module Playbook
21
21
  prop :trigger_method, type: Playbook::Props::Enum,
22
22
  values: %w[hover click],
23
23
  default: "hover"
24
+ prop :use_click_to_open, type: Playbook::Props::Boolean,
25
+ default: false
24
26
  prop :width
25
27
 
26
28
  def classname
@@ -46,6 +48,10 @@ module Playbook
46
48
  out
47
49
  end
48
50
 
51
+ def effective_trigger_method
52
+ use_click_to_open ? "click" : (trigger_method || "hover")
53
+ end
54
+
49
55
  def data
50
56
  data = Hash(values[:data]).merge(
51
57
  pb_tooltip_kit: true,
@@ -54,8 +60,9 @@ module Playbook
54
60
  pb_tooltip_trigger_element_id: trigger_element_id,
55
61
  pb_tooltip_tooltip_id: tooltip_id,
56
62
  pb_tooltip_show_tooltip: true,
57
- pb_tooltip_trigger_method: trigger_method,
58
- pb_tooltip_interaction: interaction
63
+ pb_tooltip_trigger_method: effective_trigger_method,
64
+ pb_tooltip_interaction: interaction,
65
+ pb_tooltip_use_click_to_open: use_click_to_open
59
66
  )
60
67
  data = data.merge(pb_tooltip_delay_open: delay_open) if delay_open
61
68
  data = data.merge(pb_tooltip_delay_close: delay_close) if delay_close