playbook_ui 12.25.0 → 12.26.0.pre.alpha.PLAY603datepickerquickpickinputpresetdropdown813

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/index.js +1 -0
  4. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_swift.md +82 -1
  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 +102 -95
  7. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +30 -2
  8. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +11 -4
  9. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +84 -1
  10. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +38 -4
  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 +168 -0
  16. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_calendar_input_icon.scss +3 -2
  17. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_quick_pick_styles.scss +75 -0
  18. data/app/pb_kits/playbook/pb_detail/_detail.scss +44 -0
  19. data/app/pb_kits/playbook/pb_detail/_detail.tsx +55 -0
  20. data/app/pb_kits/playbook/pb_detail/_detail_mixins.scss +29 -0
  21. data/app/pb_kits/playbook/pb_detail/detail.html.erb +7 -0
  22. data/app/pb_kits/playbook/pb_detail/detail.rb +31 -0
  23. data/app/pb_kits/playbook/pb_detail/detail.test.jsx +46 -0
  24. data/app/pb_kits/playbook/pb_detail/docs/_description.md +1 -0
  25. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.html.erb +34 -0
  26. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.jsx +49 -0
  27. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.md +1 -0
  28. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.html.erb +24 -0
  29. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.jsx +38 -0
  30. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.md +6 -0
  31. data/app/pb_kits/playbook/pb_detail/docs/_detail_default.html.erb +3 -0
  32. data/app/pb_kits/playbook/pb_detail/docs/_detail_default.jsx +13 -0
  33. data/app/pb_kits/playbook/pb_detail/docs/_detail_styled.html.erb +22 -0
  34. data/app/pb_kits/playbook/pb_detail/docs/_detail_styled.jsx +32 -0
  35. data/app/pb_kits/playbook/pb_detail/docs/example.yml +11 -0
  36. data/app/pb_kits/playbook/pb_detail/docs/index.js +4 -0
  37. data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +14 -13
  38. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +3 -2
  39. data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +212 -0
  40. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +58 -98
  41. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +340 -86
  42. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.md +1 -1
  43. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +1 -0
  44. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +1 -1
  45. data/app/pb_kits/playbook/pb_nav/_item.tsx +1 -1
  46. data/app/pb_kits/playbook/pb_nav/_subtle_mixin.scss +1 -1
  47. data/app/pb_kits/playbook/playbook-doc.js +2 -0
  48. data/dist/menu.yml +1 -0
  49. data/dist/playbook-rails.js +279 -7
  50. data/lib/playbook/version.rb +2 -2
  51. metadata +31 -9
  52. data/app/pb_kits/playbook/pb_multi_level_select/_multi_select_helper.tsx +0 -31
  53. data/app/pb_kits/playbook/pb_multi_level_select/helper_functions.ts +0 -87
@@ -3,6 +3,7 @@ import { BaseOptions } from 'flatpickr/dist/types/options'
3
3
  import monthSelectPlugin from 'flatpickr/dist/plugins/monthSelect'
4
4
  import weekSelect from "flatpickr/dist/plugins/weekSelect/weekSelect"
5
5
  import timeSelectPlugin from './plugins/timeSelect'
6
+ import quickPickPlugin from './plugins/quickPick'
6
7
 
7
8
  const getPositionElement = (element: string | Element) => {
8
9
  return (typeof element === 'string') ? document.querySelectorAll(element)[0] : element
@@ -19,10 +20,11 @@ type DatePickerConfig = {
19
20
  hideIcon?: boolean;
20
21
  inLine?: boolean,
21
22
  onChange: (dateStr: string, selectedDates: Date[]) => void,
23
+ selectionType?: "month" | "week" | "quickpick" | "",
22
24
  onClose: (dateStr: Date[] | string, selectedDates: Date[] | string) => void,
23
- selectionType?: "month" | "week" | "",
24
25
  showTimezone?: boolean,
25
26
  staticPosition: boolean,
27
+ thisRangesEndToday?: boolean,
26
28
  timeCaption?: string,
27
29
  timeFormat?: string,
28
30
  yearRange: number[]
@@ -51,6 +53,7 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
51
53
  selectionType,
52
54
  showTimezone,
53
55
  staticPosition = true,
56
+ thisRangesEndToday = false,
54
57
  timeCaption = 'Select Time',
55
58
  timeFormat = 'at h:i K',
56
59
  yearRange,
@@ -89,19 +92,24 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
89
92
  }
90
93
  }
