playbook_ui 13.30.0.pre.alpha.PLAY1328fixtimelinekitglobalpropsreact3096 → 13.30.0.pre.alpha.play1367contenttagnoninputkits3159

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta_sort.html.erb +59 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta_sort.md +6 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +3 -2
  5. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +4 -4
  6. data/app/pb_kits/playbook/pb_background/background.html.erb +2 -11
  7. data/app/pb_kits/playbook/pb_body/body.html.erb +1 -6
  8. data/app/pb_kits/playbook/pb_bread_crumbs/bread_crumb_item.html.erb +1 -6
  9. data/app/pb_kits/playbook/pb_bread_crumbs/bread_crumbs.html.erb +1 -6
  10. data/app/pb_kits/playbook/pb_caption/caption.html.erb +1 -6
  11. data/app/pb_kits/playbook/pb_card/_card.tsx +4 -3
  12. data/app/pb_kits/playbook/pb_card/card.html.erb +1 -7
  13. data/app/pb_kits/playbook/pb_collapsible/index.js +6 -1
  14. data/app/pb_kits/playbook/pb_date_time_stacked/docs/_date_time_stacked_default_swift.md +33 -0
  15. data/app/pb_kits/playbook/pb_date_time_stacked/docs/_date_time_stacked_props_swift.md +18 -0
  16. data/app/pb_kits/playbook/pb_date_time_stacked/docs/example.yml +6 -1
  17. data/app/pb_kits/playbook/pb_detail/detail.html.erb +1 -6
  18. data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +30 -35
  19. data/app/pb_kits/playbook/pb_dialog/dialog_body.html.erb +2 -7
  20. data/app/pb_kits/playbook/pb_dialog/dialog_footer.html.erb +1 -5
  21. data/app/pb_kits/playbook/pb_dialog/dialog_header.html.erb +1 -6
  22. data/app/pb_kits/playbook/pb_draggable/_draggable.scss +2 -4
  23. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +70 -50
  24. data/app/pb_kits/playbook/pb_draggable/context/types.ts +26 -0
  25. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.jsx +2 -1
  26. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.md +1 -1
  27. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers.jsx +5 -1
  28. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards.jsx +11 -4
  29. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards.md +4 -2
  30. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list.jsx +2 -2
  31. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list.md +7 -1
  32. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list.jsx +6 -4
  33. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list.md +7 -0
  34. data/app/pb_kits/playbook/pb_draggable/draggable.test.jsx +142 -15
  35. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableItem.tsx +6 -5
  36. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +18 -0
  37. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +228 -218
  38. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.html.erb +9 -0
  39. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.jsx +34 -0
  40. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +2 -0
  41. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +2 -1
  42. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +14 -12
  43. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +7 -0
  44. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +17 -2
  45. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.tsx +9 -3
  46. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_custom_icon.html.erb +32 -0
  47. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_custom_icon.jsx +48 -0
  48. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/example.yml +2 -0
  49. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/index.js +1 -0
  50. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/fixed_confirmation_toast.rb +16 -11
  51. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/fixed_confirmation_toast.test.js +72 -0
  52. data/app/pb_kits/playbook/pb_flex/flex.html.erb +1 -5
  53. data/app/pb_kits/playbook/pb_hashtag/hashtag.html.erb +1 -6
  54. data/app/pb_kits/playbook/pb_highlight/highlight.html.erb +1 -5
  55. data/app/pb_kits/playbook/pb_home_address_street/home_address_street.html.erb +1 -5
  56. data/app/pb_kits/playbook/pb_icon/_icon.tsx +37 -6
  57. data/app/pb_kits/playbook/pb_icon/docs/_icon_default.html.erb +1 -1
  58. data/app/pb_kits/playbook/pb_icon/docs/_icon_default.jsx +2 -3
  59. data/app/pb_kits/playbook/pb_icon/icon.rb +21 -1
  60. data/app/pb_kits/playbook/pb_icon/icon_aliases.json +39 -0
  61. data/app/pb_kits/playbook/pb_list/_list.tsx +4 -4
  62. data/app/pb_kits/playbook/pb_list/_list_item.tsx +7 -3
  63. data/app/pb_kits/playbook/pb_nav/docs/_collapsible_nav.html.erb +1 -1
  64. data/app/pb_kits/playbook/pb_nav/docs/_collapsible_nav.jsx +1 -0
  65. data/app/pb_kits/playbook/pb_nav/docs/_collapsible_nav.md +3 -1
  66. data/app/pb_kits/playbook/pb_nav/item.html.erb +1 -1
  67. data/app/pb_kits/playbook/pb_nav/item.rb +1 -0
  68. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_default.html.erb +24 -0
  69. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_default.md +4 -4
  70. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_multi_directional.html.erb +11 -0
  71. data/app/pb_kits/playbook/pb_overlay/docs/example.yml +4 -0
  72. data/app/pb_kits/playbook/pb_overlay/overlay.html.erb +27 -0
  73. data/app/pb_kits/playbook/pb_overlay/overlay.rb +110 -0
  74. data/app/pb_kits/playbook/pb_selectable_list/_item.tsx +7 -3
  75. data/app/pb_kits/playbook/pb_selectable_list/_selectable_list.tsx +3 -3
  76. data/app/pb_kits/playbook/pb_table/table_header.html.erb +16 -2
  77. data/app/pb_kits/playbook/utilities/globalProps.ts +1 -0
  78. data/dist/menu.yml +2 -2
  79. data/dist/playbook-rails.js +7 -7
  80. data/lib/playbook/version.rb +1 -1
  81. metadata +18 -2
