playbook_ui 13.31.0 → 13.32.0.pre.alpha.PLAY1138iconkitaddcolorprop3268
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_button/_button.scss +3 -3
- data/app/pb_kits/playbook/pb_button/_button_mixins.scss +3 -2
- data/app/pb_kits/playbook/pb_caption/_caption_mixin.scss +1 -1
- data/app/pb_kits/playbook/pb_dashboard/commonSettings.js +1 -1
- data/app/pb_kits/playbook/pb_dashboard/pbChartsDarkTheme.ts +1 -1
- data/app/pb_kits/playbook/pb_dashboard/pbChartsLightTheme.ts +1 -1
- data/app/pb_kits/playbook/pb_date_year_stacked/docs/_date_year_stacked_default.jsx +4 -1
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +15 -1
- data/app/pb_kits/playbook/pb_draggable/context/types.ts +5 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.jsx +14 -19
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.md +5 -3
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards.md +7 -3
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list.md +3 -5
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list.md +3 -5
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +2 -0
- data/app/pb_kits/playbook/pb_dropdown/index.js +33 -4
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +9 -0
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +1 -1
- data/app/pb_kits/playbook/pb_icon/_icon.scss +26 -0
- data/app/pb_kits/playbook/pb_icon/_icon.tsx +3 -0
- data/app/pb_kits/playbook/pb_icon/docs/_icon_color.html.erb +7 -0
- data/app/pb_kits/playbook/pb_icon/docs/_icon_color.jsx +46 -0
- data/app/pb_kits/playbook/pb_icon/docs/_icon_color.md +1 -0
- data/app/pb_kits/playbook/pb_icon/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_icon/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_icon/icon.rb +9 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +8 -23
- data/app/pb_kits/playbook/tokens/_titles.scss +4 -4
- data/app/pb_kits/playbook/tokens/_typography.scss +10 -10
- data/dist/menu.yml +566 -472
- data/dist/playbook-rails.js +6 -6
- data/dist/reset.css +1 -1
- data/lib/playbook/version.rb +2 -2
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b8727cde66e2db0ab8c6e03d0e4f1f120946349c33ccde13db3a57654e723f6
|
4
|
+
data.tar.gz: 62cd6fd054f6114e65ebf42836c112b6defd2fb641cc5286f7a0515e9275b7e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64db2dd4d63371d32e7f7430ca1f683946a830bc2782ee19779a4082a57943b0f5f275c15e81be777c42dfcb76ea640a846be4d3118252149cb458861362ec52
|
7
|
+
data.tar.gz: dd527085844a67f55d0420db0f2458f815f9cbc12e4d40c0387249d2bda0c16a9a8b35800c88202e5e06fcc7b0f6043c4bb181ff91f2aa3da12ca0e18e9b2289
|
@@ -9,7 +9,7 @@
|
|
9
9
|
|
10
10
|
$pb_button_size: 40px;
|
11
11
|
$pb_button_v_padding: 7px;
|
12
|
-
$pb_button_h_padding:
|
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: $
|
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;
|
@@ -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.
|
56
|
+
axis.labels.style.fontWeight = typography.regular
|
57
57
|
axis.labels.style.fontSize = typography.font_small
|
58
58
|
}
|
59
59
|
|
@@ -4,7 +4,10 @@ import { DateYearStacked } from '../../'
|
|
4
4
|
const DateYearStackedDefault = (props) => {
|
5
5
|
return (
|
6
6
|
<div>
|
7
|
-
<DateYearStacked
|
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 = ({
|
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 {
|
2
|
+
import { Flex, Image, Draggable, DraggableProvider } from "../../";
|
3
3
|
|
4
4
|
// Initial items to be dragged
|
5
5
|
const data = [
|
6
6
|
{
|
7
|
-
id: "
|
8
|
-
|
7
|
+
id: "21",
|
8
|
+
url: "https://unsplash.it/500/400/?image=633",
|
9
9
|
},
|
10
10
|
{
|
11
|
-
id: "
|
12
|
-
|
11
|
+
id: "22",
|
12
|
+
url: "https://unsplash.it/500/400/?image=634",
|
13
13
|
},
|
14
14
|
{
|
15
|
-
id: "
|
16
|
-
|
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
|
-
|
34
|
-
{initialState.map(({ id,
|
29
|
+
<Flex>
|
30
|
+
{initialState.map(({ id, url }) => (
|
35
31
|
<Draggable.Item dragId={id}
|
36
32
|
key={id}
|
37
33
|
>
|
38
|
-
<
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
{...props}
|
34
|
+
<Image alt={id}
|
35
|
+
margin="xs"
|
36
|
+
size="md"
|
37
|
+
url={url}
|
43
38
|
/>
|
44
39
|
</Draggable.Item>
|
45
40
|
))}
|
46
|
-
|
41
|
+
</Flex>
|
47
42
|
</Draggable.Container>
|
48
43
|
</DraggableProvider>
|
49
44
|
</>
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
The Draggable kit gives you a full subcomponent structure that allows it to be used with almost any kits.
|
2
2
|
|
3
|
-
|
4
|
-
|
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,
|
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,
|
1
|
+
For a simplified version of the Draggable API for the List kit, you can do the following:
|
2
2
|
|
3
|
-
|
3
|
+
Use `DraggableProvider` and manage state as shown.
|
4
4
|
|
5
|
-
The
|
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,
|
1
|
+
For a simplified version of the Draggable API for the SelectableList kit, you can do the following:
|
2
2
|
|
3
|
-
|
3
|
+
Use `DraggableProvider` and manage state as shown.
|
4
4
|
|
5
|
-
The
|
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 } %>
|
@@ -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
|
-
|
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)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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),
|