playbook_ui 13.11.1 → 13.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_collapsible/collapsible_content.rb +3 -1
  3. data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_external_controls.html.erb +22 -0
  4. data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_external_controls.md +3 -0
  5. data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_external_controls_multiple.html.erb +40 -0
  6. data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_external_controls_multiple.md +1 -0
  7. data/app/pb_kits/playbook/pb_collapsible/docs/example.yml +2 -0
  8. data/app/pb_kits/playbook/pb_collapsible/index.js +4 -0
  9. data/app/pb_kits/playbook/pb_icon/docs/_icon_border_swift.md +7 -0
  10. data/app/pb_kits/playbook/pb_icon/docs/_icon_default_swift.md +7 -0
  11. data/app/pb_kits/playbook/pb_icon/docs/_icon_flip_swift.md +11 -0
  12. data/app/pb_kits/playbook/pb_icon/docs/_icon_props_swift.md +8 -0
  13. data/app/pb_kits/playbook/pb_icon/docs/_icon_rotate_swift.md +11 -0
  14. data/app/pb_kits/playbook/pb_icon/docs/_icon_sizes_swift.md +46 -0
  15. data/app/pb_kits/playbook/pb_icon/docs/example.yml +8 -0
  16. data/app/pb_kits/playbook/pb_image/docs/_image_props_swift.md +7 -0
  17. data/app/pb_kits/playbook/pb_image/docs/_rounded_image_swift.md +47 -0
  18. data/app/pb_kits/playbook/pb_image/docs/_size_image_swift.md +47 -0
  19. data/app/pb_kits/playbook/pb_image/docs/_size_none_image_swift.md +15 -0
  20. data/app/pb_kits/playbook/pb_image/docs/example.yml +5 -0
  21. data/app/pb_kits/playbook/pb_label_value/docs/_label_value_default_swift.md +11 -0
  22. data/app/pb_kits/playbook/pb_label_value/docs/_label_value_details_examples_swift.md +72 -0
  23. data/app/pb_kits/playbook/pb_label_value/docs/_label_value_details_swift.md +41 -0
  24. data/app/pb_kits/playbook/pb_label_value/docs/_label_value_props_swift.md +11 -0
  25. data/app/pb_kits/playbook/pb_label_value/docs/example.yml +6 -0
  26. data/app/pb_kits/playbook/pb_message/docs/_message_default_swift.md +57 -0
  27. data/app/pb_kits/playbook/pb_message/docs/_message_props_swift.md +12 -0
  28. data/app/pb_kits/playbook/pb_message/docs/example.yml +4 -0
  29. data/app/pb_kits/playbook/pb_table/docs/_table_header.html.erb +4 -4
  30. data/app/pb_kits/playbook/pb_table/styles/_hover.scss +26 -2
  31. data/app/pb_kits/playbook/pb_table/styles/_table-dark.scss +1 -17
  32. data/app/pb_kits/playbook/pb_table/table_header.html.erb +4 -3
  33. data/app/pb_kits/playbook/pb_table/table_header.rb +28 -5
  34. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +25 -9
  35. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_default.html.erb +1 -1
  36. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_default_react.jsx +0 -2
  37. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay.jsx +0 -1
  38. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_interaction.jsx +0 -1
  39. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_margin.jsx +0 -1
  40. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_selectors.html.erb +1 -1
  41. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_show_tooltip.html.erb +39 -0
  42. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_show_tooltip.md +5 -0
  43. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_show_tooltip_react.jsx +45 -0
  44. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_show_tooltip_react.md +3 -0
  45. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +3 -0
  46. data/app/pb_kits/playbook/pb_tooltip/docs/index.js +1 -0
  47. data/app/pb_kits/playbook/pb_tooltip/index.js +6 -0
  48. data/app/pb_kits/playbook/pb_tooltip/tooltip.rb +2 -1
  49. data/app/pb_kits/playbook/pb_tooltip/tooltip.test.jsx +34 -0
  50. data/app/pb_kits/playbook/playbook-doc.js +1 -1
  51. data/dist/playbook-rails.js +3 -3
  52. data/lib/playbook/version.rb +2 -2
  53. metadata +26 -2
@@ -1,6 +1,7 @@
1
1
  @import "../../tokens/opacity";
2
2
 
3
3
  $transition-speed: 0.2s;
4
+ $border_hover_color_dark: lighten($border_dark, 5%);
4
5
 
