playbook_ui 14.12.0.pre.alpha.advancedtablealignmentfixes5693 → 14.12.0.pre.alpha.play1790darkaudittable5802

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +3 -4
  4. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +8 -13
  5. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +2 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +1 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_loading.html.erb +33 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_loading_rails.md +1 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_loading.md → _advanced_table_loading_react.md} +2 -2
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/index.js +9 -6
  12. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +3 -1
  13. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +9 -5
  14. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +2 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +9 -6
  16. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +2 -0
  17. data/app/pb_kits/playbook/pb_avatar/_avatar.scss +5 -0
  18. data/app/pb_kits/playbook/pb_button/button.rb +1 -1
  19. data/app/pb_kits/playbook/pb_copy_button/_copy_button.scss +3 -0
  20. data/app/pb_kits/playbook/pb_copy_button/_copy_button.tsx +92 -0
  21. data/app/pb_kits/playbook/pb_copy_button/copy_button.test.jsx +64 -0
  22. data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_default.jsx +21 -0
  23. data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_from.jsx +45 -0
  24. data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_from.md +1 -0
  25. data/app/pb_kits/playbook/pb_copy_button/docs/example.yml +8 -0
  26. data/app/pb_kits/playbook/pb_copy_button/docs/index.js +2 -0
  27. data/app/pb_kits/playbook/pb_date/_date.tsx +14 -4
  28. data/app/pb_kits/playbook/pb_date/docs/_date_default.jsx +2 -1
  29. data/app/pb_kits/playbook/pb_date/docs/_date_unstyled.jsx +13 -5
  30. data/app/pb_kits/playbook/pb_file_upload/file_upload.html.erb +1 -6
  31. data/app/pb_kits/playbook/pb_filter/filter.html.erb +1 -5
  32. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_auto_close.html.erb +58 -0
  33. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_auto_close_rails.md +3 -0
  34. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/example.yml +1 -0
  35. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/index.js +7 -5
  36. data/app/pb_kits/playbook/pb_form_group/form_group.html.erb +1 -6
  37. data/app/pb_kits/playbook/pb_form_pill/form_pill.html.erb +1 -1
  38. data/app/pb_kits/playbook/pb_table/docs/_table_with_background_kit.html.erb +6 -9
  39. data/app/pb_kits/playbook/pb_table/docs/_table_with_background_kit.jsx +6 -9
  40. data/app/pb_kits/playbook/pb_table/styles/_desktop_collapse.scss +26 -0
  41. data/app/pb_kits/playbook/pb_table/styles/_mobile.scss +0 -1
  42. data/app/pb_kits/playbook/pb_table/styles/_mobile_collapse.scss +25 -0
  43. data/app/pb_kits/playbook/pb_table/styles/_tablet_collapse.scss +25 -0
  44. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +3 -1
  45. data/dist/chunks/{_typeahead-BWwaAo_0.js → _typeahead-BIhRQo8Q.js} +3 -3
  46. data/dist/chunks/_weekday_stacked-CttHBFW3.js +45 -0
  47. data/dist/chunks/vendor.js +1 -1
  48. data/dist/menu.yml +6 -0
  49. data/dist/playbook-doc.js +1 -1
  50. data/dist/playbook-rails-react-bindings.js +1 -1
  51. data/dist/playbook-rails.js +1 -1
  52. data/dist/playbook.css +1 -1
  53. data/lib/playbook/pb_forms_global_props_helper.rb +136 -0
  54. data/lib/playbook/pb_forms_helper.rb +13 -4
  55. data/lib/playbook/version.rb +1 -1
  56. metadata +19 -6
  57. data/dist/chunks/_weekday_stacked-N1NVUtQO.js +0 -45
  58. /data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/{_fixed_confirmation_toast_auto_close.md → _fixed_confirmation_toast_auto_close_react.md} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e4dc3d2e5a79486ca82c7d90654b0cf1db86bdb42cc9c0540ffb9635c373174
4
- data.tar.gz: cb9d6f1a2680e4ac81dc637ec1984efa4368d5b0739c44f6134ec44f214dccd2
3
+ metadata.gz: 136b50dee766ec4667e6d2f602d111a863ce4020dd67fe561bf2778ebd060fb1
4
+ data.tar.gz: 3ac4d8e93f62e1814d1ebe98fe4532239eb54370421b5bbad63503411d7639f7
5
5
  SHA512:
