playbook_ui 12.17.1 → 12.18.0.pre.alpha.PLAY603datepickerquickpickinputpresetdropdown617

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/index.js +1 -1
  3. data/app/pb_kits/playbook/pb_avatar_action_button/avatar_action_button.html.erb +1 -2
  4. data/app/pb_kits/playbook/pb_collapsible/_collapsible.tsx +2 -2
  5. data/app/pb_kits/playbook/pb_date_picker/_date_picker.scss +26 -0
  6. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +99 -95
  7. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +1 -1
  8. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +1 -1
  9. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +44 -1
  10. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +34 -2
  11. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick.html.erb +8 -0
  12. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick.jsx +18 -0
  13. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
  14. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +2 -1
  15. data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +161 -0
  16. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_calendar_input_icon.scss +4 -3
  17. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_quick_pick_styles.scss +75 -0
  18. data/app/pb_kits/playbook/pb_docs/kit_api.html.erb +48 -36
  19. data/app/pb_kits/playbook/pb_docs/kit_api.rb +97 -9
  20. data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +1 -1
  21. data/app/pb_kits/playbook/pb_docs/kit_example.rb +9 -5
  22. data/app/pb_kits/playbook/pb_lightbox/_lightbox.tsx +8 -0
  23. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_current_photo.jsx +121 -0
  24. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_current_photo.md +1 -0
  25. data/app/pb_kits/playbook/pb_lightbox/docs/example.yml +1 -0
  26. data/app/pb_kits/playbook/pb_lightbox/docs/index.js +1 -0
  27. data/app/pb_kits/playbook/pb_nav/_item.tsx +7 -7
  28. data/app/pb_kits/playbook/pb_nav/_nav.tsx +4 -4
  29. data/app/pb_kits/playbook/pb_nav/_subtle_mixin.scss +1 -1
  30. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/EditorButton.tsx +49 -0
  31. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/EditorTypes.ts +9 -0
  32. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/Toolbar.tsx +62 -0
  33. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarDropdown.tsx +139 -0
  34. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarHistory.tsx +45 -0
  35. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarNodes.tsx +59 -0
  36. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.scss +1 -1
  37. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +28 -12
  38. data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_styles.scss +231 -0
  39. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_description.md +1 -0
  40. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_default.jsx +36 -0
  41. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_default.md +4 -0
  42. data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +1 -0
  43. data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +1 -0
  44. data/app/pb_kits/playbook/pb_time_range_inline/_time_range_inline.tsx +185 -0
  45. data/app/pb_kits/playbook/pb_time_range_inline/time_range_inline.test.js +85 -0
  46. data/app/pb_kits/playbook/pb_title/_title.tsx +1 -1
  47. data/app/pb_kits/playbook/pb_title_detail/_title_detail.tsx +45 -0
  48. data/app/pb_kits/playbook/pb_title_detail/title_detail.test.js +71 -0
  49. data/app/pb_kits/playbook/pb_toggle/{_toggle.jsx → _toggle.tsx} +20 -22
  50. data/app/pb_kits/playbook/pb_toggle/toggle.test.js +67 -0
  51. data/app/pb_kits/playbook/pb_tooltip/_tooltip.scss +11 -6
  52. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_default.html.erb +4 -4
  53. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_with_icon_circle.html.erb +1 -2
  54. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +0 -1
  55. data/app/pb_kits/playbook/pb_user/_user.tsx +1 -1
  56. data/lib/playbook/markdown/helper.rb +50 -71
  57. data/lib/playbook/markdown.rb +0 -1
  58. data/lib/playbook/number_spacing.rb +10 -10
  59. data/lib/playbook/position.rb +10 -10
  60. data/lib/playbook/spacing.rb +10 -10
  61. data/lib/playbook/version.rb +2 -2
  62. data/lib/playbook/z_index.rb +10 -10
  63. metadata +31 -14
  64. data/app/pb_kits/playbook/pb_time_range_inline/_time_range_inline.jsx +0 -172
  65. data/app/pb_kits/playbook/pb_title_detail/_title_detail.jsx +0 -44
  66. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_white.html.erb +0 -9
  67. data/lib/playbook/markdown/template_handler.rb +0 -47
