playbook_ui 12.17.1 → 12.18.0.pre.alpha.PLAY603datepickerquickpickinputpresetdropdown617

Sign up to get free protection for your applications and to get access to all the features.
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
+ })