91
94
 
92
- const setPlugins = () => {
93
- let pluginList = []
95
+ const setPlugins = (thisRangesEndToday: boolean) => {
96
+ const pluginList = []
94
97
 
95
98
  // month and week selection
96
99
  if (selectionType === "month" || plugins.length > 0) {
97
100
  pluginList.push(monthSelectPlugin({ shorthand: true, dateFormat: 'F Y', altFormat: 'F Y' }))
98
101
  } else if ( selectionType === "week") {
99
102
  pluginList.push(weekSelect())
103
+
104
+ } else if (selectionType === "quickpick") {
105
+ //------- QUICKPICK VARIANT PLUGIN -------------//
106
+ pluginList.push(quickPickPlugin(thisRangesEndToday))
100
107
  }
101
108
 
102
109
  // time selection
103
110
  if (enableTime) pluginList.push(timeSelectPlugin({ caption: timeCaption, showTimezone: showTimezone}))
104
111
 
112
+
105
113
  return pluginList
106
114
  }
107
115
 
@@ -144,6 +152,9 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
144
152
  },
145
153
  ] : disabledParser(),
146
154
  enableTime,
155
+ locale: {
156
+ rangeSeparator: ' → '
157
+ },
147
158
  maxDate,
148
159
  minDate,
149
160
  mode,
@@ -164,17 +175,40 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
164
175
  onYearChange: [() => {
165
176
  yearChangeHook()
166
177
  }],
167
- plugins: setPlugins(),
178
+ plugins: setPlugins(thisRangesEndToday),
168
179
  position,
169
180
  positionElement: getPositionElement(positionElement),
170
181
  prevArrow: '<i class="far fa-angle-left"></i>',
171
182
  static: staticPosition,
172
183
  })
173
184
 
185
+
174
186
  // ===========================================================
175
187
  // Additional JS Functionality |
176
188
  // ===========================================================
177
189
 
190
+ // opens flatpickr instance when calander icon is clicked so we can have a hover state on icon
191
+ // window.addEventListener("DOMContentLoaded", (event) => {
192
+ // event.preventDefault();
193
+ // function attachIconClickHandler() {
194
+ // const variantArr = document.querySelectorAll(`#cal-icon-${pickerId}`)
195
+ // if (!variantArr) {
196
+ // setTimeout(attachIconClickHandler, 100);
197
+ // return;
198
+ // }
199
+
200
+ // const instance = document.querySelector<HTMLElement & { [x: string]: any }>(`#${pickerId}`)._flatpickr
201
+ // variantArr.forEach((icon) => {
202
+ // icon.addEventListener("click", function(event) {
203
+ // event.preventDefault();
204
+ // instance.open()
205
+ // });
206
+ // })
207
+ // }
208
+
209
+ // attachIconClickHandler();
210
+ // });
211
+
178
212
  // Assign dynamically sourced flatpickr instance to variable
179
213
  const picker = document.querySelector<HTMLElement & { [x: string]: any }>(`#${pickerId}`)._flatpickr
180
214
  picker.innerContainer.parentElement.id = `cal-${pickerId}`