@@ -23,6 +23,7 @@ type FixedConfirmationToastProps = {
23
23
  data?: string;
24
24
  horizontal?: "right" | "left" | "center";
25
25
  htmlOptions?: { [key: string]: string | number | boolean | (VoidCallback) };
26
+ icon?: string,
26
27
  id?: string;
27
28
  multiLine?: boolean;
28
29
  onClose?: VoidCallback;
@@ -41,6 +42,7 @@ const FixedConfirmationToast = (props: FixedConfirmationToastProps): React.React
41
42
  closeable = false,
42
43
  horizontal,
43
44
  htmlOptions = {},
45
+ icon,
44
46
  multiLine = false,
45
47
  onClose = () => undefined,
46
48
  open = true,
@@ -48,14 +50,18 @@ const FixedConfirmationToast = (props: FixedConfirmationToastProps): React.React
48
50
  text,
49
51
  vertical,
50
52
  } = props;
53
+
54
+ const returnedIcon = icon || iconMap[status]
55
+ const iconClass = icon ? "custom_icon" : ""
56
+
51
57
  const css = classnames(
52
58
  `pb_fixed_confirmation_toast_kit_${status}`,
53
59
  { _multi_line: multiLine },
54
60
  { [`positioned_toast ${vertical} ${horizontal}`]: vertical && horizontal },
61
+ `${iconClass}`,
55
62
  globalProps(props),
56
63
  className
57
64
  );
58
- const icon = iconMap[status];
59
65
 
60
66
  const htmlProps = buildHtmlProps(htmlOptions);
61
67
 
@@ -86,11 +92,11 @@ const FixedConfirmationToast = (props: FixedConfirmationToastProps): React.React
86
92
  onClick={handleClick}
87
93
  {...htmlProps}
88
94
  >
