playbook_ui 13.31.0 → 13.32.0.pre.alpha.PLAY1138iconkitaddcolorprop3268

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_button/_button.scss +3 -3
  3. data/app/pb_kits/playbook/pb_button/_button_mixins.scss +3 -2
  4. data/app/pb_kits/playbook/pb_caption/_caption_mixin.scss +1 -1
  5. data/app/pb_kits/playbook/pb_dashboard/commonSettings.js +1 -1
  6. data/app/pb_kits/playbook/pb_dashboard/pbChartsDarkTheme.ts +1 -1
  7. data/app/pb_kits/playbook/pb_dashboard/pbChartsLightTheme.ts +1 -1
  8. data/app/pb_kits/playbook/pb_date_year_stacked/docs/_date_year_stacked_default.jsx +4 -1
  9. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +15 -1
  10. data/app/pb_kits/playbook/pb_draggable/context/types.ts +5 -0
  11. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.jsx +14 -19
  12. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.md +5 -3
  13. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards.md +7 -3
  14. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list.md +3 -5
  15. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list.md +3 -5
  16. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -1
  17. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +2 -0
  18. data/app/pb_kits/playbook/pb_dropdown/index.js +33 -4
  19. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +9 -0
  20. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +1 -1
  21. data/app/pb_kits/playbook/pb_icon/_icon.scss +26 -0
  22. data/app/pb_kits/playbook/pb_icon/_icon.tsx +3 -0
  23. data/app/pb_kits/playbook/pb_icon/docs/_icon_color.html.erb +7 -0
  24. data/app/pb_kits/playbook/pb_icon/docs/_icon_color.jsx +46 -0
  25. data/app/pb_kits/playbook/pb_icon/docs/_icon_color.md +1 -0
  26. data/app/pb_kits/playbook/pb_icon/docs/example.yml +2 -0
  27. data/app/pb_kits/playbook/pb_icon/docs/index.js +1 -0
  28. data/app/pb_kits/playbook/pb_icon/icon.rb +9 -1
  29. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +8 -23
  30. data/app/pb_kits/playbook/tokens/_titles.scss +4 -4
  31. data/app/pb_kits/playbook/tokens/_typography.scss +10 -10
  32. data/dist/menu.yml +566 -472
  33. data/dist/playbook-rails.js +6 -6
  34. data/dist/reset.css +1 -1
  35. data/lib/playbook/version.rb +2 -2
  36. metadata +8 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c02852f26be30f0f9abff5ba3089c03c4d9f6878880b2e3f59827e7b556f8c3d
4
- data.tar.gz: a5c30e259ea3d6a77135c2f6172d607ddb105732e20caf60f68d1d1f014bf468
3
+ metadata.gz: 2b8727cde66e2db0ab8c6e03d0e4f1f120946349c33ccde13db3a57654e723f6
4
+ data.tar.gz: 62cd6fd054f6114e65ebf42836c112b6defd2fb641cc5286f7a0515e9275b7e5
5
5
  SHA512:
6
- metadata.gz: d14c183e1ef95272881479defd28dec0aa49a6ee8539af55aa630cdd493aa48918830906465d6a46c0caf405a1c2a8b2b7dd5fc894f0031feb62bbd21341ae22
7
- data.tar.gz: 26cd7b2d68304e1c80c4bf3e1bc9ce5cc07cf5c378c82e52bac4541abd61ca0a5a817ded5c6abde4282cb7c785b484778902afa96c3e83e0e7f3fcd84e68872b
6
+ metadata.gz: 64db2dd4d63371d32e7f7430ca1f683946a830bc2782ee19779a4082a57943b0f5f275c15e81be777c42dfcb76ea640a846be4d3118252149cb458861362ec52
7
+ data.tar.gz: dd527085844a67f55d0420db0f2458f815f9cbc12e4d40c0387249d2bda0c16a9a8b35800c88202e5e06fcc7b0f6043c4bb181ff91f2aa3da12ca0e18e9b2289
@@ -6,9 +6,9 @@
6
6
  @import "../tokens/typography";
7
7
 