@@ -0,0 +1,231 @@
1
+ @import "../tokens/border_radius";
2
+ @import "../tokens/colors";
3
+ @import "../tokens/spacing";
4
+ @import "../tokens/titles";
5
+ @import "../tokens/line_height";
6
+ @import "../tokens/typography";
7
+ @import "../tokens/shadows";
8
+ @import "../tokens/transition";
9
+
10
+ [class^="pb_rich_text_editor_kit"] {
11
+ .toolbar_button {
12
+ display: flex;
13
+ align-items: center;
14
+ background: $transparent;
15
+ border: none;
16
+ border-radius: $border_rad_heaviest;
17
+ color: $text_lt_light;
18
+ cursor: pointer;
19
+ &_icon {
20
+ width: $space_xl + 2;
21
+ height: $space_xl + 2;
22
+ }
23
+ &.open {
24
+ color: $primary;
25
+ }
26
+ &.is-active,
27
+ &:active {
28
+ color: $primary;
29
+ background-color: $bg_light;
30
+ }
31
+ &:hover:not([disabled]) {
32
+ background-color: $neutral_subtle;
33
+ }
34
+ &:disabled {
35
+ .pb_icon_kit {
36
+ color: $border_light;
37
+ }
38
+ }
39
+ &:focus-visible {
40
+ outline: none !important;
41
+ }
42
+ }
43
+
44
+ .toolbar {
45
+ border-radius: $border_rad_heaviest $border_rad_heaviest 0 0;
46
+ border: 1px solid $border_light;
47
+ overflow-x: auto;
48
+ &_block {
49
+ gap: $space_xs;
50
+ }
51
+ .editor-dropdown-button {
52
+ background: transparent;
53
+ border: none;
54
+ color: $text_lt_light;
55
+ cursor: pointer;
56
+ font-weight: $light;
57
+ padding: ($space_xs - 1) 0px;
58
+ width: $space_xl * 3;
59
+ &:focus-visible {
60
+ box-shadow: unset;
61
+ }
62
+ }
63
+ }
64
+
65
+ .ProseMirror {
66
+ background: $white;
67
+ border: 1px solid $border_light;
68
+ border-top-color: transparent;
69
+ border-bottom-right-radius: $border_rad_heaviest;
70
+ border-bottom-left-radius: $border_rad_heaviest;
71
+ height: 100%;
72
+ padding: 1rem 1.5rem 1.5rem 1.5rem;
73
+ line-height: $lh_loose;
74
+ @include transition_default;
75
+ :first-child {
76
+ margin-top: 0;
77
+ }
78
+
79
+ h4,
80
+ h5,
81
+ h6,
82
+ ul,
83
+ ol,
84
+ blockquote,
85
+ p {
86
+ margin: 1rem 0 0 0;
87
+ }
88
+
89
+ code {
90
+ font-family: monospace;
91
+ background: $bg_light;
92
+ padding: 0.1rem 0.3rem;
93
+ margin: 0 5px;
94
+ box-shadow: 0 2px 10px $shadow;
95
+ border-radius: 0.25rem;
96
+ overflow: hidden;
97
+ font-size: ($text_small - 1px);
98
+ }
99
+
100
+ pre {
101
+ background: $bg_dark;
102
+ padding: $space_sm;
103
+ border-radius: $border_rad_heaviest;
104
+ margin: 1.5rem 0 2rem 0;
105
+ code {
106
+ background: transparent;
107
+ box-shadow: none;
108
+ border: 0;
109
+ color: #faf6e4;
110
+ }
111
+ }
112
+ a {
113
+ color: $primary;
114
+ border-bottom: 1px solid $primary;
115
+ &:hover {
116
+ color: $text_lt_default;
117
+ border-bottom: 1px solid $text_lt_default;
118
+ }
119
+ }
120
+ blockquote {
121
+ font-size: $font_larger;
122
+ padding: $space_sm $space_md;
123
+ font-style: italic;
124
+ p {
125
+ margin: 0;
126
+ }
127
+ }
128
+ &:focus-visible {
129
+ outline: unset;
130
+ border-top-color: $primary;
131
+ @include transition_default;
132
+ }
133
+ h1 {
134
+ font-size: $text_largest;
135
+ line-height: $text_larger;
136
+ font-weight: $bolder;
137
+ letter-spacing: $lspace_tight;
138
+ margin: 2.1rem 0 0 0;
139
+ }
140
+ h2 {
141
+ font-size: $text_larger;
142
+ line-height: $text_larger;
143
+ font-weight: $bolder;
144
+ letter-spacing: $lspace_tight;
145
+ margin: 1.9rem 0 0 0;
146
+ }
147
+ h3 {
148
+ font-size: $text_large;
149
+ line-height: $text_large;
150
+ font-weight: $bolder;
151
+ letter-spacing: $lspace_tight;
152
+ margin: 1.7rem 0 0 0;
153
+ }
154
+ h4,
155
+ h5,
156
+ h6 {
157
+ font-size: $text_base;
158
+ line-height: $text_base;
159
+ letter-spacing: $lspace_tight;
160
+ font-weight: $bolder;
161
+ }
162
+ hr {
163
+ margin: 2.2rem 0;
164
+ box-sizing: content-box;
165
+ overflow: hidden;
166
+ background: transparent;
167
+ border-bottom: 1px solid $transparent;
168
+ height: 1px;
169
+ padding: 0;
170
+ background-color: $border_light;
171
+ border: 0;
172
+ }
173
+ ol {
174
+ margin: 1rem 0 0 0;
175
+ padding-left: $space_md;
176
+ list-style: decimal;
177
+ li {
178
+ margin: 2px 0;
179
+ p {
180
+ margin: 0;
181
+ }
182
+ }
183
+ }
184
+ ul {
185
+ list-style-position: disc;
186
+ margin: 1rem 0 0 0;
187
+ padding-left: $space_md;
188
+ li {
189
+ margin: 2px 0;
190
+ p {
191
+ margin: 0;
192
+ }
193
+ }
194
+ }
195
+ }
196
+ }
197
+
198
+ .pb_tiptap_toolbar_dropdown_list_item {
199
+ &.is-active,
200
+ &:active {
201
+ color: $primary;
202
+ background-color: $bg_light;
203
+ border-radius: unset !important;
204
+ .pb_nav_list_item_text,
205
+ .pb_nav_list_item_icon_left {
206
+ color: $primary !important;
207
+ }
208
+ }
209
+ &:hover {
210
+ background-color: $neutral_subtle;
211
+ border-radius: unset !important;
212
+ .pb_nav_list_item_text,
213
+ .pb_nav_list_item_icon_left {
214
+ background-color: unset;
215
+ color: $text_lt_light !important;
216
+ }
217
+ .pb_nav_list_item_link {
218
+ background-color: unset !important;
219
+ }
220
+ }
221
+ }
222
+ .pb_rich_text_editor_advanced_container {
223
+ transition: box-shadow 0.3s ease-in-out, border-radius 0.3s ease-in-out;
224
+ &:focus-visible,
225
+ &:focus-within {
226
+ outline: unset;
227
+ box-shadow: 0 0 0 1px $primary;
228
+ border-radius: $border_rad_heaviest;
229
+ transition: box-shadow 0.3s ease-in-out, border-radius 0.3s ease-in-out;
230
+ }
231
+ }
@@ -0,0 +1 @@
1
+ NOTE: All editors have a default max-width of "md". Use our [Max Width global prop](https://playbook.powerapp.cloud/visual_guidelines/max_width) to override this default, as necessary.
@@ -0,0 +1,36 @@
1
+ import React from 'react'
2
+ import { RichTextEditor } from '../..'
3
+ import { useEditor, EditorContent } from "@tiptap/react"
4
+ import StarterKit from "@tiptap/starter-kit"
5
+ import Link from '@tiptap/extension-link'
6
+
7
+
8
+ const RichTextEditorAdvancedDefault = (props) => {
9
+
10
+ const editor = useEditor({
11
+ extensions: [
12
+ StarterKit,
13
+ Link
14
+ ],
15
+ content:"Add your text here. You can format your text, add links, quotes, and bullets."
16
+ })
17
+ if (!editor) {
18
+ return null
19
+ }
20
+
21
+
22
+
23
+
24
+ return (
25
+ <div>
26
+ <RichTextEditor
27
+ advancedEditor={editor}
28
+ {...props}
29
+ >
30
+ <EditorContent editor={editor}/>
31
+ </RichTextEditor>
32
+ </div>
33
+ )
34
+ }
35
+
36
+ export default RichTextEditorAdvancedDefault
@@ -0,0 +1,4 @@
1
+ The advanced variant leverages Tiptap to unlock additional UI options (e.g., consolidated nav toolbar, styling, etc.) as well as several extensions (see [Tiptap docs](https://tiptap.dev/extensions) for more). To leverage this variant, Tiptap __must be installed__ in your project. Complete docs for using the library can be found [here](https://tiptap.dev/). To get started with this variant, see the Code Example below for required imports as well as the basic setup.
2
+
3
+
4
+ NOTE: Once the Tiptap editor is initialized as shown below, you must pass that instance to the kit via the `advancedEditor` prop.
@@ -13,6 +13,7 @@ examples:
13
13
 
14
14
  react:
15
15
  - rich_text_editor_default: Default
16
+ - rich_text_editor_advanced_default: Advanced Default
16
17
  - rich_text_editor_simple: Simple
17
18
  - rich_text_editor_attributes: Attributes
18
19
  - rich_text_editor_focus: Focus
@@ -7,3 +7,4 @@ export { default as RichTextEditorTemplates } from './_rich_text_editor_template
7
7
  export { default as RichTextEditorToolbarBottom } from './_rich_text_editor_toolbar_bottom.jsx'
8
8
  export { default as RichTextEditorInline } from './_rich_text_editor_inline.jsx'
9
9
  export { default as RichTextEditorPreview } from './_rich_text_editor_preview.jsx'
10
+ export { default as RichTextEditorAdvancedDefault } from './_rich_text_editor_advanced_default.jsx'
@@ -0,0 +1,185 @@
1
+ import React from 'react'
2
+ import classnames from 'classnames'
3
+
4
+ import DateTime from '../pb_kit/dateTime'
5
+ import { globalProps, GlobalProps } from '../utilities/globalProps'
6
+ import { buildAriaProps, buildDataProps } from '../utilities/props'
7
+
8
+ import Body from '../pb_body/_body'
9
+ import Caption from '../pb_caption/_caption'
10
+ import Icon from '../pb_icon/_icon'
11
+
12
+ type TimeRangeInlineProps = {
13
+ aria?: { [key: string]: string },
14
+ className?: string,
15
+ id?: string,
16
+ data?: { [key: string]: string },
17
+ alignment?: "left" | "center" | "vertical",
18
+ size?: "sm" | "xs",
19
+ dark?: boolean,
20
+ icon?: boolean,
21
+ timezone?: boolean,
22
+ startTime: string,
23
+ endTime: string,
24
+ } & GlobalProps
25
+
26
+ const timezoneString = (dateValue: string) => {
27
+ const date = new DateTime({ value: dateValue })
28
+ return `${date.convertToTimezone()}`
29
+ }
30
+
31
+ const dateTimestamp = (dateValue: string) => {
32
+ const date = new DateTime({ value: dateValue })
33
+ return `${date.toHour()}:${date.toMinute()}${date.toMeridian()}`
34
+ }
35
+
36
+ const dateTimeIso = (dateValue: string) => {
37
+ const date = new DateTime({ value: dateValue })
38
+ return date.toIso()
39
+ }
40
+
41
+ const TimeRangeInline = (props: TimeRangeInlineProps) => {
42
+ const {
43
+ aria = {},
44
+ className,
45
+ data = {},
46
+ alignment = 'left',
47
+ size = 'sm',
48
+ dark = false,
49
+ icon = false,
50
+ timezone = false,
51
+ startTime,
52
+ endTime,
53
+ id,
54
+ } = props
55
+
56
+ const dataProps: { [key: string]: string } = buildDataProps(data)
57
+ const ariaProps: { [key: string]: string } = buildAriaProps(aria)
58
+
59
+ const separator = (
60
+ <Body color="light">
61
+ <Icon
62
+ className="pb_time_range_inline_arrow"
63
+ dark={dark}
64
+ fixedWidth
65
+ icon="long-arrow-right"
66
+ />
67
+ </Body>
68
+ )
69
+
70
+ const iconContent = () => {
71
+ return (
72
+ icon &&
73
+ <Body
74
+ color="light"
75
+ tag="span"
76
+ >
77
+ <Icon
78
+ className="pb_time_range_inline_icon"
79
+ dark={dark}
80
+ fixedWidth
81
+ icon="clock"
82
+ size={size}
83
+ tag="span"
84
+ />
85
+ </Body>
86
+ )
87
+ }
88
+
89
+ return (
90
+ <div
91
+ {...ariaProps}
92
+ {...dataProps}
93
+ className={classnames('pb_time_range_inline_kit_' + alignment, globalProps(props), className)}
94
+ id={id}
95
+ >
96
+ <div className="pb_time_range_inline_wrapper">
97
+ {size == 'xs' &&
98
+ <>
99
+ <Caption
100
+ dark={dark}
101
+ tag="span"
102
+ >
103
+ {iconContent()}
104
+ <time dateTime={dateTimeIso(startTime)}>
105
+ {` ${dateTimestamp(
106
+ startTime
107
+ )} `}
108
+ </time>
109
+ </Caption>
110
+ <Caption
111
+ className="pb_time_range_inline_arrow"
112
+ dark={dark}
113
+ tag="span"
114
+ >
115
+ {separator}
116
+ </Caption>
117
+ <Caption
118
+ dark={dark}
119
+ tag="span"
120
+ >
121
+ <time dateTime={dateTimeIso(endTime)}>
122
+ {` ${dateTimestamp(
123
+ endTime
124
+ )} `}
125
+ </time>
126
+ </Caption>
127
+ {timezone &&
128
+ <Caption
129
+ className="pb_time_range_inline_timezone"
130
+ dark={dark}
131
+ tag="span"
132
+ >
133
+ {timezoneString(endTime)}
134
+ </Caption>
135
+ }
136
+ </>
137
+ }
138
+ {size == 'sm' &&
139
+ <>
140
+ <Body
141
+ dark={dark}
142
+ tag="span"
143
+ >
144
+ {iconContent()}
145
+ <time dateTime={dateTimeIso(startTime)}>
146
+ {` ${dateTimestamp(
147
+ startTime
148
+ )} `}
149
+ </time>
150
+ </Body>
151
+ <Body
152
+ className="pb_time_range_inline_arrow"
153
+ dark={dark}
154
+ tag="span"
155
+ >
156
+ {separator}
157
+ </Body>
158
+ <Body
159
+ dark={dark}
160
+ tag="span"
161
+ >
162
+ <time dateTime={dateTimeIso(endTime)}>
163
+ {` ${dateTimestamp(
164
+ endTime
165
+ )} `}
166
+ </time>
167
+ </Body>
168
+ {timezone &&
169
+ <Body
170
+ className="pb_time_range_inline_timezone"
171
+ color="light"
172
+ dark={dark}
173
+ tag="span"
174
+ >
175
+ {timezoneString(endTime)}
176
+ </Body>
177
+ }
178
+ </>
179
+ }
180
+ </div>
181
+ </div>
182
+ )
183
+ }
184
+
185
+ export default TimeRangeInline
@@ -0,0 +1,85 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import TimeRangeInline from './_time_range_inline'
5
+
6
+ const testId = 'timeRangeInline'
7
+ const className = 'custom-class-name'
8
+
9
+ const TimeRangeInlineDefault = (props) => (
10
+ <>
11
+ <TimeRangeInline
12
+ aria={{ label: testId }}
13
+ className={className}
14
+ data={{ testid: testId }}
15
+ endTime="2012-08-02T17:49:29Z"
16
+ icon="true"
17
+ id={testId}
18
+ size="sm"
19
+ startTime="2012-08-02T15:49:29Z"
20
+ timezone="true"
21
+ {...props}
22
+ />
23
+ </>
24
+ )
25
+
26
+ test('should pass data prop', () => {
27
+ render(<TimeRangeInlineDefault />)
28
+ const kit = screen.getByTestId(testId)
29
+ expect(kit).toBeInTheDocument()
30
+ })
31
+
32
+ test('should pass className prop', () => {
33
+ render(<TimeRangeInlineDefault />)
34
+ const kit = screen.getByTestId(testId)
35
+ expect(kit).toHaveClass(className)
36
+ })
37
+
38
+ test('should pass aria prop', () => {
39
+ render(<TimeRangeInlineDefault />)
40
+ const kit = screen.getByTestId(testId)
41
+ expect(kit).toHaveAttribute('aria-label', testId)
42
+ })
43
+
44
+ test('should pass id prop', () => {
45
+ render(<TimeRangeInlineDefault />)
46
+ const kit = screen.getByTestId(testId)
47
+ expect(kit).toHaveProperty('id', testId)
48
+ })
49
+
50
+ test('should have left alignment by default', () => {
51
+ render(<TimeRangeInlineDefault />)
52
+ const kit = screen.getByTestId(testId)
53
+ expect(kit).toHaveClass('pb_time_range_inline_kit_left')
54
+ })
55
+
56
+ test('should pass alignment prop', () => {
57
+ render(<TimeRangeInlineDefault alignment="right" />)
58
+ const kit = screen.getByTestId(testId)
59
+ expect(kit).toHaveClass('pb_time_range_inline_kit_right')
60
+ })
61
+
62
+ test('should have icon', () => {
63
+ render(<TimeRangeInlineDefault />)
64
+ const kit = screen.getByTestId(testId)
65
+ const icon = kit.querySelector('.pb_time_range_inline_icon')
66
+ expect(icon).toBeInTheDocument()
67
+ })
68
+
69
+ test('should have timezone', () => {
70
+ render(<TimeRangeInlineDefault />)
71
+ const kit = screen.getByTestId(testId)
72
+ expect(kit.querySelector('.pb_time_range_inline_timezone')).toBeInTheDocument()
73
+ })
74
+
75
+ test('should render startTime', () => {
76
+ render(<TimeRangeInlineDefault />)
77
+ const kit = screen.getByTestId(testId)
78
+ expect(kit).toHaveTextContent('11:49a')
79
+ })
80
+
81
+ test('should render endTime', () => {
82
+ render(<TimeRangeInlineDefault />)
83
+ const kit = screen.getByTestId(testId)
84
+ expect(kit).toHaveTextContent('1:49p')
85
+ })
@@ -39,7 +39,7 @@ const Title = (props: TitleProps): React.ReactElement => {
39
39
  const classes = classnames(
40
40
  buildCss('pb_title_kit', `size_${size}`, variant, color, getBold),
41
41
  globalProps(props),
42
- className,
42
+ className
43
43
  )
44
44
  const Tag: React.ReactElement | any = `${tag}`
45
45
 
@@ -0,0 +1,45 @@
1
+ import React from 'react'
2
+ import classnames from 'classnames'
3
+
4
+ import { GlobalProps, globalProps } from '../utilities/globalProps'
5
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
6
+
7
+ import Body from '../pb_body/_body'
8
+ import Title from '../pb_title/_title'
9
+
10
+ type TitleDetailProps = {
11
+ align?: "left" | "center" | "right",
12
+ aria?: { [key: string]: string },
13
+ className?: string,
14
+ data?: { [key: string]: string },
15
+ detail: string,
16
+ id?: string,
17
+ title: string,
18
+ } & GlobalProps
19
+
20
+ const TitleDetail = (props: TitleDetailProps) => {
21
+ const { align = 'left', aria = {}, className, data = {}, detail, id, title } = props
22
+ const ariaProps = buildAriaProps(aria)
23
+ const dataProps = buildDataProps(data)
24
+ const pbCss = buildCss('pb_title_detail_kit', align)
25
+
26
+ return (
27
+ <div
28
+ {...ariaProps}
29
+ {...dataProps}
30
+ className={classnames(pbCss, globalProps(props), className)}
31
+ id={id}
32
+ >
33
+ <Title
34
+ size={4}
35
+ text={title}
36
+ />
37
+ <Body
38
+ color="light"
39
+ text={detail}
40
+ />
41
+ </div>
42
+ )
43
+ }
44
+
45
+ export default TitleDetail
@@ -0,0 +1,71 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import TitleDetail from './_title_detail'
5
+
6
+ const testId = 'titleDetail'
7
+ const className = 'custom-class-name'
8
+ const detail = 'Commits data and history'
9
+ const title = 'Email Notifications'
10
+
11
+ const TitleDetailDefault = (props) => (
12
+ <>
13
+ <TitleDetail
14
+ aria={{ label: testId }}
15
+ className={className}
16
+ data={{ testid: testId }}
17
+ detail={detail}
18
+ id={testId}
19
+ title={title}
20
+ {...props}
21
+ />
22
+ </>
23
+ )
24
+
25
+ test('should pass data prop', () => {
26
+ render(<TitleDetailDefault />)
27
+ const kit = screen.getByTestId(testId)
28
+ expect(kit).toBeInTheDocument()
29
+ })
30
+
31
+ test('should pass className prop', () => {
32
+ render(<TitleDetailDefault />)
33
+ const kit = screen.getByTestId(testId)
34
+ expect(kit).toHaveClass(className)
35
+ })
36
+
37
+ test('should pass aria prop', () => {
38
+ render(<TitleDetailDefault />)
39
+ const kit = screen.getByTestId(testId)
40
+ expect(kit).toHaveAttribute('aria-label', testId)
41
+ })
42
+
43
+ test('should pass id prop', () => {
44
+ render(<TitleDetailDefault />)
45
+ const kit = screen.getByTestId(testId)
46
+ expect(kit).toHaveProperty('id', testId)
47
+ })
48
+
49
+ test('should have left align by default', () => {
50
+ render(<TitleDetailDefault />)
51
+ const kit = screen.getByTestId(testId)
52
+ expect(kit).toHaveClass('pb_title_detail_kit_left')
53
+ })
54
+
55
+ test('should pass align prop', () => {
56
+ render(<TitleDetailDefault align="right" />)
57
+ const kit = screen.getByTestId(testId)
58
+ expect(kit).toHaveClass('pb_title_detail_kit_right')
59
+ })
60
+
61
+ test('should render detail', () => {
62
+ render(<TitleDetailDefault />)
63
+ const kit = screen.getByTestId(testId)
64
+ expect(kit).toHaveTextContent(detail)
65
+ })
66
+
67
+ test('should render title', () => {
68
+ render(<TitleDetailDefault />)
69
+ const kit = screen.getByTestId(testId)
70
+ expect(kit).toHaveTextContent(title)
71
+ })