89
- {icon && (
95
+ {returnedIcon && (
90
96
  <Icon
91
97
  className="pb_icon"
92
98
  fixedWidth
93
- icon={icon}
99
+ icon={returnedIcon}
94
100
  />
95
101
  )}
96
102
 
@@ -0,0 +1,32 @@
1
+ <div>
2
+ <%= pb_rails("fixed_confirmation_toast", props: {
3
+ icon: "wrench",
4
+ text: "Fix before proceeding",
5
+ status: "error",
6
+ closeable: true,
7
+ margin_bottom: "md"
8
+ })%>
9
+ </div>
10
+ <div>
11
+ <%= pb_rails("fixed_confirmation_toast", props: {
12
+ icon: "star",
13
+ text: "Thank you for completing the form!",
14
+ status: "success",
15
+ margin_bottom: "md"
16
+ })%>
17
+ </div>
18
+ <div>
19
+ <%= pb_rails("fixed_confirmation_toast", props: {
20
+ icon: "file-pdf",
21
+ text: "Saved as PDF",
22
+ status: "neutral",
23
+ margin_bottom: "md"
24
+ })%>
25
+ </div>
26
+ <div>
27
+ <%= pb_rails("fixed_confirmation_toast", props: {
28
+ icon: "arrow-down",
29
+ text: "New Messages",
30
+ status: "tip"
31
+ })%>
32
+ </div>
@@ -0,0 +1,48 @@
1
+ import React from 'react'
2
+
3
+ import FixedConfirmationToast from '../_fixed_confirmation_toast'
4
+
5
+ const FixedConfirmationToastCustomIcon = (props) => {
6
+ return (
7
+ <div>
8
+ <div>
9
+ <FixedConfirmationToast
10
+ closeable
11
+ icon="wrench"
12
+ marginBottom="md"
13
+ status="error"
14
+ text="Fix before proceeding"
15
+ {...props}
16
+ />
17
+ </div>
18
+ <div>
19
+ <FixedConfirmationToast
20
+ icon="star"
21
+ marginBottom="md"
22
+ status="success"
23
+ text="Thank you for completing the form!"
24
+ {...props}
25
+ />
26
+ </div>
27
+ <div>
28
+ <FixedConfirmationToast
29
+ icon="file-pdf"
30
+ marginBottom="md"
31
+ status="neutral"
32
+ text="Saved as PDF"
33
+ {...props}
34
+ />
35
+ </div>
36
+ <div>
37
+ <FixedConfirmationToast
38
+ icon="arrow-down"
39
+ status="tip"
40
+ text="New Messages"
41
+ {...props}
42
+ />
43
+ </div>
44
+ </div>
45
+ )
46
+ }
47
+
48
+ export default FixedConfirmationToastCustomIcon
@@ -6,6 +6,7 @@ examples:
6
6
  - fixed_confirmation_toast_close: Click to Close
7
7
  - fixed_confirmation_toast_positions: Click to Show Positions
8
8
  - fixed_confirmation_toast_children: Children
9
+ - fixed_confirmation_toast_custom_icon: Custom Icon
9
10
 
10
11
  react:
11
12
  - fixed_confirmation_toast_default: Default
@@ -14,6 +15,7 @@ examples:
14
15
  - fixed_confirmation_toast_positions: Click to Show Positions
15
16
  - fixed_confirmation_toast_auto_close: Click to Show Auto Close
16
17
  - fixed_confirmation_toast_children: Children
18
+ - fixed_confirmation_toast_custom_icon: Custom Icon
17
19
 
18
20
  swift:
19
21
  - fixed_confirmation_toast_default_swift: Default
@@ -4,3 +4,4 @@ export { default as FixedConfirmationToastClose } from './_fixed_confirmation_to
4
4
  export { default as FixedConfirmationToastPositions } from './_fixed_confirmation_toast_positions.jsx'
5
5
  export { default as FixedConfirmationToastAutoClose } from './_fixed_confirmation_toast_auto_close.jsx'
6
6
  export { default as FixedConfirmationToastChildren } from './_fixed_confirmation_toast_children.jsx'
7
+ export { default as FixedConfirmationToastCustomIcon } from './_fixed_confirmation_toast_custom_icon.jsx'
@@ -20,6 +20,7 @@ module Playbook
20
20
  values: [nil, "top", "bottom"],
21
21
  default: nil
22
22
  prop :auto_close, type: Playbook::Props::Number
23
+ prop :icon, type: Playbook::Props::String
23
24
 
24
25
  def show_text?
25
26
  text.present?
@@ -42,20 +43,24 @@ module Playbook
42
43
  end
43
44
 
44
45
  def icon_value
45
- case status
46
- when "success"
47
- "check"
48
- when "error"
49
- "exclamation-triangle"
50
- when "neutral"
51
- "info-circle"
52
- when "tip"
53
- "info-circle"
54
- end
46
+ icon || case status
47
+ when "success"
48
+ "check"
49
+ when "error"
50
+ "exclamation-triangle"
51
+ when "neutral"
52
+ "info-circle"
53
+ when "tip"
54
+ "info-circle"
55
+ end
56
+ end
57
+
58
+ def icon_class
59
+ icon.present? ? " custom_icon" : ""
55
60
  end
56
61
 
57
62
  def classname
58
- generate_classname("pb_fixed_confirmation_toast_kit", status, multi_line_class) + close_class + position_class + auto_close_class
63
+ generate_classname("pb_fixed_confirmation_toast_kit", status, multi_line_class) + close_class + position_class + auto_close_class + icon_class
59
64
  end
60
65
  end
61
66
  end
@@ -0,0 +1,72 @@
1
+ import React from 'react'
2
+ import { render, waitFor } from '../utilities/test-utils'
3
+
4
+ import { FixedConfirmationToast } from '../'
5
+
6
+ beforeEach(() => {
7
+ // Silences error logs within the test suite.
8
+ jest.spyOn(console, 'error')
9
+ // eslint-disable-next-line
10
+ console.error.mockImplementation(() => {})
11
+ })
12
+
13
+ afterEach(() => {
14
+ // eslint-disable-next-line
15
+ console.error.mockRestore()
16
+ })
17
+
18
+ test('renders with default props', () => {
19
+ const { container } = render(<FixedConfirmationToast />);
20
+ expect(container.firstChild).toBeInTheDocument();
21
+ });
22
+
23
+ test('renders with text', () => {
24
+ const { getByText } = render(<FixedConfirmationToast text="Message Text" />);
25
+ expect(getByText('Message Text')).toBeInTheDocument();
26
+ });
27
+
28
+ test('does not render if open prop is false', () => {
29
+ const { container } = render(<FixedConfirmationToast open={false} />);
30
+ expect(container.firstChild).toBeNull();
31
+ });
32
+
33
+ test('closes after autoClose duration', async () => {
34
+ jest.useFakeTimers();
35
+ const onCloseMock = jest.fn();
36
+ render(
37
+ <FixedConfirmationToast
38
+ autoClose={1000}
39
+ onClose={onCloseMock}
40
+ open
41
+ />
42
+ );
43
+
44
+ jest.advanceTimersByTime(1000);
45
+ await waitFor(() => expect(onCloseMock).toHaveBeenCalled());
46
+ });
47
+
48
+ test('renders success status with icon', () => {
49
+ const { container } = render(<FixedConfirmationToast status="success" />);
50
+ expect(container.querySelector('.pb_fixed_confirmation_toast_kit_success')).toBeInTheDocument();
51
+ expect(container.querySelector('.pb_icon')).toBeInTheDocument();
52
+ });
53
+
54
+ test('renders custom icon when provided', () => {
55
+ const { container } = render(<FixedConfirmationToast icon="wrench" />);
56
+ expect(container.querySelector('.custom_icon')).toBeInTheDocument();
57
+ });
58
+
59
+ test('renders correctly with multiLine prop', () => {
60
+ const { container } = render(<FixedConfirmationToast multiLine />);
61
+ expect(container.querySelector('._multi_line')).toBeInTheDocument();
62
+ });
63
+
64
+ test('renders position when provided', () => {
65
+ const { container } = render(
66
+ <FixedConfirmationToast
67
+ horizontal="right"
68
+ vertical="bottom"
69
+ />
70
+ );
71
+ expect(container.querySelector('.positioned_toast')).toBeInTheDocument();
72
+ });
@@ -1,7 +1,3 @@
1
- <%= content_tag(:div,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- **combined_html_options) do %>
1
+ <%= pb_content_tag do %>
6
2
  <%= content.presence %>
7
3
  <% end %>
@@ -1,9 +1,4 @@
1
- <%= content_tag(:span,
2
- aria: object.aria,
3
- class: object.classname,
4
- data: object.data,
5
- id: object.id,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag(:span) do %>
7
2
  <%= link_to object.url, target: object.link_option do %>
8
3
  <%= pb_rails("badge", props: { dark: object.dark, variant: "primary", text: object.hashtag_text }) %>
9
4
  <% end %>
@@ -1,8 +1,4 @@
1
- <%= content_tag(:span,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- **combined_html_options) do %>
1
+ <%= pb_content_tag(:span) do %>
6
2
  <mark>
7
3
  <%= content.presence || object.text %>
8
4
  </mark>
@@ -1,8 +1,4 @@
1
- <%= content_tag(:div,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- **combined_html_options) do %>
1
+ <%= pb_content_tag do %>
6
2
  <%= pb_rails("home_address_street/#{emphasis}_emphasis", props: object.send("#{emphasis}_emphasis_props")) %>
7
3
  <% end %>
8
4
 
@@ -3,6 +3,7 @@ import classnames from 'classnames'
3
3
  import { buildAriaProps, buildDataProps, buildHtmlProps } from '../utilities/props'
4
4
  import { GlobalProps, globalProps } from '../utilities/globalProps'
5
5
  import { isValidEmoji } from '../utilities/validEmojiChecker'
6
+ import aliasesJson from './icon_aliases.json'
6
7
 
7
8
  export type IconSizes = "lg"
8
9
  | "xs"
@@ -40,6 +41,19 @@ type IconProps = {
40
41
  spin?: boolean,
41
42
  } & GlobalProps
42
43
 
44
+ type AliasType = string | string[];
45
+
46
+ interface Aliases {
47
+ [key: string]: AliasType;
48
+ }
49
+
50
+ interface AliasesJson {
51
+ aliases: Aliases;
52
+ }
53
+
54
+ const aliases: AliasesJson = aliasesJson;
55
+
56
+
43
57
  const flipMap = {
44
58
  horizontal: 'fa-flip-horizontal',
45
59
  vertical: 'fa-flip-vertical',
@@ -52,6 +66,22 @@ declare global {
52
66
  var PB_ICONS: {[key: string]: React.FunctionComponent<any>}
53
67
  }
54
68
 
69
+ // Resolve alias function
70
+ const resolveAlias = (icon: string): string => {
71
+ const alias = aliases.aliases[icon];
72
+
73
+ if (alias) {
74
+ if (Array.isArray(alias)) {
75
+ return alias[0];
76
+ } else {
77
+ return alias;
78
+ }
79
+ }
80
+
81
+ return icon;
82
+ };
83
+
84
+
55
85
  const Icon = (props: IconProps) => {
56
86
  const {
57
87
  aria = {},
@@ -74,7 +104,8 @@ const Icon = (props: IconProps) => {
74
104
  spin = false,
75
105
  } = props
76
106
 
77
- let iconElement: ReactSVGElement | null = typeof(icon) === "object" ? icon : null
107
+ const resolvedIcon = resolveAlias(icon as string)
108
+ let iconElement: ReactSVGElement | null = typeof(resolvedIcon) === "object" ? resolvedIcon : null
78
109
 
79
110
  const faClasses = {
80
111
  'fa-border': border,
@@ -90,12 +121,12 @@ const Icon = (props: IconProps) => {
90
121
 
91
122
  if (!customIcon && !iconElement) {
92
123
  const PowerIcon: React.FunctionComponent<any> | undefined =
93
- window.PB_ICONS ? window.PB_ICONS[icon as string] : null
124
+ window.PB_ICONS ? window.PB_ICONS[resolvedIcon as string] : null
94
125
 
95
126
  if (PowerIcon) {
96
127
  iconElement = <PowerIcon /> as ReactSVGElement
97
128
  } else {
98
- faClasses[`fa-${icon}`] = icon as string
129
+ faClasses[`fa-${resolvedIcon}`] = resolvedIcon as string
99
130
  }
100
131
  }
101
132
 
@@ -115,7 +146,7 @@ const Icon = (props: IconProps) => {
115
146
  className
116
147
  )
117
148
 
118
- aria.label ? null : aria.label = `${icon} icon`
149
+ aria.label ? null : aria.label = `${resolvedIcon} icon`
119
150
  const ariaProps: {[key: string]: any} = buildAriaProps(aria)
120
151
  const dataProps: {[key: string]: any} = buildDataProps(data)
121
152
  const htmlProps = buildHtmlProps(htmlOptions)
@@ -137,7 +168,7 @@ const Icon = (props: IconProps) => {
137
168
  }
138
169
  </>
139
170
  )
140
- else if (isValidEmoji(icon as string))
171
+ else if (isValidEmoji(resolvedIcon as string))
141
172
  return (
142
173
  <>
143
174
  <span
@@ -146,7 +177,7 @@ const Icon = (props: IconProps) => {
146
177
  className={classesEmoji}
147
178
  id={id}
148
179
  >
149
- {icon}
180
+ {resolvedIcon}
150
181
  </span>
151
182
  </>
152
183
  )
@@ -1 +1 @@
1
- <%= pb_rails("icon", props: { icon: "user", fixed_width: true }) %>
1
+ <%= pb_rails("icon", props: { icon: "user", fixed_width: true }) %>
@@ -1,6 +1,5 @@
1
- import React from 'react'
2
-
3
- import Icon from '../_icon'
1
+ import React from "react"
2
+ import Icon from "../_icon"
4
3
 
5
4
  const IconDefault = (props) => {
6
5
  return (
@@ -3,6 +3,7 @@
3
3
  # rubocop:disable Style/HashLikeCase
4
4
 
5
5
  require "open-uri"
6
+ require "json"
6
7
 
7
8
  module Playbook
8
9
  module PbIcon
@@ -38,6 +39,8 @@ module Playbook
38
39
  prop :spin, type: Playbook::Props::Boolean,
39
40
  default: false
40
41
 
42
+ ALIASES = JSON.parse(File.read(Playbook::Engine.root.join("app/pb_kits/playbook/pb_icon/icon_aliases.json")))["aliases"].freeze
43
+
41
44
  def valid_emoji?
42
45
  emoji_regex = /\p{Emoji}/
43
46
  emoji_regex.match?(icon)
@@ -83,7 +86,8 @@ module Playbook
83
86
  return unless Rails.application.config.respond_to?(:icon_path)
84
87
 
85
88
  base_path = Rails.application.config.icon_path
86
- icon_path = Dir.glob(Rails.root.join(base_path, "**", "#{icon}.svg")).first
89
+ resolved_icon = resolve_alias(icon)
90
+ icon_path = Dir.glob(Rails.root.join(base_path, "**", "#{resolved_icon}.svg")).first
87
91
  icon_path if icon_path && File.exist?(icon_path)
88
92
  end
89
93
 
@@ -106,6 +110,22 @@ module Playbook
106
110
 
107
111
  private
108
112
 
113
+ def resolve_alias(icon)
114
+ aliases = ALIASES[icon]
115
+ return icon unless aliases
116
+
117
+ if aliases.is_a?(Array)
118
+ aliases.find { |alias_name| file_exists?(alias_name) } || icon
119
+ else
120
+ aliases
121
+ end
122
+ end
123
+
124
+ def file_exists?(alias_name)
125
+ base_path = Rails.application.config.icon_path
126
+ File.exist?(Dir.glob(Rails.root.join(base_path, "**", "#{alias_name}.svg")).first)
127
+ end
128
+
109
129
  def svg_size
110
130
  size.nil? ? "1x" : size
111
131
  end
@@ -0,0 +1,39 @@
1
+ {
2
+ "aliases": {
3
+ "arrow-alt-circle-right": "circle-right",
4
+ "angles-down": "angle-double-down",
5
+ "arrow-alt-down": "down",
6
+ "arrow-alt-up": "up",
7
+ "arrow-right-long": "long-arrow-right",
8
+ "arrow-to-bottom": "arrow-down-to-line",
9
+ "arrows-h": "arrows-left-right",
10
+ "calendar-days": "calendar-alt",
11
+ "circle-arrow-right": "arrow-circle-right",
12
+ "clock-rotate-left": "history",
13
+ "close": [
14
+ "times",
15
+ "xmark"
16
+ ],
17
+ "ellipsis-h": "ellipsis",
18
+ "exclamation-circle": "circle-exclamation",
19
+ "external-link": "arrow-up-right-from-square",
20
+ "file-lines": "file-alt",
21
+ "gear": "cog",
22
+ "home": "house",
23
+ "info-circle": "circle-info",
24
+ "map-o": "map",
25
+ "message": "comment-alt",
26
+ "minus-circle": "circle-minus",
27
+ "money": "money-bill",
28
+ "mouse-pointer": "arrow-pointer",
29
+ "nitro": "nitro-n",
30
+ "play-circle": "circle-play",
31
+ "plus-circle": "circle-plus",
32
+ "plus-square": "square-plus",
33
+ "powergon": "powergon-p",
34
+ "question-circle": "circle-question",
35
+ "roofing": "product-roofing",
36
+ "shelves": "inventory",
37
+ "th-list": "table-list"
38
+ }
39
+ }
@@ -10,7 +10,7 @@ type ListProps = {
10
10
  className?: string;
11
11
  children: React.ReactNode[] | React.ReactNode;
12
12
  dark?: boolean;
13
- draggable?: boolean;
13
+ enableDrag?: boolean;
14
14
  data?: Record<string, unknown>;
15
15
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
16
16
  id?: string;
@@ -32,7 +32,7 @@ const List = (props: ListProps) => {
32
32
  className,
33
33
  dark = false,
34
34
  data = {},
35
- draggable = false,
35
+ enableDrag = false,
36
36
  htmlOptions = {},
37
37
  id,
38
38
  layout = "",
@@ -54,7 +54,7 @@ const List = (props: ListProps) => {
54
54
  const childrenWithProps = React.Children.map(
55
55
  children,
56
56
  (child: React.ReactElement) => {
57
- return React.cloneElement(child, { text, variant, draggable });
57
+ return React.cloneElement(child, { text, variant, enableDrag });
58
58
  }
59
59
  );
60
60
  const ariaProps = buildAriaProps(aria);
@@ -74,7 +74,7 @@ const List = (props: ListProps) => {
74
74
  return (
75
75
  <>
76
76
  {
77
- draggable ? (
77
+ enableDrag ? (
78
78
  <Draggable.Container>
79
79
  <div className={classes}>
80
80
  {ordered ? (
@@ -11,6 +11,7 @@ type ListItemProps = {
11
11
  children: React.ReactNode[] | React.ReactNode,
12
12
  className?: string,
13
13
  data?: Record<string, unknown>,
14
+ dragId?: string,
14
15
  dragHandle?: boolean,
15
16
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
16
17
  id?: string,
@@ -23,7 +24,8 @@ const ListItem = (props: ListItemProps) => {
23
24
  children,
24
25
  className,
25
26
  data = {},
26
- draggable = false,
27
+ enableDrag,
28
+ dragId,
27
29
  dragHandle = true,
28
30
  htmlOptions = {},
29
31
  id,
@@ -42,8 +44,10 @@ const ListItem = (props: ListItemProps) => {
42
44
  return (
43
45
  <>
44
46
  {
45
- draggable ? (
46
- <Draggable.Item id={id}>
47
+ enableDrag ? (
48
+ <Draggable.Item
49
+ dragId={dragId}
50
+ >
47
51
  <li
48
52
  {...ariaProps}
49
53
  {...dataProps}
@@ -1,5 +1,5 @@
1
1
  <%= pb_rails("nav", props: { variant: "bold" }) do %>
2
- <%= pb_rails("nav/item", props: { text: "Overview", link: "#", collapsible: true, icon_left:"city" }) do %>
2
+ <%= pb_rails("nav/item", props: { text: "Overview", link: "#", collapsible: true, icon_left:"city", collapsed: false }) do %>
3
3
  <%= pb_rails("nav", props: { variant: "bold" }) do %>
4
4
  <%= pb_rails("nav/item", props: { text: "City", link: "#" }) %>
5
5
  <%= pb_rails("nav/item", props: { text: "People", link: "#" }) %>
@@ -9,6 +9,7 @@ const CollapsibleNav = (props) => {
9
9
  >
10
10
  <NavItem
11
11
  active
12
+ collapsed={false}
12
13
  collapsible
13
14
  iconLeft="city"
14
15
  link="#"
@@ -1 +1,3 @@
1
- The `collapsible` prop allows users to create a nested, collapsible nav. Pass `collapsible` to any NavItem and pass that navItem any number of NavItems as children to create a collapsible nav.
1
+ The `collapsible` prop allows users to create a nested, collapsible nav. Pass `collapsible` to any NavItem and pass that navItem any number of NavItems as children to create a collapsible nav.
2
+
3
+ The optional `collapsed` prop can also be used to set the default state for the collapsed nav on first render of the page. `collapsed` takes a boolean value that is set to true (meaning nav is collapsed) by default. Set it to false as shown here to have the nav open on first render.
@@ -22,7 +22,7 @@
22
22
  </span>
23
23
  <% end %>
24
24
  <% end %>
25
- <%= pb_rails("collapsible/collapsible_content") do %>
25
+ <%= pb_rails("collapsible/collapsible_content", props: {collapsed: object.collapsed}) do %>
26
26
  <%= content.presence %>
27
27
  <% end %>
28
28
  <% end %>
@@ -12,6 +12,7 @@ module Playbook
12
12
  default: "regular"
13
13
  prop :highlighted_border, type: Playbook::Props::Boolean, default: true
14
14
  prop :collapsible, type: Playbook::Props::Boolean, default: false
15
+ prop :collapsed, type: Playbook::Props::Boolean, default: true
15
16
  prop :link
16
17
  prop :text
17
18
  prop :collapsible_trail, type: Playbook::Props::Boolean, default: false
@@ -0,0 +1,24 @@
1
+ <%= pb_rails("overlay") do %>
2
+ <%= pb_rails("table", props: { size: "sm" }) do %>
3
+ <thead>
4
+ <tr>
5
+ <th>Column 1</th>
6
+ <th>Column 2</th>
7
+ <th>Column 3</th>
8
+ <th>Column 4</th>
9
+ <th>Column 5</th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <% 7.times do %>
14
+ <tr>
15
+ <td>Value 1</td>
16
+ <td>Value 2</td>
17
+ <td>Value 3</td>
18
+ <td>Value 4</td>
19
+ <td>Value 5</td>
20
+ </tr>
21
+ <% end %>
22
+ </tbody>
23
+ <% end %>
24
+ <% end %>
@@ -1,7 +1,7 @@
1
- Overlays require a `color`, which sets the "start" (opaque) color of a gradient mask. Because this overlay is intended to reveal underlying content, the "end" color is fixed to transparent.
1
+ Overlays optionally accept a `color`, which sets the "start" (opaque) color of a gradient mask. Because this overlay is intended to reveal underlying content, the "end" color is fixed to transparent.
2
2
 
3
- The optional `layout` prop accepts a `position` and a `size` as a key:value pair object.
3
+ The optional `layout` prop accepts the `position` and `size` of the overlay as a key:value pair.
4
4
 
5
- The `position` key accepts `top`, `bottom`, `y` (for both top and bottom) `right`, `left`, or `x` (for both left and right), which sets the side(s) where the `color` overlay starts. The direction of the overlay is always toward the opposite side of the position. For example, the default position of `bottom` starts the overlay on the bottom edge of your container and extends it toward the opposite side: the top.
5
+ The `position` key accepts `bottom` (default), `top`, `y` (for both top and bottom) `right`, `left`, or `x` (for both left and right), which sets the side(s) where the `color` overlay starts. The direction of the overlay is always toward the opposite side of the position. For example, the default position of `bottom` starts the overlay on the bottom edge of your container and extends it toward the opposite side: the top.
6
6
 
7
- The `size` value accepts our [spacing tokens](https://playbook.powerapp.cloud/visual_guidelines/spacing) or a percentage value as a string, and literally translates to how much of the container is covered by the overlay. By default, `size` is set to `full` (100%) so that your overlay covers the entire container with a smooth fade from `color` at its starting edge, fading to transparent and ending at the containers opposite edge.
7
+ The `size` value is `full` (100%) by default, but accepts our [spacing tokens](https://playbook.powerapp.cloud/visual_guidelines/spacing) or a percentage value as a string, and literally translates to how much of the container is covered by the overlay(s).