6
- metadata.gz: 77ec944b74d30f62a35b54bb1138fa97dd7b4635a67375336fd6c4fd6d3d2875abb8338d271a874688c22f562e126c49387d2ce5ca1d9610a3b12d077f5efb7a
7
- data.tar.gz: dfbf55ff877f9c17064e58ee45b72a24adf289238e3b06cac9b27f4fa3492dec18d7d6b756cd5053b954d1142de84942468d8b794e2f3432dc8c88e16c19a3c7
6
+ metadata.gz: e07d993618ba3291e460247bfae535f6725c3563a10bc58e4ac90bcedb436088f73c6c979114ca381f060bc222dd640b32cd66bb0fd91d6a6a8c298f26eb3d64
7
+ data.tar.gz: 98ffa30e5b69b4759356a445a308eb9858522f206df9dff83b142e92bc75376d60235719d777702a3185ecbb2a51c2c2f7b64a7998325482f607feab9e249c61
@@ -15,6 +15,7 @@
15
15
  @import 'pb_circle_chart/circle_chart';
16
16
  @import 'pb_circle_icon_button/circle_icon_button';
17
17
  @import 'pb_collapsible/collapsible';
18
+ @import 'pb_copy_button/copy_button';
18
19
  @import 'pb_contact/contact';
19
20
  @import 'pb_currency/currency';
20
21
  @import 'pb_dashboard_value/dashboard_value';
@@ -89,7 +89,6 @@
89
89
  }
90
90
  }
91
91
 
92
-
93
92
  .table-header-cells-active:first-child {
94
93
  color: $primary !important;
95
94
  }
@@ -179,7 +178,7 @@
179
178
  }
180
179
 
181
180
  // Responsive Styles
182
- @media only screen and (max-width: $screen-xl-min) {
181
+ @media only screen and (max-width: $screen-xl-min) {
183
182
  &[class*="advanced-table-responsive-scroll"] {
184
183
  border-radius: 4px;
185
184
  box-shadow: 1px 0 0 0px $border_light,
@@ -215,7 +214,7 @@
215
214
  .bg-white td:first-child {
216
215
  background-color: $white;
217
216
  }
218
-
217
+
219
218
  }
220
219
  }
221
220
  @media only screen and (min-width: $screen-xl-min) {
@@ -306,4 +305,4 @@
306
305
  }
307
306
  }
308
307
  }
309
- }
308
+ }
@@ -1,15 +1,10 @@
1
1
  <%= pb_content_tag do %>
2
- <%= pb_rails("table", props: { size: "sm", data_table: true, number_spacing:"tabular", responsive: "none", dark: dark }.merge(object.table_props)) do %>
3
- <% if content.present? %>
4
- <% content.presence %>
5
- <% else %>
6
- <%= pb_rails("advanced_table/table_header", props: { column_definitions: object.column_definitions,
7
- enable_toggle_expansion: object.enable_toggle_expansion,
8
- responsive: object.responsive }) %>
9
- <%= pb_rails("advanced_table/table_body", props: { id: object.id,
10
- table_data: object.table_data,
11
- column_definitions: object.column_definitions,
12
- responsive: object.responsive }) %>
13
- <% end %>
14
- <% end %>
2
+ <%= pb_rails("table", props: { size: "sm", data_table: true, number_spacing:"tabular", responsive:"none", dark: dark, classname: object.loading ? "content-loading" : "" }.merge(object.table_props)) do %>
3
+ <% if content.present? %>
4
+ <% content.presence %>
5
+ <% else %>
6
+ <%= pb_rails("advanced_table/table_header", props: { column_definitions: object.column_definitions, enable_toggle_expansion: object.enable_toggle_expansion, responsive: object.responsive, loading: object.loading }) %>
7
+ <%= pb_rails("advanced_table/table_body", props: { id: object.id, table_data: object.table_data, column_definitions: object.column_definitions, responsive: object.responsive, loading: object.loading }) %>
8
+ <% end %>
9
+ <% end %>
15
10
  <% end %>
@@ -10,6 +10,8 @@ module Playbook
10
10
  prop :enable_toggle_expansion, type: Playbook::Props::Enum,
11
11
  values: %w[all header none],
12
12
  default: "header"
13
+ prop :loading, type: Playbook::Props::Boolean,
14
+ default: false
13
15
  prop :responsive, type: Playbook::Props::Enum,
