playbook_ui 13.31.0.pre.alpha.play1262iconstyles3172 → 13.31.0.pre.alpha.powercentrainplaybookpt23212

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_background/background.html.erb +2 -11
  3. data/app/pb_kits/playbook/pb_body/body.html.erb +1 -6
  4. data/app/pb_kits/playbook/pb_bread_crumbs/bread_crumb_item.html.erb +1 -6
  5. data/app/pb_kits/playbook/pb_bread_crumbs/bread_crumbs.html.erb +1 -6
  6. data/app/pb_kits/playbook/pb_button/_button.scss +3 -3
  7. data/app/pb_kits/playbook/pb_button/_button_mixins.scss +3 -2
  8. data/app/pb_kits/playbook/pb_caption/_caption_mixin.scss +1 -1
  9. data/app/pb_kits/playbook/pb_caption/caption.html.erb +1 -6
  10. data/app/pb_kits/playbook/pb_card/card.html.erb +1 -7
  11. data/app/pb_kits/playbook/pb_collapsible/__snapshots__/collapsible.test.js.snap +1 -1
  12. data/app/pb_kits/playbook/pb_dashboard/commonSettings.js +1 -1
  13. data/app/pb_kits/playbook/pb_dashboard/pbChartsDarkTheme.ts +1 -1
  14. data/app/pb_kits/playbook/pb_dashboard/pbChartsLightTheme.ts +1 -1
  15. data/app/pb_kits/playbook/pb_date_year_stacked/docs/_date_year_stacked_default.jsx +4 -1
  16. data/app/pb_kits/playbook/pb_detail/detail.html.erb +1 -6
  17. data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +1 -6
  18. data/app/pb_kits/playbook/pb_dialog/dialog_body.html.erb +1 -6
  19. data/app/pb_kits/playbook/pb_dialog/dialog_footer.html.erb +2 -5
  20. data/app/pb_kits/playbook/pb_dialog/dialog_header.html.erb +1 -6
  21. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +15 -1
  22. data/app/pb_kits/playbook/pb_draggable/context/types.ts +5 -0
  23. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.jsx +14 -19
  24. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.md +5 -3
  25. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards.md +7 -3
  26. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list.md +3 -5
  27. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list.md +3 -5
  28. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -1
  29. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +2 -0
  30. data/app/pb_kits/playbook/pb_dropdown/index.js +33 -4
  31. data/app/pb_kits/playbook/pb_flex/flex.html.erb +1 -5
  32. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +9 -0
  33. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +1 -1
  34. data/app/pb_kits/playbook/pb_hashtag/hashtag.html.erb +1 -6
  35. data/app/pb_kits/playbook/pb_highlight/highlight.html.erb +1 -5
  36. data/app/pb_kits/playbook/pb_home_address_street/home_address_street.html.erb +1 -5
  37. data/app/pb_kits/playbook/pb_icon/_icon.scss +1 -211
  38. data/app/pb_kits/playbook/pb_icon/_icon.tsx +7 -99
  39. data/app/pb_kits/playbook/pb_icon/icon.rb +16 -22
  40. data/app/pb_kits/playbook/pb_nav/_nav_item.test.js +2 -2
  41. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +8 -23
  42. data/app/pb_kits/playbook/tokens/_titles.scss +4 -4
  43. data/app/pb_kits/playbook/tokens/_typography.scss +10 -10
  44. data/dist/menu.yml +566 -472
  45. data/dist/playbook-rails.js +6 -6
  46. data/dist/reset.css +1 -1
  47. data/lib/playbook/version.rb +1 -1
  48. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40926fc2e7c733b41e34cd183f1e0ba98adf9c136615f73415a64a88bdcd7ef5