5
6
  [class^=pb_table] {
6
7
  &.table-sm,
@@ -15,9 +16,9 @@ $transition-speed: 0.2s;
15
16
  td {
16
17
  border-top-color: transparent;
17
18
  border-top-width: 0;
18
- transition: all $transition-speed ease;
19
+ transition: all $transition-speed ease;
19
20
  }
20
- @media (hover:hover) {
21
+ @media (hover:hover) {
21
22
  td {
22
23
  position: relative;
23
24
  &:after {
@@ -69,6 +70,29 @@ $transition-speed: 0.2s;
69
70
  }
70
71
  }
71
72
  }
73
+
74
+ &.dark {
75
+ tbody {
76
+ tr {
77
+ @media (hover:hover) {
78
+ &:hover {
79
+ box-shadow: 0 2px 10px 0 $shadow_dark;
80
+ td {
81
+ border-top-width: 0;
82
+ border-top-color: transparent;
83
+ border-color: $border_hover_color_dark !important;
84
+ &:after {
85
+ transition: background-color $transition-speed ease, height $transition-speed ease;
86
+ background-color: $border_hover_color_dark !important;
87
+ height: 1px;
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
95
+
72
96
  }
73
97
  }
74
98
  }
@@ -1,6 +1,6 @@
1
1
  @import "../../tokens/screen_sizes";
2
2
 
3
- $table-dark-card-bg: $bg_dark;
3
+ $table-dark-card-bg: $card_dark;
4
4
 
5
5
  [class^=pb_table] {
6
6
  &.table-sm,
@@ -24,7 +24,6 @@ $table-dark-card-bg: $bg_dark;
24
24
 
25
25
  td {
26
26
  border-color: $border_dark !important;
27
- border-bottom-width: 0 !important;
28
27
  color: $white;
29
28
 
30
29
  &:before {
@@ -39,21 +38,6 @@ $table-dark-card-bg: $bg_dark;
39
38
  }
40
39
  }
41
40
 
42
- &:not(.no-hover) {
43
- tbody {
44
- tr {
45
- @media (hover:hover) {
46
- &:hover {
47
- td {
48
- border-color: $border_dark !important;
49
- background: $bg_dark;
50
- }
51
- }
52
- }
53
- }
54
- }
55
- }
56
-
57
41
  &.table-card {
58
42
  background: $table-dark-card-bg !important;
59
43
  }
@@ -28,15 +28,16 @@
28
28
  position: object.placement ,
29
29
  padding: 'none'}) do %>
30
30
  <%= pb_rails("nav", props: {classname: "pb_table_header_dropdown"}) do %>
31
- <% object.sort_menu.each_with_index do |item, index| %>
31
+ <% object.sort_items.each do |sort_item| %>
32
+ <% item = active_or_first_item(sort_items_for(sort_item)) %>
32
33
  <%= pb_rails("nav/item", props: {
33
34
  text: item[:item],
34
- link: item[:link],
35
+ link: next_link(sort_item: sort_item),
35
36
  highlighted_border: false,
36
37
  padding: "xs",
37
38
  icon_right: sort_icon(item[:direction], item[:active]),
38
39
  active: item[:active],
39
- classname: "header_nav_item #{'header_first_item' if index == 0} #{'header_last_item' if index == object.sort_menu.size - 1}"
40
+ classname: "header_nav_item"
40
41
  }) %>
41
42
  <% end %>
42
43
  <% end %>
@@ -32,20 +32,43 @@ module Playbook
32
32
  align.present? ? "align_#{align}" : nil
33
33
  end
34
34
 
35
- def next_link
36
- return sort_menu[0][:link] if sort_menu.all? { |item| item[:active] == false }
35
+ def next_link(sort_item: "")
36
+ sort_menu_for = if sort_item.blank?
37
+ sort_menu
38
+ else
39
+ sort_items_for(sort_item)
40
+ end
41
+
42
+ return sort_menu_for[0][:link] if sort_menu_for.all? { |item| item[:active] == false }
37
43
 
38
44
  link = ""
39
45
 
40
- sort_menu.each_with_index do |item, index|
46
+ sort_menu_for.each_with_index do |item, index|
41
47
  if item[:active] == true
42
- next_index = (index + 1) % sort_menu.length
43
- link = sort_menu[next_index][:link]
48
+ next_index = (index + 1) % sort_menu_for.length
49
+ link = sort_menu_for[next_index][:link]
44
50
  end
45
51
  end
46
52
  link
47
53
  end
48
54
 
55
+ def sort_items
56
+ sort_menu.map { |hash| hash[:item] }.uniq
57
+ end
58
+
59
+ def sort_items_for(sort_item)
60
+ sort_menu.find_all { |hash| hash[:item] == sort_item }
61
+ end
62
+
63
+ def active_or_first_item(items)
64
+ active_item = items.find { |hash| hash[:active] == true }
65
+ if active_item.present?
66
+ active_item
67
+ else
68
+ items[0]
69
+ end
70
+ end
71
+
49
72
  def sorting_style?
50
73
  sort_menu != [{}]
51
74
  end
@@ -1,4 +1,4 @@
1
- import React, { useRef, useState } from "react"
1
+ import React, { useRef, useState, forwardRef, ForwardedRef } from "react"
2
2
 
3
3
  import {
4
4
  arrow,
@@ -28,9 +28,10 @@ type TooltipProps = {
28
28
  placement?: Placement,
29
29
  position?: "absolute" | "fixed";
30
30
  text: string,
31
+ showTooltip?: boolean,
31
32
  } & GlobalProps
32
33
 
33
- const Tooltip = (props: TooltipProps): React.ReactElement => {
34
+ const Tooltip = forwardRef((props: TooltipProps, ref: ForwardedRef<unknown>): React.ReactElement => {
34
35
  const {
35
36
  aria = {},
36
37
  className,
@@ -42,6 +43,7 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
42
43
  placement: preferredPlacement = "top",
43
44
  position = "absolute",
44
45
  text,
46
+ showTooltip = true,
45
47
  zIndex,
46
48
  ...rest
47
49
  } = props
@@ -59,10 +61,9 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
59
61
 
60
62
  const {
61
63
  context,
62
- floating,
63
64
  middlewareData: { arrow: { x: arrowX, y: arrowY } = {}, },
64
65
  placement,
65
- reference,
66
+ refs,
66
67
  strategy,
67
68
  x,
68
69
  y,
@@ -82,12 +83,16 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
82
83
  ],
83
84
  open,
84
85
  onOpenChange(open) {
85
- setOpen(open)
86
+ if(!showTooltip) {
87
+ return
88
+ } else {
89
+ setOpen(open)
90
+ }
86
91
  },
87
92
  placement: preferredPlacement
88
93
  })
89
94
 
90
-
95
+
91
96
  const { getFloatingProps } = useInteractions([
92
97
  useHover(context, {
93
98
  delay,
@@ -108,7 +113,16 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
108
113
  <>
109
114
  <div
110
115
  className={`pb_tooltip_kit ${css}`}
111
- ref={reference}
116
+ ref={(element) => {
117
+ refs.setReference(element);
118
+ if (ref) {
119
+ if (typeof ref === "function") {
120
+ ref(element);
121
+ } else if (typeof ref === "object") {
122
+ ref.current = element;
123
+ }
124
+ }
125
+ }}
112
126
  role="tooltip_trigger"
113
127
  style={{ display: "inline-flex" }}
114
128
  {...ariaProps}
@@ -120,7 +134,7 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
120
134
  <div
121
135
  {...getFloatingProps({
122
136
  className: `tooltip_tooltip ${placement} visible`,
123
- ref: floating,
137
+ ref: refs.setFloating,
124
138
  role: "tooltip",
125
139
  style: {
126
140
  position: strategy,
@@ -153,6 +167,8 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
153
167
  )}
154
168
  </>
155
169
  )
156
- }
170
+ })
171
+
172
+ Tooltip.displayName = "Tooltip"
157
173
 
158
174
  export default Tooltip
@@ -1,4 +1,4 @@
1
- <%= pb_rails("flex", props: { gap: "md", justify: "center", wrap: true }) do %>
1
+ <%= pb_rails("flex", props: { gap: "md", wrap: true }) do %>
2
2
  <%= pb_rails("flex/flex_item") do %>
3
3
  <span id='regular-tooltip-1'>Hover here (Top)</span>
4
4
 
@@ -9,12 +9,10 @@ const TooltipDefaultReact = (props) => {
9
9
  <Flex
10
10
  flexDirection='row'
11
11
  gap='md'
12
- justifyContent='center'
13
12
  wrap
14
13
  >
15
14
  <FlexItem>
16
15
  <Tooltip
17
- className={"customClassNameHere"}
18
16
  placement='top'
19
17
  text="Whoa. I'm a Tooltip"
20
18
  zIndex={10}
@@ -9,7 +9,6 @@ const TooltipDelay = (props) => {
9
9
  <Flex
10
10
  flexDirection='row'
11
11
  gap='md'
12
- justifyContent='center'
13
12
  wrap
14
13
  >
15
14
  <FlexItem>
@@ -9,7 +9,6 @@ const TooltipInteraction = (props) => {
9
9
  <Flex
10
10
  flexDirection='row'
11
11
  gap='md'
12
- justifyContent='center'
13
12
  wrap
14
13
  >
15
14
  <FlexItem>
@@ -7,7 +7,6 @@ const TooltipMargin = (props) => {
7
7
  return (
8
8
  <Flex
9
9
  flexDirection='row'
10
- justifyContent='center'
11
10
  wrap
12
11
  >
13
12
  <Tooltip
@@ -1,4 +1,4 @@
1
- <%= pb_rails("flex", props: { horizontal: "center", orientation: "column" }) do %>
1
+ <%= pb_rails("flex", props: { orientation: "column" }) do %>
2
2
  <%= pb_rails("flex/flex_item", props: {margin_top: "md"}) do %>
3
3
  <%= pb_rails("button", props: {classname: "tooltip-example-trigger", text: "Example 1"}) %>
4
4
  <% end %>
@@ -0,0 +1,39 @@
1
+
2
+ <%= pb_rails("flex", props: { orientation: "column", gap: "md" }) do %>
3
+ <%= pb_rails("button", props: {text: "Toggle state", id: "toggle-tooltip-button"}) %>
4
+ <%= pb_rails("body") do %>
5
+ Tooltip is: <code id="show-tooltip-state">enabled</code>
6
+ <% end %>
7
+ <%= pb_rails("flex/flex_item") do %>
8
+ <span id="truncated-tooltip-1">Hover me</span>
9
+ <%= pb_rails("tooltip", props: {
10
+ trigger_element_selector: "#truncated-tooltip-1",
11
+ tooltip_id: "truncated-1",
12
+ position: "right",
13
+ }) do %>
14
+ Tooltip is enabled
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
18
+
19
+
20
+ <script>
21
+ const toggleTooltipButton = document.getElementById("toggle-tooltip-button");
22
+ const showTooltipStateText = document.getElementById("show-tooltip-state");
23
+
24
+ function hideTooltipIfNotTruncated(tooltipId) {
25
+ const tooltipElement = document.querySelector(
26
+ `[data-pb-tooltip-tooltip-id="${tooltipId}"]`
27
+ );
28
+
29
+ tooltipElement.dataset.pbTooltipShowTooltip =
30
+ tooltipElement.dataset.pbTooltipShowTooltip == "false" ? "true" : "false";
31
+
32
+ showTooltipStateText.innerText =
33
+ tooltipElement.dataset.pbTooltipShowTooltip == "false" ? "disabled" : "enabled";
34
+ }
35
+
36
+ toggleTooltipButton.addEventListener("click", () => {
37
+ hideTooltipIfNotTruncated("truncated-1");
38
+ });
39
+ </script>
@@ -0,0 +1,5 @@
1
+ You can build your own logic to control whether to show or hide the tooltip.
2
+
3
+ Click on the `Toggle state` button to change the state of the component and hover over the 'hover me' text to see it in action.
4
+
5
+ Each Tooltip has a `dataset` with the `pbTooltipShowTooltip` property set to true by default. To update it, access the `pbTooltipShowTooltip` in the dataset of your tooltip element: `yourTooltip.dataset.pbTooltipShowTooltip = 'false'`
@@ -0,0 +1,45 @@
1
+ // @flow
2
+
3
+ import React, { useState } from 'react'
4
+ import { Button, Body, Flex, FlexItem, Tooltip } from '../..'
5
+
6
+ const TooltipShowTooltipReact = (props) => {
7
+ const [showTooltip, setShowTooltip] = useState(true);
8
+
9
+ return (
10
+ <Flex
11
+ flexDirection='column'
12
+ gap='md'
13
+ wrap
14
+ >
15
+ <FlexItem>
16
+ <Button
17
+ onClick={()=> setShowTooltip(!showTooltip)}
18
+ text="Toggle state"
19
+ />
20
+ </FlexItem>
21
+ <FlexItem>
22
+ <Body >
23
+ <p>
24
+ {'Tooltip is: '}
25
+ <code>{showTooltip ? "enabled" : "disabled"}</code>
26
+ </p>
27
+ </Body>
28
+ </FlexItem>
29
+ <FlexItem>
30
+ <Tooltip
31
+ placement='right'
32
+ showTooltip={showTooltip}
33
+ text='Tooltip is enabled'
34
+ zIndex={10}
35
+ {...props}
36
+ >
37
+ {'Hover me.'}
38
+ </Tooltip>
39
+ </FlexItem>
40
+
41
+ </Flex>
42
+ )
43
+ }
44
+
45
+ export default TooltipShowTooltipReact
@@ -0,0 +1,3 @@
1
+ You can build your own logic to control whether to show the tooltip using the `showTooltip` prop. Its default value is `true`.
2
+
3
+ Click on the `Toggle state` button to change the state of the component and hover over the 'hover me' text to see it in action.
@@ -4,6 +4,7 @@ examples:
4
4
  - tooltip_default: Default
5
5
  - tooltip_selectors: Using Common Selectors
6
6
  - tooltip_with_icon_circle: Icon Circle Tooltip
7
+ - tooltip_show_tooltip: Show Tooltip
7
8
 
8
9
  react:
9
10
  - tooltip_default_react: Default
@@ -11,3 +12,5 @@ examples:
11
12
  - tooltip_margin: Margin
12
13
  - tooltip_icon: Tooltip with Icon
13
14
  - tooltip_delay: Delay
15
+ - tooltip_show_tooltip_react: Show Tooltip
16
+
@@ -3,3 +3,4 @@ export { default as TooltipInteraction } from './_tooltip_interaction'
3
3
  export { default as TooltipMargin } from './_tooltip_margin'
4
4
  export { default as TooltipIcon } from './_tooltip_icon'
5
5
  export { default as TooltipDelay } from './_tooltip_delay'
6
+ export { default as TooltipShowTooltipReact } from './_tooltip_show_tooltip_react'
@@ -54,6 +54,8 @@ export default class PbTooltip extends PbEnhancedElement {
54
54
  }
55
55
 
56
56
  showTooltip(trigger) {
57
+ if (this.shouldShowTooltip === "false") return
58
+
57
59
  this.popper = createPopper(trigger, this.tooltip, {
58
60
  placement: this.position,
59
61
  modifiers: [
@@ -127,4 +129,8 @@ export default class PbTooltip extends PbEnhancedElement {
127
129
  get triggerElementSelector() {
128
130
  return this.element.dataset.pbTooltipTriggerElementSelector
129
131
  }
132
+
133
+ get shouldShowTooltip() {
134
+ return this.element.dataset.pbTooltipShowTooltip
135
+ }
130
136
  }
@@ -20,7 +20,8 @@ module Playbook
20
20
  pb_tooltip_position: position,
21
21
  pb_tooltip_trigger_element_selector: trigger_element_selector,
22
22
  pb_tooltip_trigger_element_id: trigger_element_id,
23
- pb_tooltip_tooltip_id: tooltip_id
23
+ pb_tooltip_tooltip_id: tooltip_id,
24
+ pb_tooltip_show_tooltip: true
24
25
  )
25
26
  end
26
27
 
@@ -92,5 +92,39 @@ test("has position fixed", async () => {
92
92
  cleanup();
93
93
  })
94
94
 
95
+ cleanup();
96
+ });
97
+
98
+ test("display tooltip with showTooltip set to true", async () => {
99
+ render(
100
+ <Tooltip
101
+ data={{ testid: "fixed-position-test" }}
102
+ showTooltip
103
+ />
104
+ );
105
+
106
+ fireEvent.mouseEnter(screen.getByRole("tooltip_trigger"));
107
+ await waitFor(() => {
108
+ expect(screen.queryByRole("tooltip")).toBeInTheDocument();
109
+ cleanup();
110
+ })
111
+
112
+ cleanup();
113
+ });
114
+
115
+ test("doesn't display tooltip with showTooltip set to false", async () => {
116
+ render(
117
+ <Tooltip
118
+ data={{ testid: "fixed-position-test" }}
119
+ showTooltip={false}
120
+ />
121
+ );
122
+
123
+ fireEvent.mouseEnter(screen.getByRole("tooltip_trigger"));
124
+ await waitFor(() => {
125
+ expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
126
+ cleanup();
127
+ })
128
+
95
129
  cleanup();
96
130
  });
@@ -104,7 +104,7 @@ import * as UserBadge from 'pb_user_badge/docs'
104
104
  import * as Walkthrough from 'pb_walkthrough/docs'
105
105
  import * as WeekdayStacked from 'pb_weekday_stacked/docs'
106
106
 
107
- WebpackerReact.setup({
107
+ WebpackerReact.registerComponents({
108
108
  ...Avatar,
109
109
  ...AvatarActionButton,
110
110
  ...Background,