@@ -0,0 +1,8 @@
1
+ <%= pb_rails("date_picker", props: {
2
+ allow_input: true,
3
+ mode: "range",
4
+ picker_id: "date-picker-quick-pick",
5
+ placeholder: "mm/dd/yyyy → mm/dd/yyyy",
6
+ selection_type: "quickpick"
7
+ }) %>
8
+
@@ -0,0 +1,18 @@
1
+ import React from 'react'
2
+
3
+ import DatePicker from '../_date_picker'
4
+
5
+ const DatePickerQuickPick = (props) => (
6
+ <div>
7
+ <DatePicker
8
+ allowInput
9
+ mode="range"
10
+ pickerId="date-picker-quick-pick"
11
+ placeholder="mm/dd/yyyy → mm/dd/yyyy"
12
+ selectionType="quickpick"
13
+ {...props}
14
+ />
15
+ </div>
16
+ )
17
+
18
+ export default DatePickerQuickPick
@@ -8,6 +8,7 @@ examples:
8
8
  - date_picker_input: Input Field
9
9
  - date_picker_label: Label
10
10
  - date_picker_range: Range
11
+ - date_picker_quick_pick: Range (Quick Pick)
11
12
  - date_picker_format: Format
12
13
  - date_picker_disabled: Disabled Dates
13
14
  - date_picker_min_max: Min Max
@@ -33,6 +34,7 @@ examples:
33
34
  - date_picker_on_change: onChange
34
35
  - date_picker_on_close: onClose
35
36
  - date_picker_range: Range
37
+ - date_picker_quick_pick: Range (Quick Pick)
36
38
  - date_picker_format: Format
37
39
  - date_picker_disabled: Disabled Dates
38
40
  - date_picker_min_max: Min Max
@@ -19,4 +19,5 @@ export { default as DatePickerWeek } from './_date_picker_week.jsx'
19
19
  export { default as DatePickerPositions } from './_date_picker_positions.jsx'
20
20
  export { default as DatePickerPositionsElement } from './_date_picker_positions_element.jsx'
21
21
  export { default as DatePickerAllowInput } from './_date_picker_allow_input'