4
- data.tar.gz: '038a9914dad8b716dbb6bcd3cc9c73ff2c4b5b3f59ee578130903e68e791a5ea'
3
+ metadata.gz: 4a1c64dce06929e6d1c5308db0a219c98928f941b659f06d2a6780d8ec7884de
4
+ data.tar.gz: 2f5256ff5648697c7f144b54dc62277e23c1189d1c0ae87d04c60f86a1fe7240
5
5
  SHA512:
6
- metadata.gz: cad3db04fdc0cd38b2896803be0002f866cf654a0c21e61f21fcf26dda0de2a0819324245f606e2a5b28a1da0f70d8a66a89a6961a5d3c3403557e45dd322130
7
- data.tar.gz: 1099544d9ecf11f27874c3939ab83aaf50e9b7f09cae1459eecf06bfea553782f1b98ec0936ef92211ea9ed3822d325aff0259b418d118f6411fb0bfa17e89bd
6
+ metadata.gz: f06bcdc6d07585a0eb44a4784f32cf9d1bccfc4e8811dee814e6affa7c587983d32615663745b14ab37f3e542ecb0aa0e159aa36fc5b75c4032ffcdfbcddd3fc
7
+ data.tar.gz: cea9826880aad795f72f212dd9719800dee0de2c09fb090c6f2c3bfd7f1624c0f1b615ede15c0cf444c25df80e429cfeb416fb665752924cb9095655a5040ac3
@@ -1,23 +1,14 @@
1
1
  <% if object.image_url.present? %>
