playbook_ui 8.1.1 → 8.2.0.pre.alpha4

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -0
  3. data/app/pb_kits/playbook/_playbook.scss +1 -0
  4. data/app/pb_kits/playbook/data/menu.yml +2 -1
  5. data/app/pb_kits/playbook/index.js +1 -0
  6. data/app/pb_kits/playbook/pb_avatar/_avatar.jsx +14 -2
  7. data/app/pb_kits/playbook/pb_avatar/avatar.html.erb +1 -1
  8. data/app/pb_kits/playbook/pb_avatar/avatar.rb +5 -2
  9. data/app/pb_kits/playbook/pb_avatar/avatar.test.js +5 -2
  10. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_default.html.erb +5 -0
  11. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_default.jsx +5 -0
  12. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_status.html.erb +4 -0
  13. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_status.jsx +4 -0
  14. data/app/pb_kits/playbook/pb_avatar_action_button/_avatar_action_button.jsx +6 -0
  15. data/app/pb_kits/playbook/pb_avatar_action_button/avatar_action_button.html.erb +2 -1
  16. data/app/pb_kits/playbook/pb_avatar_action_button/avatar_action_button.rb +2 -0
  17. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_actions.html.erb +4 -0
  18. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_actions.jsx +4 -0
  19. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_default.html.erb +2 -0
  20. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_default.jsx +2 -0
  21. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_on_click.jsx +2 -0
  22. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_onclick.html.erb +2 -0
  23. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_placement.html.erb +8 -0
  24. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_placement.jsx +8 -0
  25. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_tooltip.html.erb +2 -0
  26. data/app/pb_kits/playbook/pb_avatar_action_button/pb_avatar_action_button.test.js +31 -0
  27. data/app/pb_kits/playbook/pb_button/_button.jsx +6 -0
  28. data/app/pb_kits/playbook/pb_button/button.test.js +91 -0
  29. data/app/pb_kits/playbook/pb_button/docs/_button_default.jsx +0 -1
  30. data/app/pb_kits/playbook/pb_button_toolbar/button_toolbar.test.js +46 -0
  31. data/app/pb_kits/playbook/pb_caption/_caption.jsx +3 -2
  32. data/app/pb_kits/playbook/pb_caption/caption.rb +1 -1
  33. data/app/pb_kits/playbook/pb_card/_card.jsx +18 -3
  34. data/app/pb_kits/playbook/pb_card/card.html.erb +1 -1
  35. data/app/pb_kits/playbook/pb_card/card.rb +3 -0
  36. data/app/pb_kits/playbook/pb_card/docs/_card_tag.html.erb +25 -0
  37. data/app/pb_kits/playbook/pb_card/docs/_card_tag.jsx +59 -0
  38. data/app/pb_kits/playbook/pb_card/docs/example.yml +2 -0
  39. data/app/pb_kits/playbook/pb_card/docs/index.js +1 -0
  40. data/app/pb_kits/playbook/pb_checkbox/_checkbox.jsx +31 -9
  41. data/app/pb_kits/playbook/pb_checkbox/_checkbox.scss +28 -19
  42. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +11 -3
  43. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +6 -1
  44. data/app/pb_kits/playbook/pb_checkbox/checkbox.test.js +94 -0
  45. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_custom.jsx +0 -1
  46. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +7 -0
  47. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.jsx +16 -0
  48. data/app/pb_kits/playbook/pb_checkbox/docs/example.yml +2 -0
  49. data/app/pb_kits/playbook/pb_checkbox/docs/index.js +1 -0
  50. data/app/pb_kits/playbook/pb_circle_icon_button/circle_icon_button.test.js +17 -0
  51. data/app/pb_kits/playbook/pb_dashboard/commonSettings.js +2 -2
  52. data/app/pb_kits/playbook/pb_dashboard/pbChartsLightTheme.js +2 -2
  53. data/app/pb_kits/playbook/pb_dialog/_close_icon.jsx +23 -0
  54. data/app/pb_kits/playbook/pb_dialog/_dialog.html.erb +10 -0
  55. data/app/pb_kits/playbook/pb_dialog/_dialog.jsx +142 -0
  56. data/app/pb_kits/playbook/pb_dialog/_dialog.scss +133 -0
  57. data/app/pb_kits/playbook/pb_dialog/_dialog_context.jsx +3 -0
  58. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_body.jsx +21 -0
  59. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_footer.jsx +36 -0
  60. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_header.jsx +68 -0
  61. data/app/pb_kits/playbook/pb_dialog/dialog.rb +47 -0
  62. data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +23 -0
  63. data/app/pb_kits/playbook/pb_dialog/dialog_header.rb +31 -0
  64. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_compound_components.jsx +53 -0
  65. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_compound_components.md +2 -0
  66. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_default.jsx +27 -0
  67. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_scrollable.jsx +27 -0
  68. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_scrollable.md +2 -0
  69. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_separators.jsx +119 -0
  70. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_separators.md +2 -0
  71. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_should_close_on_overlay.jsx +28 -0
  72. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_should_close_on_overlay.md +2 -0
  73. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_sizes.jsx +93 -0
  74. data/app/pb_kits/playbook/pb_dialog/docs/example.yml +10 -0
  75. data/app/pb_kits/playbook/pb_dialog/docs/index.js +6 -0
  76. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -1
  77. data/app/pb_kits/playbook/pb_form/form_with.rb +0 -1
  78. data/app/pb_kits/playbook/pb_online_status/_online_status.jsx +2 -0
  79. data/app/pb_kits/playbook/pb_online_status/online_status.html.erb +1 -1
  80. data/app/pb_kits/playbook/pb_user_badge/_user_badge.jsx +1 -1
  81. data/app/pb_kits/playbook/plugins/pb_chart.js +1 -1
  82. data/app/pb_kits/playbook/react_rails_kits.js +4 -0
  83. data/app/pb_kits/playbook/tokens/_border_radius.scss +0 -10
  84. data/app/pb_kits/playbook/tokens/_colors.scss +0 -25
  85. data/app/pb_kits/playbook/tokens/_line_height.scss +0 -9
  86. data/app/pb_kits/playbook/tokens/_opacity.scss +0 -9
  87. data/app/pb_kits/playbook/tokens/_positioning.scss +0 -9
  88. data/app/pb_kits/playbook/tokens/_screen_sizes.scss +0 -9
  89. data/app/pb_kits/playbook/tokens/_shadows.scss +0 -9
  90. data/app/pb_kits/playbook/tokens/_spacing.scss +0 -10
  91. data/app/pb_kits/playbook/tokens/_typography.scss +0 -25
  92. data/app/pb_kits/playbook/tokens/exports/_border_radius.scss +10 -0
  93. data/app/pb_kits/playbook/tokens/exports/_colors.scss +26 -0
  94. data/app/pb_kits/playbook/tokens/exports/_line_height.scss +10 -0
  95. data/app/pb_kits/playbook/tokens/exports/_opacity.scss +10 -0
  96. data/app/pb_kits/playbook/tokens/exports/_positioning.scss +10 -0
  97. data/app/pb_kits/playbook/tokens/exports/_screen_sizes.scss +10 -0
  98. data/app/pb_kits/playbook/tokens/exports/_shadows.scss +10 -0
  99. data/app/pb_kits/playbook/tokens/exports/_spacing.scss +10 -0
  100. data/app/pb_kits/playbook/tokens/exports/_typography.scss +24 -0
  101. data/app/pb_kits/playbook/utilities/test-utils.js +6 -0
  102. data/dist/reset.css +1 -0
  103. data/lib/playbook/version.rb +2 -1
  104. metadata +52 -10