14
16
  values: %w[none scroll],
15
17
  default: "scroll"
@@ -245,7 +245,7 @@ test("toggleExpansionAll button exists and toggles subrows open and closed", asy
245
245
  })
246
246
 
247
247
 
248
- test("loading state + initialLoadingRowCount prop", () => {
248
+ test("loading state + initialLoadingRowsCount prop", () => {
249
249
  render(
250
250
  <AdvancedTable
251
251
  columnDefinitions={columnDefinitions}
@@ -0,0 +1,33 @@
1
+ <% column_definitions = [
2
+ {
3
+ accessor: "year",
4
+ label: "Year",
5
+ cellAccessors: ["quarter", "month", "day"],
6
+ },
7
+ {
8
+ accessor: "newEnrollments",
9
+ label: "New Enrollments",
10
+ },
11
+ {
12
+ accessor: "scheduledMeetings",
13
+ label: "Scheduled Meetings",
14
+ },
15
+ {
16
+ accessor: "attendanceRate",
17
+ label: "Attendance Rate",
18
+ },
19
+ {
20
+ accessor: "completedClasses",
21
+ label: "Completed Classes",
22
+ },
23
+ {
24
+ accessor: "classCompletionRate",
25
+ label: "Class Completion Rate",
26
+ },
27
+ {
28
+ accessor: "graduatedStudents",
29
+ label: "Graduated Students",
30
+ }
31
+ ] %>
32
+
33
+ <%= pb_rails("advanced_table", props: { id: "beta_table", table_data: @table_data, column_definitions: column_definitions, loading: true }) %>
@@ -0,0 +1 @@
1
+ The optional `loading` prop takes a boolean value that can be managed using state. If loading is true, the table will display the loading skeleton and once loading is false, the table will render with the data provided.
@@ -1,3 +1,3 @@
1
- the optional `loading` prop takes a boolean value that can be managed using state. If loading is true, the table will display the loading skeleton and once loading is false, the table will render with the data provided.
1
+ The optional `loading` prop takes a boolean value that can be managed using state. If loading is true, the table will display the loading skeleton and once loading is false, the table will render with the data provided.
2
2
 
3
- By default, the inital row count of the loading skeleton is set to 10. If you want more control over this initial row count, the optional `initialLoadingRowCount` prop can be used to pass in a number. __NOTE__: This is only for the first render of the table, subsequent loading skeleton row count logic is handled within the kit itself.
3
+ By default, the inital row count of the loading skeleton is set to 10. If you want more control over this initial row count, the optional `initialLoadingRowsCount` prop can be used to pass in a number. __NOTE__: This is only for the first render of the table, subsequent loading skeleton row count logic is handled within the kit itself.
@@ -1,6 +1,7 @@
1
1
  examples:
2
2
  rails:
3
3
  - advanced_table_beta: Default (Required Props)
4
+ - advanced_table_loading: Loading State
4
5
  - advanced_table_beta_subrow_headers: SubRow Headers
5
6
  - advanced_table_collapsible_trail_rails: Collapsible Trail
6
7
  - advanced_table_table_props: Table Props
@@ -133,15 +133,18 @@ export default class PbAdvancedTable extends PbEnhancedElement {
133
133
  if (!elements.length) return;
134
134
 
135
135
  const isVisible = elements[0].classList.contains("is-visible");
136
- if (isVisible) {
137
- this.hideElement(elements);
138
- this.displayDownArrow();
139
- } else {
140
- this.showElement(elements);
141
- this.displayUpArrow();
136
+
137
+ isVisible ? this.hideElement(elements) : this.showElement(elements);
138
+ isVisible ? this.displayDownArrow() : this.displayUpArrow();
139
+
140
+ const row = this.element.closest("tr");
141
+ if (row) {
142
+ row.classList.toggle("bg-silver", !isVisible);
143
+ row.classList.toggle("bg-white", isVisible);
142
144
  }
143
145
  }
144
146
 
147
+
145
148
  displayDownArrow() {
146
149
  this.element.querySelector(DOWN_ARROW_SELECTOR).style.display =
147
150
  "inline-block";
@@ -16,6 +16,8 @@ module Playbook
16
16
  default: []
17
17
  prop :collapsible_trail, type: Playbook::Props::Boolean,
18
18
  default: true
19
+ prop :loading, type: Playbook::Props::Boolean,
20
+ default: false
19
21
  prop :responsive, type: Playbook::Props::Enum,
20
22
  values: %w[none scroll],
21
23
  default: "scroll"
@@ -54,7 +56,7 @@ module Playbook
54
56
  current_data_attributes = current_depth.zero? ? { row_depth: 0 } : table_data_attributes
55
57
 
56
58
  # Additional class and data attributes needed for toggle logic
57
- output << pb_rails("advanced_table/table_row", props: { id: id, row: row, column_definitions: leaf_columns, depth: current_depth, collapsible_trail: collapsible_trail, classname: additional_classes, table_data_attributes: current_data_attributes, responsive: responsive })
59
+ output << pb_rails("advanced_table/table_row", props: { id: id, row: row, column_definitions: leaf_columns, depth: current_depth, collapsible_trail: collapsible_trail, classname: additional_classes, table_data_attributes: current_data_attributes, responsive: responsive, loading: loading })
58
60
 
59
61
  if row[:children].present?
60
62
  row[:children].each do |child_row|
@@ -6,11 +6,15 @@
6
6
  <%= pb_rails("table/table_header", props: { id: header_id, colspan: cell[:colspan], classname: [object.th_classname(is_first_column: cell_index.zero?), ('last-header-cell' if cell[:is_last_in_group] && cell_index != 0)].compact.join(' '), sort_menu: cell[:accessor] ? cell[:sort_menu] : nil }) do %>
7
7
  <%= pb_rails("flex", props: { align: "center", justify: cell_index.zero? ? "start" : row_index === header_rows.size - 1 ? "end" : "center", text_align: "end" }) do %>
8
8
  <% if cell_index.zero? && (object.enable_toggle_expansion == "header" || object.enable_toggle_expansion == "all") && row_index === header_rows.size - 1 %>
9
- <button
10
- class="gray-icon toggle-all-icon"
11
- onclick="expandAllRows(this); event.preventDefault();">
12
- <%= pb_rails("icon", props: { icon: "arrows-from-line", cursor: "pointer", fixed_width: true, padding_right: "xs" }) %>
13
- </button>
9
+ <% if loading %>
10
+ <div class="<%= object.loading ? 'loading-toggle-icon' : '' %>"></div>
11
+ <% else %>
12
+ <button
13
+ class="gray-icon toggle-all-icon"
14
+ onclick="expandAllRows(this); event.preventDefault();">
15
+ <%= pb_rails("icon", props: { icon: "arrows-from-line", cursor: "pointer", fixed_width: true, padding_right: "xs" }) %>
16
+ </button>
17
+ <% end %>
14
18
  <% end %>
15
19
  <%= cell[:label] %>
16
20
  <% end %>
@@ -8,6 +8,8 @@ module Playbook
8
8
  prop :enable_toggle_expansion, type: Playbook::Props::Enum,
9
9
  values: %w[all header none],
10
10
  default: "header"
11
+ prop :loading, type: Playbook::Props::Boolean,
12
+ default: false
11
13
  prop :responsive, type: Playbook::Props::Enum,
12
14
  values: %w[none scroll],
13
15
  default: "scroll"
@@ -2,7 +2,7 @@
2
2
  <% object.column_definitions.each_with_index do |column, index| %>
3
3
  <% next unless column[:accessor].present? %>
4
4
  <%= pb_rails("table/table_cell", props: { classname:object.td_classname(column, index)}) do %>
5
- <%= pb_rails("flex", props:{ align: "center", justify: index.zero? ? "start" : "end" }) do %>
5
+ <%= pb_rails("flex", props:{ align: "center", justify: index.zero? ? "start" : "end", classname: object.loading ? "loading-cell" : "" }) do %>
6
6
  <% if collapsible_trail && index.zero? %>
7
7
  <% (1..depth).each do |i| %>
8
8
  <% additional_offset = i > 1 ? (i - 1) * 0.25 : 0 %>
@@ -14,10 +14,13 @@
14
14
  <div style="padding-left: <%= depth * 1.25 %>em">
15
15
  <%= pb_rails("flex", props:{align: "center", column_gap: "xs"}) do %>
16
16
  <% if index.zero? && object.row[:children].present? %>
17
- <button id="<%= "#{object.id}_#{object.row.object_id}" %>" class="gray-icon expand-toggle-icon" data-advanced-table="true" >
18
- <%= pb_rails("icon", props: { id: "advanced-table_open_icon", icon: "circle-play", cursor: "pointer" }) %>
19
- <%= pb_rails("icon", props: { id: "advanced-table_close_icon", display: "none", icon: "circle-play", cursor: "pointer", rotation: 90 }) %>
20
- </button>
17
+ <button
18
+ id="<%= "#{object.id}_#{object.row.object_id}" %>"
19
+ class="gray-icon expand-toggle-icon"
20
+ data-advanced-table="true">
21
+ <%= pb_rails("icon", props: { id: "advanced-table_open_icon", icon: "circle-play", cursor: "pointer" }) %>
22
+ <%= pb_rails("icon", props: { id: "advanced-table_close_icon", display: "none", icon: "circle-play", cursor: "pointer", rotation: 90 }) %>
23
+ </button>
21
24
  <% end %>
22
25
  <%= pb_rails("flex/flex_item", props:{padding_left: index.zero? && object.row[:children].present? ? "none" : "xs"}) do %>
23
26
  <% if column[:custom_renderer].present? %>
@@ -42,4 +45,4 @@
42
45
  <% end %>
43
46
  <% end %>
44
47
  <% end %>
45
- <% end %>
48
+ <% end %>
@@ -13,6 +13,8 @@ module Playbook
13
13
  default: true
14
14
  prop :table_data_attributes, type: Playbook::Props::HashProp,
15
15
  default: {}
16
+ prop :loading, type: Playbook::Props::Boolean,
17
+ default: false
16
18
  prop :responsive, type: Playbook::Props::Enum,
17
19
  values: %w[none scroll],
18
20
  default: "scroll"
@@ -78,4 +78,9 @@ $avatar-sizes: (
78
78
  }
79
79
  }
80
80
  }
81
+ &.dark {
82
+ [class^=pb_card_kit] {
83
+ position: absolute;
84
+ }
85
+ }
81
86
  }
@@ -65,7 +65,7 @@ module Playbook
65
65
  end
66
66
 
67
67
  def tag
68
- link ? "a" : "button"
68
+ link && !disabled ? "a" : "button"
69
69
  end
70
70
 
71
71
  def valid_emoji(icon)
@@ -0,0 +1,3 @@
1
+ .pb_copy_button_kit {
2
+
3
+ }
@@ -0,0 +1,92 @@
1
+
2
+ import React, { useState } from 'react'
3
+ import classnames from 'classnames'
4
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
5
+ import { globalProps } from '../utilities/globalProps'
6
+
7
+ import Button from '../pb_button/_button'
8
+ import Tooltip from '../pb_tooltip/_tooltip'
9
+
10
+ type CopyButtonProps = {
11
+ aria?: { [key: string]: string },
12
+ className?: string,
13
+ data?: { [key: string]: string },
14
+ id?: string,
15
+ from?: string,
16
+ text?: string,
17
+ tooltipPlacement?: "top" | "right" | "bottom" | "left",
18
+ tooltipText?: string,
19
+ value?: string,
20
+ }
21
+
22
+ const CopyButton = (props: CopyButtonProps) => {
23
+ const {
24
+ aria = {},
25
+ className,
26
+ data = {},
27
+ from = '',
28
+ id,
29
+ text= 'Copy',
30
+ tooltipPlacement= 'bottom',
31
+ tooltipText = 'Copied!',
32
+ value = '',
33
+ } = props
34
+
35
+ const [copied, setCopied] = useState(false)
36
+
37
+ const ariaProps = buildAriaProps(aria)
38
+ const dataProps = buildDataProps(data)
39
+ const classes = classnames(buildCss('pb_copy_button_kit'), globalProps(props), className)
40
+
41
+ const copy = () => {
42
+ if (!from && !value) {
43
+ return
44
+ }
45
+
46
+ if (value) {
47
+ navigator.clipboard.writeText(value)
48
+ } else if (from) {
49
+ const copyElement = document.getElementById(from);
50
+ let copyText = copyElement?.innerText
51
+
52
+ if (copyElement instanceof HTMLTextAreaElement || copyElement instanceof HTMLInputElement) {
53
+ copyText = copyElement.value;
54
+ }
55
+
56
+ if (copyText) {
57
+ navigator.clipboard.writeText(copyText)
58
+ }
59
+ }
60
+
61
+ setCopied(true)
62
+
63
+ setTimeout(() => {
64
+ setCopied(false)
65
+ }, 1000);
66
+ }
67
+
68
+ return (
69
+ <div
70
+ {...ariaProps}
71
+ {...dataProps}
72
+ className={classes}
73
+ id={id}
74
+ >
75
+ <Tooltip
76
+ forceOpenTooltip={copied}
77
+ placement={tooltipPlacement}
78
+ showTooltip={false}
79
+ text={tooltipText}
80
+ >
81
+ <Button
82
+ icon='copy'
83
+ onClick={copy}
84
+ >
85
+ { text }
86
+ </Button>
87
+ </Tooltip>
88
+ </div>
89
+ )
90
+ }
91
+
92
+ export default CopyButton
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import { CopyButton } from 'playbook-ui'
3
+ import { ensureAccessible, renderKit, render, fireEvent, screen } from '../utilities/test-utils'
4
+
5
+ const props = {
6
+ data: { testid: 'default', value: 'copy' }
7
+ }
8
+
9
+ test('returns namespaced class name', () => {
10
+ const kit = renderKit(CopyButton, props)
11
+ expect(kit).toBeInTheDocument()
12
+ expect(kit).toHaveClass('pb_copy_button_kit')
13
+ })
14
+
15
+ it('should be accessible', async () => {
16
+ ensureAccessible(CopyButton, props)
17
+ })
18
+
19
+ // It's difficult to actually use navigator.clipboard.readText, so we mock
20
+ it('copies the value to clipboard and pastes it into an input', async () => {
21
+ Object.defineProperty(global, 'navigator', {
22
+ value: {
23
+ clipboard: {
24
+ writeText: jest.fn().mockResolvedValueOnce(undefined),
25
+ },
26
+ },
27
+ writable: true,
28
+ })
29
+
30
+ render(<CopyButton {...props} />)
31
+
32
+ const copyButton = screen.getByTestId('default')
33
+ fireEvent.click(copyButton)
34
+
35
+ await navigator.clipboard.writeText('copy')
36
+
37
+ expect(navigator.clipboard.writeText).toHaveBeenCalledWith("copy");
38
+ })
39
+
40
+ test('passes text and tooltip props to button', () => {
41
+ render(
42
+ <CopyButton
43
+ data={{ testid: 'text-test' }}
44
+ text={"text"}
45
+ tooltipPlacement="right"
46
+ tooltipText="Text copied!"
47
+ value="copy"
48
+ />
49
+ )
50
+
51
+ const content = screen.getByText("text")
52
+ expect(content).toHaveTextContent("text")
53
+
54
+ const kit = screen.getByTestId('text-test')
55
+ const button = kit.querySelector('.pb_button_kit_primary_inline_enabled')
56
+ expect(button).toBeInTheDocument()
57
+
58
+ fireEvent.click(button)
59
+ const tooltipContent = screen.getByText("Text copied!")
60
+ expect(tooltipContent).toHaveTextContent("Text copied!")
61
+
62
+ const tooltip = kit.querySelector('.pb_tooltip_kit')
63
+ expect(tooltip).toBeInTheDocument()
64
+ })
@@ -0,0 +1,21 @@
1
+ import React from 'react'
2
+ import { CopyButton, Textarea } from 'playbook-ui'
3
+
4
+ const CopyButtonDefault = (props) => (
5
+ <div>
6
+ <CopyButton
7
+ {...props}
8
+ text="Copy Text"
9
+ tooltipPlacement="right"
10
+ tooltipText="Text copied!"
11
+ value="Playbook makes it easy to support bleeding edge, or legacy systems. Use Playbook’s 200+ components and end-to-end design language to create simple, intuitive and beautiful experiences with ease."
12
+ />
13
+
14
+ <Textarea
15
+ {...props}
16
+ placeholder="Copy and paste here"
17
+ />
18
+ </div>
19
+ )
20
+
21
+ export default CopyButtonDefault
@@ -0,0 +1,45 @@
1
+ import React, { useState } from 'react'
2
+ import { CopyButton, Body, TextInput, Textarea } from 'playbook-ui'
3
+
4
+ const CopyButtonFrom = (props) => {
5
+ const [text, setText] = useState("Copy this text input text")
6
+
7
+ const handleChange = (event) => {
8
+ setText(event.target.value);
9
+ }
10
+
11
+ return (<div>
12
+ <Body id="body">Copy this body text!</Body>
13
+ <CopyButton
14
+ {...props}
15
+ from="body"
16
+ marginBottom="sm"
17
+ text="Copy Body text"
18
+ tooltipPlacement="right"
19
+ tooltipText="Body text copied!"
20
+ />
21
+
22
+ <TextInput
23
+ {...props}
24
+ id="textinput"
25
+ onChange={handleChange}
26
+ value={text}
27
+ />
28
+ <CopyButton
29
+ {...props}
30
+ from="textinput"
31
+ marginBottom="sm"
32
+ text="Copy Text Input"
33
+ tooltipPlacement="right"
34
+ tooltipText="Text input copied!"
35
+ />
36
+
37
+ <Textarea
38
+ {...props}
39
+ placeholder="Copy and paste here"
40
+ />
41
+ </div>
42
+ )
43
+ }
44
+
45
+ export default CopyButtonFrom
@@ -0,0 +1 @@
1
+ Provide an element's ID as the `from` parameter, and its text will be copied. If the element is an input, its `value` will be copied; otherwise, the `innerText` will be used. Additionally, if a `value` prop is provided, it will override the content from the `from` element and be copied instead.
@@ -0,0 +1,8 @@
1
+ examples:
2
+
3
+
4
+ react:
5
+ - copy_button_default: Default
6
+ - copy_button_from: Copy From
7
+
8
+
@@ -0,0 +1,2 @@
1
+ export { default as CopyButtonDefault } from './_copy_button_default.jsx'
2
+ export { default as CopyButtonFrom } from './_copy_button_from.jsx'
@@ -14,6 +14,7 @@ type PbDateProps = {
14
14
  alignment?: "left" | "center" | "right";
15
15
  aria?: { [key: string]: string };
16
16
  className?: string;
17
+ dark?: boolean;
17
18
  data?: { [key: string]: string };
18
19
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
19
20
  id?: string;
@@ -29,6 +30,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
29
30
  aria = {},
30
31
  alignment = "left",
31
32
  className,
33
+ dark = false,
32
34
  data = {},
33
35
  htmlOptions = {},
34
36
  id,
@@ -56,7 +58,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
56
58
  );
57
59
 
58
60
  return (
59
- <div
61
+ <div
60
62
  {...ariaProps}
61
63
  {...dataProps}
62
64
  {...htmlProps}
@@ -93,7 +95,9 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
93
95
  </>
94
96
  : size == "md" || size == "lg"
95
97
  ? (
96
- <Title size={4}
98
+ <Title
99
+ dark={dark}
100
+ size={4}
97
101
  tag="h4"
98
102
  >
99
103
  {showIcon && (
@@ -127,6 +131,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
127
131
  <>
128
132
  {showIcon && (
129
133
  <Caption className="pb_icon_kit_container"
134
+ dark={dark}
130
135
  tag="span"
131
136
  >
132
137
  <Icon fixedWidth
@@ -138,15 +143,20 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
138
143
 
139
144
  {showDayOfWeek && (
140
145
  <>
141
- <Caption tag="div">{weekday}</Caption>
146
+ <Caption dark={dark}
147
+ tag="div">
148
+ {weekday}
149
+ </Caption>
142
150
  <Caption color="light"
151
+ dark={dark}
143
152
  tag="div"
144
153
  text=" • "
145
154
  />
146
155
  </>
147
156
  )}
148
157
 
149
- <Caption tag="span">
158
+ <Caption dark={dark}
159
+ tag="span">
150
160
  {month} {day}
151
161
  {currentYear != year && <>{`, ${year}`}</>}
152
162
  </Caption>
@@ -18,7 +18,7 @@ const DateDefault = (props) => {
18
18
  value={"2012-08-03"}
19
19
  {...props}
20
20
  />
21
- <Caption>{"(Hyphenated Date)"}</Caption>
21
+ <Caption {...props}>{"(Hyphenated Date)"}</Caption>
22
22
  </div>
23
23
 
24
24
  <br />
@@ -56,6 +56,7 @@ const DateDefault = (props) => {
56
56
  <Title
57
57
  size={4}
58
58
  text={"(Hyphenated Date)"}
59
+ {...props}
59
60
  />
60
61
  </div>
61
62