2
- <%= content_tag(object.tag,
3
- aria: object.aria,
4
- data: object.data,
5
- id: object.id,
6
- class: object.classname,
2
+ <%= pb_content_tag(object.tag,
7
3
  style: "background-image: url('#{object.image_url}');
8
4
  background-repeat: #{object.background_repeat};
9
5
  background-size: #{object.background_size};
10
6
  background-position: #{object.background_position};",
11
- **combined_html_options
12
7
  ) do %>
13
8
  <%= content.presence %>
14
9
  <% end %>
15
10
  <% else %>
16
- <%= content_tag(object.tag,
17
- aria: object.aria,
18
- data: object.data,
19
- id: object.id,
20
- class: object.classname,
11
+ <%= pb_content_tag(object.tag,
21
12
  style: object.custom_background_color
22
13
  ) do %>
23
14
  <%= content.presence %>
@@ -1,8 +1,3 @@
1
- <%= content_tag(object.tag,
2
- aria: object.aria,
3
- id: object.id,
4
- data: object.data,
5
- class: object.classname,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag(object.tag) do %>
7
2
  <%= object.content %>
8
3
  <% end %>
@@ -1,9 +1,4 @@
1
- <%= content_tag(:div,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- aria: object.aria,
6
- **combined_html_options) do%>
1
+ <%= pb_content_tag do%>
7
2
  <%= content_tag(object.link ? 'a' : 'span', class: 'bread_crumb_item', href: object.link) do %>
8
3
  <%= content.presence %>
9
4
  <% end %>
@@ -1,8 +1,3 @@
1
- <%= content_tag(:nav,
2
- aria: object.aria,
3
- id: object.id,
4
- data: object.data,
5
- class: object.classname,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag(:nav) do %>
7
2
  <%= content.presence %>
8
3
  <% end %>
@@ -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) {
@@ -1,8 +1,3 @@
1
- <%= content_tag(object.tag,
2
- aria: object.aria,
3
- id: object.id,
4
- data: object.data,
5
- class: object.classname,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag(object.tag) do %>
7
2
  <%= content.presence || object.text %>
8
3
  <% end %>
@@ -1,10 +1,4 @@
1
- <%= content_tag(object.tag,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- aria: object.aria,
6
- dark: object.dark,
7
- **combined_html_options) do %>
1
+ <%= pb_content_tag(object.tag) do %>
8
2
  <%= content.presence %>
9
3
  <% end %>
10
4
 
@@ -28,7 +28,7 @@ exports[`html structure is correct 1`] = `
28
28
  style="vertical-align: middle; color: rgb(193, 205, 214);"
29
29
  >
30
30
  <i
31
- class="pb_icon_kit far far fa-lg fa-fw fa-fw fa-lg fa-chevron-down"
31
+ class="pb_icon_kit far fa-fw fa-lg fa-chevron-down"
32
32
  />
33
33
  <span
34
34
  aria-label="chevron-down icon"
@@ -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()}
@@ -1,8 +1,3 @@
1
- <%= content_tag(object.tag,
2
- aria: object.aria,
3
- class: object.classname,
4
- data: object.data,
5
- id: object.id,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag(object.tag) do %>
7
2
  <%= object.content %>
8
3
  <% end %>
@@ -1,10 +1,5 @@
1
1
  <div class="pb_dialog_wrapper_rails <%= object.full_height_style %>" data-overlay-click= <%= object.overlay_close %> >
2
- <%= content_tag(:dialog,
3
- aria: object.aria,
4
- data: object.data,
5
- id: object.id,
6
- class: object.classname,
7
- **combined_html_options) do %>
2
+ <%= pb_content_tag(:dialog) do %>
8
3
  <% if object.status === "" && object.title %>
9
4
  <%= pb_rails("dialog/dialog_header", props: { title: object.title, id: object.id }) %>
10
5
  <% end %>
@@ -1,8 +1,3 @@
1
- <%= content_tag(:div,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- aria: object.aria,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag do %>
7
2
  <%= content.presence || object.text %>
8
3
  <% end %>
@@ -1,8 +1,5 @@
1
- <%= content_tag(:div,
2
- id: object.id,
3
- data: object.data,
4
- aria: object.aria,
5
- **combined_html_options) do %>
1
+ <%= pb_content_tag(:div, class: "") do %>
2
+ <% 'excluded classname?' %>
6
3
  <% if object.confirm_button && object.cancel_button %>
7
4
  <div class="dialog-pseudo-footer"></div>
8
5
  <%= pb_rails("flex", props: { classname:object.classname, spacing:"between", padding_x:"sm", padding:"sm", padding_bottom:"sm" }) do %>
@@ -1,9 +1,4 @@
1
- <%= content_tag(:div,
2
- id: object.id,
3
- data: object.data,
4
- class: object.sticky_header,
5
- aria: object.aria,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag(:div, class: object.sticky_header) do %>
7
2
  <%= pb_rails("flex", props: {classname:object.classname, spacing:"between", padding:"sm", align:"center"}) do %>
8
3
  <%= content.presence || object.title %>
9
4
 
@@ -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
  }
@@ -1,7 +1,3 @@
1
- <%= content_tag(:div,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- **combined_html_options) do %>
1
+ <%= pb_content_tag do %>
6
2
  <%= content.presence %>
7
3
  <% end %>
@@ -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,9 +1,4 @@
1
- <%= content_tag(:span,
2
- aria: object.aria,
3
- class: object.classname,
4
- data: object.data,
5
- id: object.id,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag(:span) do %>
7
2
  <%= link_to object.url, target: object.link_option do %>
8
3
  <%= pb_rails("badge", props: { dark: object.dark, variant: "primary", text: object.hashtag_text }) %>
9
4
  <% end %>
@@ -1,8 +1,4 @@
1
- <%= content_tag(:span,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- **combined_html_options) do %>
1
+ <%= pb_content_tag(:span) do %>
6
2
  <mark>
7
3
  <%= content.presence || object.text %>
8
4
  </mark>
@@ -1,8 +1,4 @@
1
- <%= content_tag(:div,
2
- id: object.id,
3
- data: object.data,
4
- class: object.classname,
5
- **combined_html_options) do %>
1
+ <%= pb_content_tag do %>
6
2
  <%= pb_rails("home_address_street/#{emphasis}_emphasis", props: object.send("#{emphasis}_emphasis_props")) %>
7
3
  <% end %>
8
4