@@ -1,25 +1,33 @@
1
1
  <div class="pb--doc-demo-row">
2
2
 
3
3
  <%= pb_rails("avatar_action_button", props: {
4
+ link_aria_label: "Sophia Carden",
4
5
  name: "Sophia Carden",
6
+ image_alt: "Sophia Carden",
5
7
  image_url: "https://randomuser.me/api/portraits/women/8.jpg",
6
8
  placement: "bottom_left"
7
9
  }) %>
8
10
 
9
11
  <%= pb_rails("avatar_action_button", props: {
12
+ link_aria_label: "Sophia Carden",
10
13
  name: "Sophia Carden",
14
+ image_alt: "Sophia Carden",
11
15
  image_url: "https://randomuser.me/api/portraits/women/8.jpg",
12
16
  placement: "bottom_right"
13
17
  }) %>
14
18
 
15
19
  <%= pb_rails("avatar_action_button", props: {
20
+ link_aria_label: "Sophia Carden",
16
21
  name: "Sophia Carden",
22
+ image_alt: "Sophia Carden",
17
23
  image_url: "https://randomuser.me/api/portraits/women/8.jpg",
18
24
  placement: "top_left"
19
25
  }) %>
20
26
 
21
27
  <%= pb_rails("avatar_action_button", props: {
28
+ link_aria_label: "Sophia Carden",
22
29
  name: "Sophia Carden",
30
+ image_alt: "Sophia Carden",
23
31
  image_url: "https://randomuser.me/api/portraits/women/8.jpg",
24
32
  placement: "top_right"
25
33
  }) %>