22
- export { default as DatePickerOnClose } from './_date_picker_on_close.jsx'
22
+ export { default as DatePickerQuickPick } from './_date_picker_quick_pick'
23
+ export { default as DatePickerOnClose } from './_date_picker_on_close.jsx'
@@ -0,0 +1,168 @@
1
+ import moment from 'moment'
2
+
3
+ type FpTypes = {
4
+ setDate: (arg0: any, arg1: boolean) => void,
5
+ config: { [key: string]: string },
6
+ clear: (arg0: boolean, arg1: boolean) => void,
7
+ close: () => void,
8
+ calendarContainer?: {
9
+ classList: { add: (arg0: string) => void };
10
+ prepend: (arg0: HTMLDivElement) => void;
11
+ append: (arg0: HTMLDivElement) => void;
12
+ },
13
+ loadedPlugins: string[],
14
+ };
15
+
16
+ type pluginDataType = {
17
+ ranges: { [key: string]: Date[] },
18
+ rangesNav: HTMLUListElement,
19
+ rangesButtons: [] | any,
20
+ }
21
+
22
+ let activeLabel = ""
23
+
24
+ const quickPickPlugin = (thisRangesEndToday: boolean) => {
25
+ return function (fp: FpTypes & any): any {
26
+ const thisWeekEndDate = thisRangesEndToday ? new Date() : moment().endOf('isoWeek').toDate()
27
+ const thisMonthEndDate = thisRangesEndToday ? new Date() : moment().endOf('month').toDate()
28
+ const thisQuarterEndDate = thisRangesEndToday ? new Date() : moment().endOf('quarter').toDate()
29
+ const thisYearEndDate = thisRangesEndToday ? new Date() : moment().endOf('year').toDate()
30
+
31
+ // variable that holds the ranges available
32
+ const ranges = {
33
+ 'Today': [new Date(), new Date()],
34
+ 'Yesterday': [moment().subtract(1, 'days').toDate(), moment().subtract(1, 'days').toDate()],
35
+ 'This week': [moment().startOf('isoWeek').toDate(), thisWeekEndDate],
36
+ 'This month': [moment().startOf('month').toDate(), thisMonthEndDate],
37
+ 'This quarter': [moment().startOf('quarter').toDate(), thisQuarterEndDate],
38
+ 'This year': [moment().startOf('year').toDate(), thisYearEndDate],
39
+ 'Last week': [
40
+ moment().subtract(1, 'week').startOf('isoWeek').toDate(),
41
+ moment().subtract(1, 'week').endOf('isoWeek').toDate()
42
+ ],
43
+ 'Last month': [
44
+ moment().subtract(1, 'month').startOf('month').toDate(),
45
+ moment().subtract(1, 'month').endOf('month').toDate()
46
+ ],
47
+ 'Last quarter': [
48
+ moment().subtract(1, 'quarter').startOf('quarter').toDate(),
49
+ moment().subtract(1, 'quarter').endOf('quarter').toDate()
50
+ ],
51
+ 'Last year': [
52
+ moment().subtract(1, 'year').startOf('year').toDate(),
53
+ moment().subtract(1, 'year').endOf('year').toDate()
54
+ ]
55
+ }
56
+ //creating the ul element for the nav dropdown and giving it classnames
57
+ const rangesNav = document.createElement('ul');
58
+
59
+ // creating the pluginData object that will hold the properties of this plugin
60
+ const pluginData: pluginDataType = {
61
+ ranges: ranges,
62
+ rangesNav: rangesNav,
63
+ rangesButtons: [],
64
+ };
65
+
66
+ /**
67
+ * @param {string} label
68
+ * @returns HTML Element
69
+ */
70
+
71
+ //function for creating the range buttons in the nav
72
+ const addRangeButton = (label: string) => {
73
+
74
+ // creating new elements to mimick selectable card component
75
+ const div2 = document.createElement('div');
76
+ div2.className = "nav-item-link"
77
+ div2.innerHTML = label;
78
+
79
+ pluginData.rangesButtons[label] = div2;
80
+
81
+ // create li elements inside the dropdown
82
+ const item = document.createElement('li');
83
+ item.className = "nav-item";
84
+
85
+ // append those nav items to the li items
86
+ item.appendChild(pluginData.rangesButtons[label]);
87
+
88
+ // append the li item to the ul rangeNav prop
89
+ pluginData.rangesNav.appendChild(item);
90
+
91
+ // return the ranges buton prop
92
+ return pluginData.rangesButtons[label];
93
+ };
94
+
95
+ const selectActiveRangeButton = (selectedDates: Array<string>) => {
96
+ const current = pluginData.rangesNav.querySelector('.active');
97
+
98
+ if (current) {
99
+ current.classList.remove('active');
100
+ }
101
+ /** conditional statment to extract start and end dates from selectedDates,
102
+ * then loop through ranges prop in pluginData
103
+ * and check if chosen dates equal to a date in the ranges prop
104
+ * if they are equal, add the active class
105
+ */
106
+ if (selectedDates.length > 0 && activeLabel) {
107
+ // const selected = pluginData.rangesNav.querySelectorAll(".nav-item-link")
108
+ // selected.forEach(el => {
109
+ // if (el.innerHTML === activeLabel)
110
+ // el.classList.add('active')
111
+ // return
112
+ // })
113
+
114
+ pluginData.rangesButtons[activeLabel].classList.add('active');
115
+ }
116
+ }
117
+
118
+
119
+ return {
120
+ // onReady is a hook from flatpickr that runs when calender is in a ready state
121
+ onReady(selectedDates: Array<string>) {
122
+ // loop through the ranges and create an anchor tag for each range and add an event listener to set the date when user clicks on a date range
123
+ for (const [label, range] of Object.entries(pluginData.ranges)) {
124
+ addRangeButton(label).addEventListener('click', function () {
125
+
126
+ const start = moment(range[0]).toDate();
127
+ const end = moment(range[1]).toDate();
128
+
129
+ if (!start) {
130
+ fp.clear();
131
+ }
132
+ else {
133
+ activeLabel = label
134
+ fp.setDate([start, end], true);
135
+ fp.close();
136
+ }
137
+ });
138
+ }
139
+ // conditional to check if there is a dropdown to add it to the calendar container and get it the classes it needs
140
+ if (pluginData.rangesNav.children.length > 0) {
141
+
142
+ fp.calendarContainer.prepend(pluginData.rangesNav);
143
+ pluginData.rangesNav.classList.add('quick-pick-ul')
144
+ fp.calendarContainer.classList.add('quick-pick-drop-down');
145
+
146
+ /**
147
+ *
148
+ * @param {Array} selectedDates
149
+ */
150
+ // function to give the active button the active class
151
+ selectActiveRangeButton(selectedDates);
152
+ }
153
+ },
154
+ onValueUpdate(selectedDates: Array<string>) {
155
+ selectActiveRangeButton(selectedDates);
156
+ },
157
+
158
+ onClose(selectedDates: Array<string>) {
159
+ // set the input value to the selected dates when the dropdown is closed
160
+ if (selectedDates.length < 2 && selectedDates.length > 0) {
161
+ fp.input.placeholder = fp.formatDate(this.selectedDates[0], fp.config.dateFormat);
162
+ }
163
+ }
164
+ };
165
+ };
166
+ }
167
+
168
+ export default quickPickPlugin;
@@ -1,3 +1,4 @@
1
+ @import "../../tokens/colors";
1
2
  // Calendar Icon Styles