8
8
  $pb_button_sizes: (
9
- "sm": 0.75rem,
10
- "md": 0.875rem,
11
- "lg": 1.125rem,
9
+ "sm": $font_smaller,
10
+ "md": $font_small,
11
+ "lg": ($font_large - 2px),
12
12
  );
13
13
 
14
14
  [class*=pb_button_kit]{
@@ -9,7 +9,7 @@
9
9
 
10
10
  $pb_button_size: 40px;
11
11
  $pb_button_v_padding: 7px;
12
- $pb_button_h_padding: 34px;
12
+ $pb_button_h_padding: 28px;
13
13
  $pb_button_hover_darken: 4%;
14
14
  $pb_button_border_width: 0px;
15
15
 
@@ -27,13 +27,14 @@ $pb_button_border_width: 0px;
27
27
  text-rendering: optimizeLegibility;
28
28
  font-size: $font_small;
29
29
  font-weight: $bold;
30
+ letter-spacing: $lspace_loose;
30
31
  text-align: center;
31
32
  text-decoration: none;
32
33
  vertical-align: middle;
33
34
  text-transform: none;
34
35
  border-width: $pb_button_border_width;
35
36
  border-style: solid;
36
- border-radius: $border_rad_light;
37
+ border-radius: $border_rad_heavy;
37
38
  min-height: $pb_button_size;
38
39
  line-height: 1.5;
39
40
  padding: $pb_button_v_padding $pb_button_h_padding;
@@ -24,7 +24,7 @@ $pb_dark_caption_colors: (
24
24
  color: $text_lt_light;
25
25
  text-transform: uppercase;
26
26
  font-size: $font_size;
27
- letter-spacing: $lspace_looser;
27
+ letter-spacing: $lspace_loosest;
28
28
  }
29
29
 
30
30
  @mixin caption_color($color: $text_lt_light) {
@@ -53,7 +53,7 @@ const adjustAxisStyle = (axis) => {
53
53
  /* Change axis label styles */
54
54
  axis.labels.style.fontFamily = typography.font_family_base
55
55
  axis.labels.style.color = colors.charcoal
56
- axis.labels.style.fontWeight = typography.light
56
+ axis.labels.style.fontWeight = typography.regular
57
57
  axis.labels.style.fontSize = typography.font_small
58
58
  }
59
59
 
@@ -33,7 +33,7 @@ const highchartsDarkTheme: ThemeProps = {
33
33
  style: {
34
34
  color: colors.text_dk_default,
35
35
  fontFamily: typography.font_family_base,
36
- fontWeight: typography.regular,
36
+ fontWeight: typography.bold,
37
37
  fontSize: typography.heading_3,
38
38
  },
39
39
  },
@@ -34,7 +34,7 @@ const highchartsTheme: ThemeProps = {
34
34
  style: {
35
35
  color: colors.text_lt_default,
36
36
  fontFamily: typography.font_family_base,
37
- fontWeight: typography.regular,
37
+ fontWeight: typography.bold,
38
38
  fontSize: typography.heading_3,
39
39
  },
40
40
  },
@@ -4,7 +4,10 @@ import { DateYearStacked } from '../../'
4
4
  const DateYearStackedDefault = (props) => {
5
5
  return (
6
6
  <div>
7
- <DateYearStacked date={new Date()} />
7
+ <DateYearStacked
8
+ date={new Date()}
9
+ {...props}
10
+ />
8
11
  <DateYearStacked
9
12
  align="center"
10
13
  date={new Date()}
@@ -51,7 +51,16 @@ export const DraggableContext = () => {
51
51
  return useContext(DragContext);
52
52
  };
53
53
 
54
- export const DraggableProvider = ({ children, initialItems, onReorder }: DraggableProviderType) => {
54
+ export const DraggableProvider = ({
55
+ children,
56
+ initialItems,
57
+ onReorder,
58
+ onDragStart,
59
+ onDragEnter,
60
+ onDragEnd,
61
+ onDrop,
62
+ onDragOver
63
+ }: DraggableProviderType) => {
55
64
  const [state, dispatch] = useReducer(reducer, initialState);
56
65
 
57
66
  useEffect(() => {
@@ -65,6 +74,7 @@ export const DraggableProvider = ({ children, initialItems, onReorder }: Draggab
65
74
  const handleDragStart = (id: string, container: string) => {
66
75
  dispatch({ type: 'SET_DRAG_DATA', payload: { id: id, initialGroup: container } });
67
76
  dispatch({ type: 'SET_IS_DRAGGING', payload: id });
77
+ if (onDragStart) onDragStart(id, container);
68
78
  };
69
79
 
70
80
  const handleDragEnter = (id: string, container: string) => {
@@ -72,11 +82,13 @@ export const DraggableProvider = ({ children, initialItems, onReorder }: Draggab
72
82
  dispatch({ type: 'REORDER_ITEMS', payload: { dragId: state.dragData.id, targetId: id } });
73
83
  dispatch({ type: 'SET_DRAG_DATA', payload: { id: state.dragData.id, initialGroup: container } });
74
84
  }
85
+ if (onDragEnter) onDragEnter(id, container);
75
86
  };
76
87
 
77
88
  const handleDragEnd = () => {
78
89
  dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
79
90
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
91
+ if (onDragEnd) onDragEnd();
80
92
  };
81
93
 
82
94
  const changeCategory = (itemId: string, container: string) => {
@@ -87,11 +99,13 @@ export const DraggableProvider = ({ children, initialItems, onReorder }: Draggab
87
99
  dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
88
100
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
89
101
  changeCategory(state.dragData.id, container);
102
+ if (onDrop) onDrop(container);
90
103
  };
91
104
 
92
105
  const handleDragOver = (e: Event, container: string) => {
93
106
  e.preventDefault();
94
107
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: container });
108
+ if (onDragOver) onDragOver(e, container);
95
109
  };
96
110
 
97
111
  const contextValue = useMemo(() => ({
@@ -23,4 +23,9 @@ export interface ItemType {
23
23
  children: React.ReactNode;
24
24
  initialItems: ItemType[];
25
25
  onReorder: (items: ItemType[]) => void;
26
+ onDragStart?: (id: string, container: string) => void;
27
+ onDragEnter?: (id: string, container: string) => void;
28
+ onDragEnd?: () => void;
29
+ onDrop?: (container: string) => void;
30
+ onDragOver?: (e: Event, container: string) => void;
26
31
  }
@@ -1,23 +1,19 @@
1
1
  import React, { useState } from "react";
2
- import { SelectableList, Draggable, DraggableProvider } from "../../";
2
+ import { Flex, Image, Draggable, DraggableProvider } from "../../";
3
3
 
4
4
  // Initial items to be dragged
5
5
  const data = [
6
6
  {
7
- id: "1",
8
- text: "Task 1",
7
+ id: "21",
8
+ url: "https://unsplash.it/500/400/?image=633",
9
9
  },
10
10
  {
11
- id: "2",
12
- text: "Task 2",
11
+ id: "22",
12
+ url: "https://unsplash.it/500/400/?image=634",
13
13
  },
14
14
  {
15
- id: "3",
16
- text: "Task 3",
17
- },
18
- {
19
- id: "4",
20
- text: "Task 4",
15
+ id: "23",
16
+ url: "https://unsplash.it/500/400/?image=637",
21
17
  },
22
18
  ];
23
19
 
@@ -30,20 +26,19 @@ const DraggableDefault = (props) => {
30
26
  onReorder={(items) => setInitialState(items)}
31
27
  >
32
28
  <Draggable.Container {...props}>
33
- <SelectableList variant="checkbox">
34
- {initialState.map(({ id, text }) => (
29
+ <Flex>
30
+ {initialState.map(({ id, url }) => (
35
31
  <Draggable.Item dragId={id}
36
32
  key={id}
37
33
  >
38
- <SelectableList.Item
39
- label={text}
40
- name={id}
41
- value={id}
42
- {...props}
34
+ <Image alt={id}
35
+ margin="xs"
36
+ size="md"
37
+ url={url}
43
38
  />
44
39
  </Draggable.Item>
45
40
  ))}
46
- </SelectableList>
41
+ </Flex>
47
42
  </Draggable.Container>
48
43
  </DraggableProvider>
49
44
  </>
@@ -1,4 +1,6 @@
1
- To use the Draggable kit, you must use the DraggableProvider and pass in `initialItems`. The `onReorder` is a function that returns the data as it changes as items are reordered. Use this to manage state as shown.
1
+ The Draggable kit gives you a full subcomponent structure that allows it to be used with almost any kits.
2
2
 
3
- The `Draggable.Container` specifies the container within which items can be dropped.
4
- The `Draggable.Item` specifies the items that can be dragged and dropped. `dragId` is a REQUIRED prop for Draggable.Item.
3
+ `DraggableProvider` = This provider manages all settings that allows drag and drop to function and must be used as the outermost wrapper. It has 2 REQUIRED props: `initialItems` (initial data) and `onReorder` (function that returns mutated data as items are reordered via drag and drop). Devs must manage state as shown.
4
+
5
+ `Draggable.Container` = This specifies the container within which items can be dropped.
6
+ `Draggable.Item` = This specifies the items that can be dragged and dropped. `dragId` is a REQUIRED prop for Draggable.Item.
@@ -1,5 +1,9 @@
1
- For a simplified version of the Draggable API for the Card kit, You can use the the Card kit as the Draggable Item by using the `draggableItem` prop. The dragHandle is added by default but this can be opted out of by setting `dragHandle` to false on the Card kit.
1
+ For a simplified version of the Draggable API for the Card kit, you can do the following:
2
+
3
+ Use `DraggableProvider` and manage state as shown.
4
+
5
+ `Draggable.Container` creates the container within which the cards can be dragged and dropped.
6
+
7
+ The Card kit is optimized to work with the draggable kit. To enable drag, use the `draggableItem` and `dragId` props on the Card kit as shown. An additional optional boolean prop (set to true by default) of `dragHandle` is also available to show the drag handle icon.
2
8
 
3
- In addition to the above `dragId` is a REQUIRED prop to be passedd to the Card kit when implementing dragging.
4
9
 
5
- The dev must manage state as shown.
@@ -1,7 +1,5 @@
1
- For a simplified version of the Draggable API for the List kit, use the DraggableProvider to wrap the List kit and use the `enableDrag` prop.
1
+ For a simplified version of the Draggable API for the List kit, you can do the following:
2
2
 
3
- In addition to the above `dragId` is a REQUIRED prop to be passed to the List kit when implementing dragging.
3
+ Use `DraggableProvider` and manage state as shown.
4
4
 
5
- The dev must manage state as shown.
6
-
7
- The dragHandle is added by default but this can be opted out of by setting `dragHandle` to false on the List kit.
5
+ The List kit is optimized to work with the draggable kit. To enable drag, use the `enableDrag` prop on List kit AND `dragId` prop on ListItem. An additional optional boolean prop (set to true by default) of `dragHandle` is also available on List kit to show the drag handle icon.
@@ -1,7 +1,5 @@
1
- For a simplified version of the Draggable API for the SelectableList kit, use the DraggableProvider to wrap the SelectableList kit and use the `enableDrag` prop.
1
+ For a simplified version of the Draggable API for the SelectableList kit, you can do the following:
2
2
 
3
- In addition to the above `dragId` is a REQUIRED prop to be passed to the SelectableList kit when implementing dragging.
3
+ Use `DraggableProvider` and manage state as shown.
4
4
 
5
- The dev must manage state as shown.
6
-
7
- The dragHandle is added by default but this can be opted out of by setting `dragHandle` to false on the SelectableList kit.
5
+ The SelectableList kit is optimized to work with the draggable kit. To enable drag, use the `enableDrag` prop on SelectableList kit AND `dragId` prop on SelectableList.Item. An additional optional boolean prop (set to true by default) of `dragHandle` is also available on SelectableList kit to show the drag handle icon.
@@ -8,7 +8,9 @@
8
8
  <%= pb_rails("caption", props: {text: object.label, margin_bottom:"xs"}) %>
9
9
  <% end %>
10
10
  <div class="dropdown_wrapper<%= error_class %>" style="position: relative">
11
- <input type="hidden" name="<%= object.name %>" id="dropdown-selected-option" value=""/>
11
+ <input type="hidden" name="<%= object.name %>" id="dropdown-selected-option" value="" />
12
+ <input id="dropdown-form-validation" name="<%= object.name %>_form_validation" value="" style="display: none" <%= object.required ? "required" : ""%> />
13
+
12
14
  <% if content.present? %>
13
15
  <%= content.presence %>
14
16
  <%= pb_rails("body", props: { status: "negative", text: object.error }) %>
@@ -8,6 +8,8 @@ module Playbook
8
8
  prop :label, type: Playbook::Props::String
9
9
  prop :name, type: Playbook::Props::String
10
10
  prop :error, type: Playbook::Props::String
11
+ prop :required, type: Playbook::Props::Boolean,
12
+ default: false
11
13
 
12
14
  def data
13
15
  Hash(prop(:data)).merge(pb_dropdown: true)
@@ -8,16 +8,22 @@ const DOWN_ARROW_SELECTOR = "#dropdown_open_icon";
8
8
  const UP_ARROW_SELECTOR = "#dropdown_close_icon";
9
9
  const OPTION_SELECTOR = "[data-dropdown-option-label]";
10
10
  const CUSTOM_DISPLAY_SELECTOR = "[data-dropdown-custom-trigger]";
11
+ const INPUT_FORM_VALIDATION = "#dropdown-form-validation";
11
12
 
12
13
  export default class PbDropdown extends PbEnhancedElement {
13
14
  static get selector() {
14
15
  return DROPDOWN_SELECTOR;
15
16
  }
16
17
 
18
+ get target() {
19
+ return this.element.parentNode.querySelector(CONTAINER_SELECTOR);
20
+ }
21
+
17
22
  connect() {
18
23
  this.keyboardHandler = new PbDropdownKeyboard(this);
19
24
  this.bindEventListeners();
20
25
  this.updateArrowDisplay(false);
26
+ this.handleFormValidation();
21
27
  }
22
28
 
23
29
  bindEventListeners() {
@@ -38,9 +44,13 @@ export default class PbDropdown extends PbEnhancedElement {
38
44
  handleOptionClick(event) {
39
45
  const option = event.target.closest(OPTION_SELECTOR);
40
46
  const hiddenInput = this.element.querySelector("#dropdown-selected-option");
47
+ const inputFormValidation = this.element.querySelector(INPUT_FORM_VALIDATION);
48
+
41
49
  if (option) {
42
50
  const value = option.dataset.dropdownOptionLabel;
43
51
  hiddenInput.value = JSON.parse(value).id;
52
+ inputFormValidation.value = JSON.parse(value).id;
53
+ this.clearFormValidation(inputFormValidation);
44
54
  this.onOptionSelected(value, option);
45
55
  }
46
56
  }
@@ -103,10 +113,6 @@ export default class PbDropdown extends PbEnhancedElement {
103
113
  selectedOption.classList.add("pb_dropdown_option_selected");
104
114
  }
105
115
 
106
- get target() {
107
- return this.element.parentNode.querySelector(CONTAINER_SELECTOR);
108
- }
109
-
110
116
  showElement(elem) {
111
117
  elem.classList.remove("close");
112
118
  elem.classList.add("open");
@@ -150,4 +156,27 @@ export default class PbDropdown extends PbEnhancedElement {
150
156
  upArrow.style.display = isOpen ? "inline-block" : "none";
151
157
  }
152
158
  }
159
+
160
+ handleFormValidation() {
161
+ const inputFormValidation = this.element.querySelector(INPUT_FORM_VALIDATION);
162
+
163
+ inputFormValidation.addEventListener("invalid", function (event) {
164
+ if (inputFormValidation.hasAttribute("required") && inputFormValidation.value === "") {
165
+ event.preventDefault();
166
+ inputFormValidation.closest(".dropdown_wrapper").classList.add("error");
167
+ }
168
+ }, true);
169
+ }
170
+
171
+ clearFormValidation(input) {
172
+ if (input.checkValidity()) {
173
+ const dropdownWrapperElement = input.closest(".dropdown_wrapper");
174
+ dropdownWrapperElement.classList.remove("error");
175
+
176
+ const errorLabelElement = dropdownWrapperElement.querySelector(".pb_body_kit_negative");
177
+ if (errorLabelElement) {
178
+ errorLabelElement.remove();
179
+ }
180
+ }
181
+ }
153
182
  }
@@ -13,6 +13,14 @@
13
13
  ]
14
14
  %>
15
15
 
16
+ <%
17
+ example_dropdown_options = [
18
+ { label: 'United States', value: 'United States', id: 'us' },
19
+ { label: 'Canada', value: 'Canada', id: 'ca' },
20
+ { label: 'Pakistan', value: 'Pakistan', id: 'pk' },
21
+ ]
22
+ %>
23
+
16
24
  <%= pb_form_with(scope: :example, method: :get, url: "", validate: true) do |form| %>
17
25
  <%= form.text_field :example_text_field, props: { label: true, required: true } %>
18
26
  <%= form.phone_number_field :example_phone_number_field, props: { label: "Example phone field" } %>
@@ -22,6 +30,7 @@
22
30
  <%= form.password_field :example_password_field, props: { label: true, required: true } %>
23
31
  <%= form.url_field :example_url_field, props: { label: true, required: true } %>
24
32
  <%= form.text_area :example_text_area, props: { label: true, required: true } %>
33
+ <%= form.dropdown_field :example_dropdown, props: { label: true, options: example_dropdown_options, required: true } %>
25
34
  <%= form.select :example_select, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true } %>
26
35
  <%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
27
36
  <%= form.check_box :example_checkbox, props: { text: "Example Checkbox", label: true, required: true } %>
@@ -55,7 +55,7 @@ $form_pill_colors: (
55
55
  height: fit-content;
56
56
  height: -moz-fit-content;
57
57
  .pb_form_pill_text, .pb_form_pill_close, .pb_form_pill_tag {
58
- font-size: 16px;
58
+ font-size: $font_base;
59
59
  font-weight: $regular;
60
60
  }
61
61
  .pb_form_pill_text, .pb_form_pill_tag {
@@ -1,3 +1,29 @@
1
+ @import "../tokens/colors";
2
+
3
+ // All the merges below create $icon_colors, a map of all color tokens in colors.scss
4
+ $merge_kits1: map-merge($status_colors, $category_colors);
5
+ $merge_kits2: map-merge($merge_kits1, $product_colors);
6
+ $merge_kits3: map-merge($merge_kits2, $text_colors);
7
+ $merge_kits4: map-merge($merge_kits3, $card_colors);
8
+ $merge_kits5: map-merge($merge_kits4, $action_colors);
9
+ $merge_kits6: map-merge($merge_kits5, $data_colors);
10
+ $merge_kits7: map-merge($merge_kits6, $border_colors);
11
+ $merge_kits8: map-merge($merge_kits7, $interface_colors);
12
+ $merge_kits9: map-merge($merge_kits8, $main_colors);
13
+ $merge_kits10: map-merge($merge_kits9, $shadow_colors);
14
+ $merge_kits11: map-merge($merge_kits10, $text_colors);
15
+ $merge_kits12: map-merge($merge_kits11, $status_color_text);
16
+ $merge_kits13: map-merge($merge_kits12, $status_color_text_dark);
17
+ $icon_colors: map-merge($merge_kits13, $colors);
18
+
19
+ .pb_custom_icon, .pb_icon_kit {
20
+ @each $color_name, $color_value in $icon_colors {
21
+ &[class*="#{$color_name}"] {
22
+ color: $color_value;
23
+ }
24
+ }
25
+ }
26
+
1
27
  // Rails custom icon styles
2
28
  svg.pb_custom_icon {
3
29
  width: 1em;
@@ -24,6 +24,7 @@ type IconProps = {
24
24
  aria?: {[key: string]: string},
25
25
  border?: string,
26
26
  className?: string,
27
+ color?: string,
27
28
  customIcon?: {[key: string] :SVGElement},
28
29
  data?: {[key: string]: string},
29
30
  fixedWidth?: boolean,
@@ -87,6 +88,7 @@ const Icon = (props: IconProps) => {
87
88
  aria = {},
88
89
  border = false,
89
90
  className,
91
+ color,
90
92
  customIcon,
91
93
  data = {},
92
94
  fixedWidth = true,
@@ -136,6 +138,7 @@ const Icon = (props: IconProps) => {
136
138
  (iconElement || customIcon) ? 'pb_custom_icon' : fontStyle,
137
139
  iconElement ? 'svg-inline--fa' : '',
138
140
  faClasses,
141
+ color ? `color_${color}` : '',
139
142
  globalProps(props),
140
143
  className
141
144
  )
@@ -0,0 +1,7 @@
1
+ <%= pb_rails("flex", props: {orientation: "column"}) do %>
2
+ <%= pb_rails("icon", props: { icon: "user", fixed_width: true, color: "primary", size: "2x" }) %>
3
+ <%= pb_rails("icon", props: { icon: "recycle", fixed_width: true, color: "info", size: "2x" }) %>
4
+ <%= pb_rails("icon", props: { icon: "frog", fixed_width: true, color: "data_4", size: "2x" }) %>
5
+ <%= pb_rails("icon", props: { icon: "vial", fixed_width: true, color: "text_lt_lighter", size: "2x" }) %>
6
+ <%= pb_rails("icon", props: { icon: "roofing", fixed_width: true, color: "product_roofing", size: "2x" }) %>
7
+ <% end %>
@@ -0,0 +1,46 @@
1
+ import React from "react"
2
+ import Icon from "../_icon"
3
+
4
+ const IconDefault = (props) => {
5
+ return (
6
+ <div style={{ display: "flex", flexDirection: "column"}}>
7
+ <Icon
8
+ color="primary"
9
+ fixedWidth
10
+ icon="user"
11
+ size="2x"
12
+ {...props}
13
+ />
14
+ <Icon
15
+ color="info"
16
+ fixedWidth
17
+ icon="recycle"
18
+ size="2x"
19
+ {...props}
20
+ />
21
+ <Icon
22
+ color="data_4"
23
+ fixedWidth
24
+ icon="frog"
25
+ size="2x"
26
+ {...props}
27
+ />
28
+ <Icon
29
+ color="text_lt_lighter"
30
+ fixedWidth
31
+ icon="vial"
32
+ size="2x"
33
+ {...props}
34
+ />
35
+ <Icon
36
+ color="roofing"
37
+ fixedWidth
38
+ icon="product-roofing"
39
+ size="2x"
40
+ {...props}
41
+ />
42
+ </div>
43
+ )
44
+ }
45
+
46
+ export default IconDefault
@@ -0,0 +1 @@
1
+ Pass any Playbook <a href="https://playbook.powerapp.cloud/visual_guidelines/colors" target="_blank">color token</a> to the `color` prop to change any icon's color.
@@ -9,6 +9,7 @@ examples:
9
9
  - icon_sizes: Icon Sizes
10
10
  - icon_custom: Icon Custom
11
11
  - icon_fa_kit: Icon with FontAwesome Kit
12
+ - icon_color: Icon Color
12
13
 
13
14
  react:
14
15
  - icon_default: Icon Default
@@ -20,6 +21,7 @@ examples:
20
21
  - icon_sizes: Icon Sizes
21
22
  - icon_custom: Icon Custom
22
23
  - icon_fa_kit: Icon with FontAwesome Kit
24
+ - icon_color: Icon Color
23
25
 
24
26
  swift:
25
27
  - icon_default_swift: Icon Default
@@ -7,3 +7,4 @@ export { default as IconBorder } from './_icon_border.jsx'
7
7
  export { default as IconSizes } from './_icon_sizes.jsx'
8
8
  export { default as IconCustom } from './_icon_custom.jsx'
9
9
  export { default as IconFaKit} from './_icon_fa_kit.jsx'
10
+ export { default as IconColor } from './_icon_color.jsx'
@@ -38,6 +38,7 @@ module Playbook
38
38
  default: "far"
39
39
  prop :spin, type: Playbook::Props::Boolean,
40
40
  default: false
41
+ prop :color, type: Playbook::Props::String
41
42
 
42
43
  ALIASES = JSON.parse(File.read(Playbook::Engine.root.join("app/pb_kits/playbook/pb_icon/icon_aliases.json")))["aliases"].freeze
43
44
 
@@ -49,6 +50,7 @@ module Playbook
49
50
  def classname
50
51
  generate_classname(
51
52
  "pb_icon_kit",
53
+ color_class,
52
54
  font_style_class,
53
55
  icon_class,
54
56
  border_class,
@@ -69,6 +71,7 @@ module Playbook
69
71
  generate_classname(
70
72
  "pb_icon_kit",
71
73
  border_class,
74
+ color_class,
72
75
  fixed_width_class,
73
76
  flip_class,
74
77
  inverse_class,
@@ -100,7 +103,8 @@ module Playbook
100
103
  svg["aria"] = object.aria
101
104
  svg["height"] = "auto"
102
105
  svg["width"] = "auto"
103
- doc.at_css("path")["fill"] = "currentColor"
106
+ fill_color = object.color || "currentColor"
107
+ doc.at_css("path")["fill"] = fill_color
104
108
  raw doc
105
109
  end
106
110
 
@@ -184,6 +188,10 @@ module Playbook
184
188
  def spin_class
185
189
  spin ? "fa-spin" : nil
186
190
  end
191
+
192
+ def color_class
193
+ color ? "color_#{color}" : nil
194
+ end
187
195
  end
188
196
  end
189
197
  end
@@ -86,33 +86,18 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
86
86
  const toolbarElement = element.parentElement.querySelector('trix-toolbar') as HTMLElement,
87
87
  blockCodeButton = toolbarElement.querySelector('[data-trix-attribute=code]') as HTMLElement
88
88
 
89
+ // replace default trix "block code" button with "inline code" button
89
90
  let inlineCodeButton = toolbarElement.querySelector('[data-trix-attribute=inlineCode]') as HTMLElement
90
- if (!inlineCodeButton) inlineCodeButton = blockCodeButton.cloneNode(true) as HTMLElement
91
-
92
- // set button attributes
93
- inlineCodeButton.dataset.trixAttribute = 'inlineCode'
94
- blockCodeButton.insertAdjacentElement('afterend', inlineCodeButton)
91
+ if (!inlineCodeButton) {
92
+ inlineCodeButton = blockCodeButton.cloneNode(true) as HTMLElement
93
+ blockCodeButton.hidden = true
94
+ // set button attributes
95
+ inlineCodeButton.dataset.trixAttribute = 'inlineCode'
96
+ blockCodeButton.insertAdjacentElement('afterend', inlineCodeButton)
97
+ }
95
98
 
96
99
  if (toolbarBottom) editor.element.after(toolbarElement)
97
100
 
98
- const getCodeFormattingType = (): string => {
99
- if (editor.attributeIsActive('code')) return 'block'
100
- if (editor.attributeIsActive('inlineCode')) return 'inline'
101
-
102
- const range = editor.getSelectedRange()
103
- if (range[0] == range[1]) return 'block'
104
-
105
- const text = editor.getSelectedDocument().toString().trim()
106
- return /\n/.test(text) ? 'block' : 'inline'
107
- }
108
-
109
- // DOM event listeners
110
- element.addEventListener('trix-selection-change', () => {
111
- const type = getCodeFormattingType()
112
- blockCodeButton.hidden = type == 'inline'
113
- inlineCodeButton.hidden = type == 'block'
114
- })
115
-
116
101
  focus
117
102
  ? (document.addEventListener('trix-focus', useFocus),
118
103
  document.addEventListener('trix-blur', useFocus),