@@ -4,25 +4,33 @@ import { AvatarActionButton } from '../../'
4
4
  const AvatarActionButtonPlacement = (props) => (
5
5
  <div className="pb--doc-demo-row">
6
6
  <AvatarActionButton
7
+ imageAlt="Sophia Carden"
7
8
  imageUrl="https://randomuser.me/api/portraits/women/8.jpg"
9
+ linkAriaLabel="Sophia Carden"
8
10
  name="Sophia Carden"
9
11
  placement="bottom_left"
10
12
  {...props}
11
13
  />
12
14
  <AvatarActionButton
15
+ imageAlt="Sophia Carden"
13
16
  imageUrl="https://randomuser.me/api/portraits/women/8.jpg"
17
+ linkAriaLabel="Sophia Carden"
14
18
  name="Sophia Carden"
15
19
  placement="bottom_right"
16
20
  {...props}
17
21
  />
18
22
  <AvatarActionButton
23
+ imageAlt="Sophia Carden"
19
24
  imageUrl="https://randomuser.me/api/portraits/women/8.jpg"
25
+ linkAriaLabel="Sophia Carden"
20
26
  name="Sophia Carden"
21
27
  placement="top_left"
22
28
  {...props}
23
29
  />
24
30
  <AvatarActionButton
31
+ imageAlt="Sophia Carden"
25
32
  imageUrl="https://randomuser.me/api/portraits/women/8.jpg"
33
+ linkAriaLabel="Sophia Carden"
26
34
  name="Sophia Carden"
27
35
  placement="top_right"
28
36
  {...props}
@@ -1,8 +1,10 @@
1
1
  <div class="pb--doc-demo-row">
2
2
 
3
3
  <%= pb_rails("avatar_action_button", props: {
4
+ link_aria_label: "Sophia Carden",
4
5
  name: "Sophia Carden",
5
6
  link_url: "http://www.google.com",
7
+ image_alt: "Sophia Carden",
6
8
  image_url: "https://randomuser.me/api/portraits/women/8.jpg",
7
9
  tooltip_text: "Tooltip Text",
8
10
  tooltip_id: "avatar_1",
@@ -0,0 +1,31 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import AvatarActionButton from './_avatar_action_button'
5
+
6
+ const imageUrl = 'https://randomuser.me/api/portraits/women/8.jpg',
7
+ testId = 'scarden',
8
+ name = 'Sophia Carden',
9
+ imageAlt = 'Sophia Carden Profile'
10
+
11
+ test('loads the given image url and name', () => {
12
+ render(
13
+ <AvatarActionButton
14
+ data={{ testid: testId }}
15
+ imageAlt={imageAlt}
16
+ imageUrl={imageUrl}
17
+ linkAriaLabel={name}
18
+ name={name}
19
+ />
20
+ )
21
+
22
+ const kit = screen.getByTestId(testId)
23
+ const image = screen.getByAltText(imageAlt)
24
+ const link = kit.children[0]
25
+
26
+ expect(kit).toHaveClass('pb_avatar_action_button_kit_add_bottom_left_md')
27
+ expect(image).toHaveAttribute('data-src', imageUrl)
28
+ expect(image).toHaveAttribute('src', imageUrl)
29
+ expect(image).toHaveAttribute('alt', imageAlt)
30
+ expect(link).toHaveAttribute('aria-label', name)
31
+ })
@@ -2,6 +2,7 @@
2
2
 
3
3
  import React from 'react'
4
4
  import classnames from 'classnames'
5
+ import { buildDataProps } from '../utilities/props'
5
6
  import { globalProps } from '../utilities/globalProps.js'
6
7
 
7
8
  import Icon from '../pb_icon/_icon.jsx'
@@ -13,6 +14,7 @@ type ButtonPropTypes = {
13
14
  },
14
15
  children?: array<React.ReactChild>,
15
16
  className?: string | array<string>,
17
+ data?: object,
16
18
  disabled?: boolean,
17
19
  fixedWidth?: boolean,
18
20
  fullWidth?: boolean,
@@ -69,6 +71,7 @@ const Button = (props: ButtonPropTypes) => {
69
71
  const {
70
72
  children,
71
73
  className,
74
+ data = {},
72
75
  disabled,
73
76
  icon = null,
74
77
  id,
@@ -82,6 +85,7 @@ const Button = (props: ButtonPropTypes) => {
82
85
  } = props
83
86
 
84
87
  const buttonAria = buttonAriaProps(props)
88
+ const dataProps = buildDataProps(data)
85
89
  const css = classnames(
86
90
  buttonClassName(props),
87
91
  globalProps(props),
@@ -111,6 +115,7 @@ const Button = (props: ButtonPropTypes) => {
111
115
  <If condition={link !== null}>
112
116
  <a
113
117
  {...buttonAria}
118
+ {...dataProps}
114
119
  className={css}
115
120
  href={link}
116
121
  id={id}
@@ -122,6 +127,7 @@ const Button = (props: ButtonPropTypes) => {
122
127
  <Else />
123
128
  <button
124
129
  {...buttonAria}
130
+ {...dataProps}
125
131
  className={css}
126
132
  disabled={disabled}
127
133
  id={id}
@@ -0,0 +1,91 @@
1
+
2
+ import React from 'react'
3
+ import { appendAlert, fireEvent, render, screen, waitFor } from '../utilities/test-utils'
4
+
5
+ import Button from './_button'
6
+
7
+ // Primary Test Variables
8
+ const htmlType = 'submit',
9
+ text = 'Button Text',
10
+ value = '1234'
11
+
12
+ test('passes type, text, and value props to button', () => {
13
+ render(
14
+ <>
15
+ <Button
16
+ data={{ testid: 'primary-test' }}
17
+ htmlType={htmlType}
18
+ text={text}
19
+ value={value}
20
+ />
21
+ </>
22
+ )
23
+
24
+ const kit = screen.getByTestId('primary-test')
25
+ const content = screen.getByText(text)
26
+
27
+ expect(kit).toHaveClass('pb_button_kit_primary_inline_enabled')
28
+ expect(kit).toHaveAttribute('type', htmlType)
29
+ expect(kit).toHaveAttribute('value', value)
30
+ expect(content).toHaveTextContent(text)
31
+ })
32
+
33
+ // Link Test Variables
34
+ const link = 'https://www.google.com'
35
+
36
+ test('adds link to button', () => {
37
+ render(
38
+ <Button
39
+ data={{ testid: 'link-test' }}
40
+ link={link}
41
+ />
42
+ )
43
+
44
+ const kit = screen.getByTestId('link-test')
45
+
46
+ expect(kit).toHaveAttribute('href', link)
47
+ })
48
+
49
+ test('button with secondary variant', () => {
50
+ render(
51
+ <Button
52
+ data={{ testid: 'variant-test' }}
53
+ variant="secondary"
54
+ />
55
+ )
56
+
57
+ const kit = screen.getByTestId('variant-test')
58
+
59
+ expect(kit).toHaveClass('pb_button_kit_secondary_inline_enabled')
60
+ expect(kit).toHaveAttribute('type', 'button')
61
+ })
62
+
63
+ test('disable prop', () => {
64
+ render(
65
+ <Button
66
+ data={{ testid: 'disable-test' }}
67
+ disabled
68
+ />
69
+ )
70
+
71
+ const kit = screen.getByTestId('disable-test')
72
+
73
+ expect(kit).toBeDisabled()
74
+ })
75
+
76
+ test('click event', async () => {
77
+ render(
78
+ <Button
79
+ data={{ testid: 'click-test' }}
80
+ onClick={() => appendAlert('clicked button!')}
81
+ />
82
+ )
83
+
84
+ const kit = screen.getByTestId('click-test')
85
+
86
+ fireEvent.click(kit)
87
+
88
+ await waitFor(() => screen.getByText('clicked button!'))
89
+
90
+ expect(screen.getByText('clicked button!')).toBeInTheDocument()
91
+ })
@@ -30,7 +30,6 @@ const ButtonDefault = (props) => (
30
30
  {...props}
31
31
  />
32
32
  </div>
33
-
34
33
  )
35
34
 
36
35
  export default ButtonDefault
@@ -0,0 +1,46 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import { Button, ButtonToolbar } from '../'
5
+
6
+ test('default test', () => {
7
+ render(
8
+ <ButtonToolbar
9
+ data={{ testid: 'default-test' }}
10
+ >
11
+ <Button
12
+ data={{ testid: 'child-button' }}
13
+ text="Test"
14
+ />
15
+ </ButtonToolbar>
16
+ )
17
+
18
+ const kit = screen.getByTestId('default-test')
19
+ const child = screen.getByTestId('child-button')
20
+
21
+ expect(kit).toHaveClass('pb_button_toolbar_kit_horizontal_primary')
22
+ expect(kit).toContainElement(child)
23
+ expect(child).toHaveClass('pb_button_kit_primary_inline_enabled')
24
+ })
25
+
26
+ test('variant and orientation props', () => {
27
+ render(
28
+ <ButtonToolbar
29
+ data={{ testid: 'second-test' }}
30
+ orientation="vertical"
31
+ variant="secondary"
32
+ >
33
+ <Button
34
+ data={{ testid: 'child-button' }}
35
+ text="Create"
36
+ variant="secondary"
37
+ />
38
+ </ButtonToolbar>
39
+ )
40
+
41
+ const kit = screen.getByTestId('second-test')
42
+ const child = screen.getByTestId('child-button')
43
+
44
+ expect(kit).toHaveClass('pb_button_toolbar_kit_vertical_secondary')
45
+ expect(child).toHaveClass('pb_button_kit_secondary_inline_enabled')
46
+ })
@@ -12,7 +12,7 @@ type CaptionProps = {
12
12
  data?: object,
13
13
  id?: string,
14
14
  size?: "xs" | "sm" | "md" | "lg" | "xl",
15
- tag?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "div",
15
+ tag?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "div" | "caption",
16
16
  text?: string,
17
17
  variant?: null | "link",
18
18
  }
@@ -29,7 +29,8 @@ const Caption = (props: CaptionProps) => {
29
29
  text,
30
30
  variant = null,
31
31
  } = props
32
- const Tag = `${tag}`
32
+ const tagOptions = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', 'div', 'caption']
33
+ const Tag = tagOptions.includes(tag) ? tag : 'div'
33
34
 
34
35
  const ariaProps = buildAriaProps(aria)
35
36
  const dataProps = buildDataProps(data)
@@ -7,7 +7,7 @@ module Playbook
7
7
  values: %w[xs sm md base lg xl],
8
8
  default: "md"
9
9
  prop :tag, type: Playbook::Props::Enum,
10
- values: %w[h1 h2 h3 h4 h5 h6 p span div],
10
+ values: %w[h1 h2 h3 h4 h5 h6 p span div caption],
11
11
  default: "div"
12
12
  prop :text
13
13
  prop :variant, type: Playbook::Props::Enum,
@@ -3,14 +3,16 @@
3
3
  import React from 'react'
4
4
  import { get } from 'lodash'
5
5
  import classnames from 'classnames'
6
- import { buildCss } from '../utilities/props'
6
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
7
7
  import { globalProps } from '../utilities/globalProps.js'
8
8
 
9
9
  type CardPropTypes = {
10
+ aria?: object,
10
11
  borderNone?: boolean,
11
12
  borderRadius?: "xs" | "sm" | "md" | "lg" | "xl" | "none" | "rounded",
12
13
  children: array<React.ReactNode> | React.ReactNode,
13
14
  className?: string,
15
+ data?: object,
14
16
  highlight?: {
15
17
  position?: "side" | "top",
16
18
  color?: string,
@@ -18,6 +20,7 @@ type CardPropTypes = {
18
20
  padding?: string,
19
21
  selected?: boolean,
20
22
  shadow?: "none" | "deep" | "deeper" | "deepest",
23
+ tag?: "div" | "section" | "footer" | "header" | "article" | "aside" | "main" | "nav",
21
24
  }
22
25
 
23
26
  type CardHeaderProps = {
@@ -62,13 +65,16 @@ const Body = (props: CardBodyProps) => {
62
65
 
63
66
  const Card = (props: CardPropTypes) => {
64
67
  const {
68
+ aria = {},
65
69
  borderNone = false,
66
70
  borderRadius = 'md',
67
71
  children,
68
72
  className,
73
+ data = {},
69
74
  highlight = {},
70
75
  selected = false,
71
76
  shadow = 'none',
77
+ tag = 'div',
72
78
  padding = 'md',
73
79
  } = props
74
80
  const borderCSS = borderNone == true ? 'border_none' : ''
@@ -78,6 +84,8 @@ const Card = (props: CardPropTypes) => {
78
84
  [`highlight_${highlight.position}`]: highlight.position,
79
85
  [`highlight_${highlight.color}`]: highlight.color,
80
86
  })
87
+ const ariaProps = buildAriaProps(aria)
88
+ const dataProps = buildDataProps(data)
81
89
 
82
90
  // coerce to array
83
91
  const cardChildren =
@@ -93,11 +101,18 @@ const Card = (props: CardPropTypes) => {
93
101
 
94
102
  const nonHeaderChildren = cardChildren.filter((child) => (get(child, 'type.displayName') !== 'Header'))
95
103
 
104
+ const tagOptions = ['div', 'section', 'footer', 'header', 'article', 'aside', 'main', 'nav']
105
+ const Tag = tagOptions.includes(tag) ? tag : 'div'
106
+
96
107
  return (
97
- <div className={classnames(cardCss, globalProps(props, { padding }), className)}>
108
+ <Tag
109
+ {...ariaProps}
110
+ {...dataProps}
111
+ className={classnames(cardCss, globalProps(props, { padding }), className)}
112
+ >
98
113
  {subComponentTags('Header')}
99
114
  {nonHeaderChildren}
100
- </div>
115
+ </Tag>
101
116
  )
102
117
  }
103
118
 
@@ -1,4 +1,4 @@
1
- <%= content_tag(:div,
1
+ <%= content_tag(object.tag,
2
2
  id: object.id,
3
3
  data: object.data,
4
4
  class: object.classname,
@@ -9,6 +9,9 @@ module Playbook
9
9
  default: "none"
10
10
  prop :highlight, type: Playbook::Props::Hash,
11
11
  default: {}
12
+ prop :tag, type: Playbook::Props::Enum,
13
+ values: %w[div section footer header article aside main nav],
14
+ default: "div"
12
15
  prop :border_none, type: Playbook::Props::Boolean,
13
16
  default: false
14
17
  prop :border_radius, type: Playbook::Props::Enum,
@@ -0,0 +1,25 @@
1
+ <%= pb_rails("card", props: { tag: "section" }) do %> section <% end %>
2
+
3
+ <br />
4
+
5
+ <%= pb_rails("card", props: { tag: "footer" }) do %> footer <% end %>
6
+
7
+ <br />
8
+
9
+ <%= pb_rails("card", props: { tag: "header" }) do %> header <% end %>
10
+
11
+ <br />
12
+
13
+ <%= pb_rails("card", props: { tag: "article" }) do %> article <% end %>
14
+
15
+ <br />
16
+
17
+ <%= pb_rails("card", props: { tag: "aside" }) do %> aside <% end %>
18
+
19
+ <br />
20
+
21
+ <%= pb_rails("card", props: { tag: "main" }) do %> main <% end %>
22
+
23
+ <br />
24
+
25
+ <%= pb_rails("card", props: { tag: "nav" }) do %> nav <% end %>