2
3
  .cal_icon_wrapper {
3
4
  pointer-events: none;
@@ -13,8 +14,8 @@
13
14
  padding-left: $space_sm - 1;
14
15
  color: $text_lt_light;
15
16
  @media (hover: hover) {
16
- &:hover {
17
- cursor: pointer;
17
+ &:hover{
18
+ background-color: rgba($focus_input_light,$opacity_5);
18
19
  }
19
20
  }
20
21
  &.dark {
@@ -0,0 +1,75 @@
1
+ @import "../../tokens/animation-curves";
2
+ @import "../../tokens/colors";
3
+ @import "../../tokens/typography";
4
+ @import "../../tokens/titles";
5
+ @import "../../tokens/spacing";
6
+
7
+ $pb_card_border_width: 1px;
8
+ $pb_card_border_radius: $border_rad_heavier;
9
+
10
+ // used to display dropdown on the left of the calender
11
+ .quick-pick-drop-down {
12
+ width: auto;
13
+ display: grid;
14
+ }
15
+
16
+ .quick-pick-ul {
17
+ padding: $space_xs 0px;
18
+ margin: 0;
19
+ list-style: none;
20
+ }
21
+
22
+ .nav-item {
23
+ list-style: none;
24
+ border-radius: 6px;
25
+ border-bottom: 0;
26
+ margin: $space_xs $space_sm;
27
+ }
28
+
29
+ .nav-item-link {
30
+ text-decoration: none;
31
+ border-width: $pb_card_border_width;
32
+ border-style: solid;
33
+ border-color: $border_light;
34
+ border-radius: $pb_card_border_radius;
35
+ padding: $space_xs 14px;
36
+ transition-property: color, background-color;
37
+ transition-duration: 0.15s;
38
+ transition-timing-function: $bezier;
39
+ line-height: 1.4;
40
+ color: $charcoal;
41
+ font-size: $font_default;
42
+ font-weight: $regular;
43
+ &.active {
44
+ border-width: 2px;
45
+ border-color: $primary;
46
+ }
47
+ @media (hover:hover) {
48
+ &:hover {
49
+ cursor: pointer;
50
+ box-shadow: $shadow-deep;
51
+ border-color: $slate;
52
+ }
53
+ }
54
+ }
55
+
56
+ // Hide the calendar
57
+ .quick-pick-drop-down > .flatpickr-months, .quick-pick-drop-down > .flatpickr-innerContainer {
58
+ display: none;
59
+ }
60
+
61
+ @media only screen and (max-width: 767px) {
62
+ .quick-pick-ul {
63
+ padding: $space_xs $space_xs;
64
+ display: grid;
65
+ grid-template-columns: 1fr 1fr;
66
+ }
67
+
68
+ .nav-item {
69
+ margin: $space_xxs $space_xs;
70
+ }
71
+
72
+ .nav-item-link {
73
+ padding: $space_xs $space_xxs;
74
+ }
75
+ }
@@ -0,0 +1,44 @@
1
+ @import "./detail_mixins";
2
+ @import "../tokens/titles";
3
+ @import "../tokens/typography";
4
+
5
+ [class^=pb_detail_kit]{
6
+ @include pb_detail;
7
+
8
+ @each $color_name, $color_value in $pb_detail_colors {
9
+ &[class*=_#{$color_name}] {
10
+ @include pb_detail($color_value);
11
+ }
12
+ }
13
+
14
+ @each $dark_color_name, $dark_color_value in $pb_dark_detail_colors{
15
+ &[class*=_#{$dark_color_name}][class*=dark]{
16
+ @include pb_detail($dark_color_value)
17
+ }
18
+ }
19
+
20
+ // Styles
21
+ &.bold,
22
+ &.bold.dark,
23
+ b,
24
+ strong {
25
+ font-weight: $bold;
26
+ }
27
+
28
+ a {
29
+ color: $primary;
30
+ &:hover {
31
+ cursor: pointer;
32
+ color: $text_lt_default;
33
+ }
34
+ }
35
+
36
+ em {
37
+ font-weight: $bold;
38
+ }
39
+
40
+ small {
41
+ font-size: $font_smaller;
42
+ letter-spacing: $lspace_loose;
43
+ }
44
+ }
@@ -0,0 +1,55 @@
1
+ import React from 'react'
2
+ import classnames from 'classnames'
3
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
4
+ import { globalProps, GlobalProps } from '../utilities/globalProps'
5
+
6
+ type DetailProps = {
7
+ aria?: { [key: string]: string },
8
+ bold?: boolean,
9
+ children?: React.ReactChild[] | React.ReactChild,
10
+ className?: string,
11
+ color?: 'light' | 'default' | 'lighter' | 'link' | 'error' | 'success',
12
+ dark?: boolean,
13
+ data?: { [key: string]: string },
14
+ id?: string,
15
+ tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div',
16
+ text?: string,
17
+ } & GlobalProps
18
+
19
+ const Detail = (props: DetailProps) => {
20
+ const {
21
+ aria = {},
22
+ bold = false,
23
+ children,
24
+ className,
25
+ color = 'light',
26
+ data = {},
27
+ id = '',
28
+ tag = 'div',
29
+ text= ''
30
+ } = props
31
+
32
+ const ariaProps: {[key: string]: any} = buildAriaProps(aria)
33
+ const dataProps: {[key: string]: any} = buildDataProps(data)
34
+ const isBold = bold ? "bold" : null
35
+ const classes = classnames(
36
+ buildCss('pb_detail_kit', color),
37
+ isBold,
38
+ globalProps(props),
39
+ className
40
+ )
41
+ const Tag: React.ReactElement | any = `${tag}`
42
+
43
+ return (
44
+ <Tag
45
+ {...ariaProps}
46
+ {...dataProps}
47
+ className={classes}
48
+ id={id}
49
+ >
50
+ {text || children}
51
+ </Tag>
52
+ )
53
+ }
54
+
55
+ export default Detail
@@ -0,0 +1,29 @@
1
+ @import "../tokens/colors";
2
+ @import "../tokens/line_height";
3
+ @import "../tokens/typography";
4
+
5
+ $pb_detail_colors: (
6
+ light: $text_lt_light,
7
+ default: $text_lt_default,
8
+ lighter: $text_lt_lighter,
9
+ link: $primary,
10
+ error: $error,
11
+ success: $text_lt_success_sm,
12
+ );
13
+
14
+ $pb_dark_detail_colors: (
15
+ light: $text_dk_light,
16
+ default: $text_dk_default,
17
+ lighter: $text_dk_lighter,
18
+ link: $primary,
19
+ error: $error_dark,
20
+ success: $text_dk_success_sm,
21
+ );
22
+
23
+ @mixin pb_detail($color: $text_lt_light) {
24
+ line-height: $lh_tight;
25
+ color: $color;
26
+ font-size: $text_small;
27
+ font-weight: $regular;
28
+ font-family: $font-family-base;
29
+ }
@@ -0,0 +1,7 @@
1
+ <%= content_tag(object.tag,
2
+ aria: object.aria,
3
+ class: object.classname,
4
+ data: object.data,
5
+ id: object.id) do %>
6
+ <%= object.content %>
7
+ <% end %>
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module PbDetail
5
+ class Detail < Playbook::KitBase
6
+ prop :bold, type: Playbook::Props::Boolean,
7
+ default: false
8
+ prop :color, type: Playbook::Props::Enum,
9
+ values: %w[light default lighter link error success],
10
+ default: "light"
11
+ prop :tag, type: Playbook::Props::Enum,
12
+ values: %w[h1 h2 h3 h4 h5 h6 p span div],
13
+ default: "div"
14
+ prop :text
15
+
16
+ def classname
17
+ generate_classname("pb_detail_kit", color) + is_bold
18
+ end
19
+
20
+ def content
21
+ super.presence || text
22
+ end
23
+
24
+ private
25
+
26
+ def is_bold
27
+ bold ? " bold" : ""
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,46 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import Detail from './_detail'
5
+
6
+ test('returns namespaced class name', () => {
7
+ render(
8
+ <Detail
9
+ data={{ testid: 'primary-test' }}
10
+ text="Test class name"
11
+ />
12
+ )
13
+
14
+ const kit = screen.getByTestId('primary-test')
15
+ expect(kit).toHaveClass('pb_detail_kit_light')
16
+ })
17
+
18
+ test('with colors', () => {
19
+ ['light', 'default', 'lighter', 'link', 'success', 'error'].forEach((color) => {
20
+ const testId = `colors-test-${color}`
21
+
22
+ render(
23
+ <Detail
24
+ color={color}
25
+ data={{ testid: testId }}
26
+ text="Test colors"
27
+ />
28
+ )
29
+
30
+ const kit = screen.getByTestId(testId)
31
+ expect(kit).toHaveClass(`pb_detail_kit_${color}`)
32
+ })
33
+ })
34
+
35
+ test('bold font-weight should be 600', () => {
36
+ render(
37
+ <Detail
38
+ bold
39
+ data={{ testid: 'primary-test' }}
40
+ text="Test bold prop"
41
+ />
42
+ )
43
+
44
+ const kit = screen.getByTestId('primary-test')
45
+ expect(kit).toHaveClass("bold")
46
+ })
@@ -0,0 +1 @@
1
+ Used for tables or designs with large amounts of data or text.
@@ -0,0 +1,34 @@
1
+ <%= pb_rails("detail", props: {
2
+ bold: true,
3
+ text: "I am a bold detail kit"
4
+ }) %>
5
+
6
+ <%= pb_rails("detail", props: {
7
+ bold: true,
8
+ color: "default",
9
+ text: "I am a bold detail kit"
10
+ }) %>
11
+
12
+ <%= pb_rails("detail", props: {
13
+ bold: true,
14
+ color: "lighter",
15
+ text: "I am a bold detail kit"
16
+ }) %>
17
+
18
+ <%= pb_rails("detail", props: {
19
+ bold: true,
20
+ color: "link",
21
+ text: "I am a bold detail kit"
22
+ }) %>
23
+
24
+ <%= pb_rails("detail", props: {
25
+ bold: true,
26
+ color: "error",
27
+ text: "I am a bold detail kit"
28
+ }) %>
29
+
30
+ <%= pb_rails("detail", props: {
31
+ bold: true,
32
+ color: "success",
33
+ text: "I am a bold detail kit"
34
+ }) %>