playbook_ui 12.2.0 → 12.3.0.pre.alpha.patchtest1

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +3 -0
  3. data/app/pb_kits/playbook/data/menu.yml +1 -0
  4. data/app/pb_kits/playbook/index.js +3 -2
  5. data/app/pb_kits/playbook/pb_button/_button.scss +0 -5
  6. data/app/pb_kits/playbook/pb_button/_button.tsx +4 -0
  7. data/app/pb_kits/playbook/pb_button/_button_mixins.scss +39 -4
  8. data/app/pb_kits/playbook/pb_button/button.rb +2 -0
  9. data/app/pb_kits/playbook/pb_button/docs/_button_accessibility.jsx +1 -0
  10. data/app/pb_kits/playbook/pb_button/docs/_button_block_content.jsx +1 -0
  11. data/app/pb_kits/playbook/pb_button/docs/_button_default.jsx +4 -0
  12. data/app/pb_kits/playbook/pb_button/docs/_button_form.jsx +1 -0
  13. data/app/pb_kits/playbook/pb_button/docs/_button_full_width.jsx +1 -0
  14. data/app/pb_kits/playbook/pb_button/docs/_button_icon_options.html.erb +2 -2
  15. data/app/pb_kits/playbook/pb_button/docs/_button_icon_options.jsx +4 -0
  16. data/app/pb_kits/playbook/pb_button/docs/_button_link.html.erb +3 -3
  17. data/app/pb_kits/playbook/pb_button/docs/_button_link.jsx +6 -0
  18. data/app/pb_kits/playbook/pb_button/docs/_button_loading.html.erb +3 -3
  19. data/app/pb_kits/playbook/pb_button/docs/_button_loading.jsx +6 -0
  20. data/app/pb_kits/playbook/pb_button/docs/_button_options.jsx +1 -0
  21. data/app/pb_kits/playbook/pb_button/docs/_button_size.html.erb +3 -3
  22. data/app/pb_kits/playbook/pb_button/docs/_button_size.jsx +6 -0
  23. data/app/pb_kits/playbook/pb_checkbox/_checkbox.scss +26 -19
  24. data/app/pb_kits/playbook/pb_circle_icon_button/_circle_icon_button.scss +24 -0
  25. data/app/pb_kits/playbook/pb_form_group/_form_group.scss +10 -2
  26. data/app/pb_kits/playbook/pb_map/_map.scss +8 -0
  27. data/app/pb_kits/playbook/pb_map/_map.tsx +40 -0
  28. data/app/pb_kits/playbook/pb_map/docs/_map_default.jsx +52 -0
  29. data/app/pb_kits/playbook/pb_map/docs/_map_default.md +13 -0
  30. data/app/pb_kits/playbook/pb_map/docs/_map_with_plugin.jsx +64 -0
  31. data/app/pb_kits/playbook/pb_map/docs/_map_with_plugin.md +8 -0
  32. data/app/pb_kits/playbook/pb_map/docs/example.yml +7 -0
  33. data/app/pb_kits/playbook/pb_map/docs/index.js +2 -0
  34. data/app/pb_kits/playbook/pb_map/map.test.jsx +17 -0
  35. data/app/pb_kits/playbook/pb_progress_simple/{_progress_simple.jsx → _progress_simple.tsx} +7 -5
  36. data/app/pb_kits/playbook/pb_progress_simple/progress_simple.test.js +120 -0
  37. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.scss +4 -9
  38. data/app/pb_kits/playbook/pb_typeahead/_typeahead.jsx +11 -2
  39. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +0 -2
  40. data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +95 -0
  41. data/app/pb_kits/playbook/pb_typeahead/components/ClearIndicator.jsx +1 -1
  42. data/app/pb_kits/playbook/pb_typeahead/components/Control.jsx +1 -0
  43. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.html.erb +19 -0
  44. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.jsx +39 -0
  45. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.md +1 -0
  46. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
  47. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  48. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +3 -0
  49. data/app/pb_kits/playbook/playbook-doc.js +2 -0
  50. data/app/pb_kits/playbook/tokens/_colors.scss +3 -1
  51. data/app/pb_kits/playbook/utilities/_focus.scss +12 -0
  52. data/lib/playbook/version.rb +2 -2
  53. metadata +20 -5
@@ -0,0 +1,52 @@
1
+ import React, { useRef, useEffect } from 'react'
2
+ import { Map } from '../../'
3
+
4
+ import maplibregl from 'maplibre-gl'
5
+
6
+ const MapDefault = () => {
7
+
8
+ const mapContainerRef = useRef(null)
9
+
10
+ useEffect(() => {
11
+ if (!maplibregl.supported()) {
12
+ alert('Your browser does not support MapLibre GL');
13
+ } else {
14
+ const map = new maplibregl.Map({
15
+ container: mapContainerRef.current,
16
+ style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
17
+ center: [-75.379143, 39.831200],
18
+ zoom: 13,
19
+ })
20
+ //set marker/pin
21
+ /* eslint-disable-next-line */
22
+ const marker = new maplibregl.Marker({
23
+ color: "#0056CF",
24
+ }).setLngLat([-75.379143, 39.831200])
25
+ .setPopup(new maplibregl.Popup({className: 'map_popup', closeButton: false}).setHTML(`<h4 class="pb_title_kit_size_4">Hello World!</h4>`)) // add popup
26
+ .addTo(map);
27
+
28
+ //add zoom controls
29
+ map.addControl(new maplibregl.NavigationControl({showCompass: false}))
30
+
31
+ // disable map zoom when using scroll
32
+ map.scrollZoom.disable();
33
+
34
+ }
35
+ }, [])
36
+ return (
37
+ <Map>
38
+ <div
39
+ ref={mapContainerRef}
40
+ style={{
41
+ position: 'absolute',
42
+ left: 0,
43
+ right: 0,
44
+ top: 0,
45
+ bottom: 0,
46
+ }}
47
+ />
48
+ </Map>
49
+ )
50
+ }
51
+
52
+ export default MapDefault
@@ -0,0 +1,13 @@
1
+ This kit provides a wrapping class to place around the MapLibre library. Complete docs for using the library can be found [here](https://maplibre.org/maplibre-gl-js-docs/api/).
2
+
3
+ Basic setup to start using MapLibre:
4
+ - Install the npm package using `yarn add maplibre-gl`
5
+ - Include a link to the CSS file as a CDN in your stylesheet using the following syntax:
6
+ `@import url("https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css");`
7
+ or include it as a link in the <head> tag `<link href='https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css' rel='stylesheet' />`
8
+ - To use Maplibre, you must also set a height on the containing div.
9
+ - You can now use MapLibre within the Map Kit as shown in this example.
10
+
11
+ __Notes__ :
12
+ - The MapLibre Marker allows us to pass it a HEX value as a color prop. In these doc examples we are using our primary color for the Marker.
13
+ - `scrollZoom` has been disabled in these doc examples for page usability
@@ -0,0 +1,64 @@
1
+ import React, { useRef, useEffect } from 'react'
2
+ import { Map } from '../../'
3
+ import maplibregl from 'maplibre-gl'
4
+ import MapboxDraw from "@mapbox/mapbox-gl-draw";
5
+
6
+ const MapWithPlugin = () => {
7
+
8
+ const mapContainerRef = useRef(null)
9
+
10
+ useEffect(() => {
11
+ if (!maplibregl.supported()) {
12
+ alert('Your browser does not support MapLibre GL');
13
+ } else {
14
+ const map = new maplibregl.Map({
15
+ container: mapContainerRef.current,
16
+ style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
17
+ center: [-75.379143, 39.831200],
18
+ zoom: 13,
19
+ })
20
+ //set marker/pin
21
+ /* eslint-disable-next-line */
22
+ const marker = new maplibregl.Marker({
23
+ color: "#0056CF",
24
+ }).setLngLat([-75.379143, 39.831200])
25
+ .setPopup(new maplibregl.Popup({className: 'map_popup', closeButton: false}).setHTML(`<h4 class="pb_title_kit_size_4">Hello World!</h4>`)) // add popup
26
+ .addTo(map);
27
+
28
+ //add zoom controls
29
+ map.addControl(new maplibregl.NavigationControl({showCompass: false}))
30
+
31
+ // disable map zoom when using scroll
32
+ map.scrollZoom.disable();
33
+
34
+ //Add polygon draw button using map-box-gl-draw plugin
35
+ var draw = new MapboxDraw({
36
+ displayControlsDefault: false,
37
+ controls: {
38
+ polygon: true,
39
+ trash: true
40
+ }
41
+ });
42
+ map.addControl(draw);
43
+ }
44
+ }, [])
45
+
46
+
47
+
48
+ return (
49
+ <Map>
50
+ <div
51
+ ref={mapContainerRef}
52
+ style={{
53
+ position: 'absolute',
54
+ left: 0,
55
+ right: 0,
56
+ top: 0,
57
+ bottom: 0,
58
+ }}
59
+ />
60
+ </Map>
61
+ )
62
+ }
63
+
64
+ export default MapWithPlugin
@@ -0,0 +1,8 @@
1
+ Various plugins are available for use with MapLibre, one of which is the [mapbox-gl-draw](https://github.com/mapbox/mapbox-gl-draw). This plugin is recommended by MapLibre if you need to add the functionality of drawing polygons on the map.
2
+
3
+ To test this tool:
4
+ - Click the "draw box" icon to activate the polygon tool
5
+ - Click on a spot on the map to start drawing
6
+ - Continue clicking to create new points, defining the boundaries of the polygon
7
+ - Press enter or re-click the first point to finish the polygon
8
+ - Once drawn, polygons can be selected on click and then moved, by dragging-and-dropping the entire shape; resized, by dragging-and-dropping any boundary point(s); or deleted, by clicking the "trash" button.
@@ -0,0 +1,7 @@
1
+ examples:
2
+
3
+
4
+ react:
5
+ - map_default: Default
6
+ - map_with_plugin: Map With Polygon Draw Plugin
7
+
@@ -0,0 +1,2 @@
1
+ export { default as MapDefault } from './_map_default.jsx'
2
+ export { default as MapWithPlugin } from './_map_with_plugin.jsx'
@@ -0,0 +1,17 @@
1
+ import { renderKit } from '../utilities/test-utils'
2
+
3
+ import { Map } from '../'
4
+
5
+ /* See these resources for more testing info:
6
+ - https://github.com/testing-library/jest-dom#usage for useage and examples
7
+ - https://jestjs.io/docs/en/using-matchers
8
+ */
9
+
10
+ test('generated scaffold test - update me', () => {
11
+ const props = {
12
+ data: { testid: 'default' }
13
+ }
14
+
15
+ const kit = renderKit(Map , props)
16
+ expect(kit).toBeInTheDocument()
17
+ })
@@ -1,16 +1,15 @@
1
- /* @flow */
2
1
  import React from 'react'
3
2
  import classnames from 'classnames'
4
- import { buildCss } from '../utilities/props'
3
+ import { buildCss, buildDataProps } from '../utilities/props'
5
4
  import { globalProps } from '../utilities/globalProps'
6
5
 
7
6
  type ProgressSimpleProps = {
8
7
  align?: "left" | "center" | "right",
9
- className?: string | array<string>,
8
+ className?: string | string[],
10
9
  dark?: boolean,
11
10
  data?: string,
12
11
  id?: string,
13
- max?: string,
12
+ max?: number,
14
13
  muted: boolean,
15
14
  percent: string,
16
15
  value: number,
@@ -23,6 +22,7 @@ const ProgressSimple = (props: ProgressSimpleProps) => {
23
22
  align,
24
23
  className,
25
24
  dark = false,
25
+ data ={},
26
26
  max,
27
27
  muted = false,
28
28
  percent = '',
@@ -34,6 +34,7 @@ const ProgressSimple = (props: ProgressSimpleProps) => {
34
34
  width: width,
35
35
  }
36
36
 
37
+ const dataProps = buildDataProps(data)
37
38
  const variantStyle = variant == 'default' ? '' : variant
38
39
 
39
40
  const valueStyles = {
@@ -52,7 +53,8 @@ const ProgressSimple = (props: ProgressSimpleProps) => {
52
53
  )
53
54
 
54
55
  return (
55
- <div className={wrapperClass}>
56
+ <div {...dataProps}
57
+ className={wrapperClass}>
56
58
  <div
57
59
  className={kitClass}
58
60
  data-value={value}
@@ -0,0 +1,120 @@
1
+ import React from 'react'
2
+ import { render, screen, cleanup } from '../utilities/test-utils'
3
+
4
+ import ProgressSimple from './_progress_simple'
5
+
6
+ const testId = "progress-simple-test"
7
+
8
+ test('renders default class name and percentage', () => {
9
+ render(
10
+ <div>
11
+ <ProgressSimple
12
+ data={{ testid: testId }}
13
+ percent={45}
14
+ />
15
+ </div>
16
+
17
+ )
18
+
19
+ const kit = screen.getByTestId(testId)
20
+ const progress = kit.querySelector(".progress_simple_value")
21
+
22
+ expect(kit).toHaveClass('pb_progress_simple_wrapper')
23
+ expect(progress).toHaveStyle("width: 45%")
24
+
25
+ })
26
+
27
+ test('renders values', () => {
28
+ render(
29
+ <div>
30
+ <ProgressSimple
31
+ data={{ testid: testId }}
32
+ max='10'
33
+ value='2'
34
+ />
35
+ </div>
36
+
37
+ )
38
+
39
+ const kit = screen.getByTestId(testId)
40
+ const progress = kit.querySelector(".progress_simple_value")
41
+ expect(progress).toHaveStyle("width: 20%")
42
+ })
43
+
44
+ test('renders progress bar width', () => {
45
+ render(
46
+ <div>
47
+ <ProgressSimple
48
+ data={{ testid: testId }}
49
+ percentage={40}
50
+ width="100px"
51
+ />
52
+ </div>
53
+
54
+ )
55
+
56
+ const kit = screen.getByTestId(testId)
57
+ const progress = kit.querySelector(".pb_progress_simple_kit")
58
+ expect(progress).toHaveStyle("width: 100px")
59
+ })
60
+
61
+ test('renders color variants', () => {
62
+ [
63
+ "positive",
64
+ "negative",
65
+ "warning"
66
+ ].forEach((colorVariant) => {
67
+
68
+ render(
69
+ <div>
70
+ <ProgressSimple
71
+ data={{ testid: testId }}
72
+ percentage={40}
73
+ variant={colorVariant}
74
+ />
75
+ </div>
76
+ )
77
+
78
+ const kit = screen.getByTestId(testId)
79
+ const progress = kit.querySelector(`.pb_progress_simple_kit_${colorVariant}`)
80
+ expect(progress).toBeInTheDocument()
81
+
82
+ cleanup()
83
+ })
84
+ })
85
+
86
+ test('renders muted prop', () => {
87
+ render(
88
+ <div>
89
+ <ProgressSimple
90
+ data={{ testid: testId }}
91
+ muted
92
+ percentage={40}
93
+ />
94
+ </div>
95
+ )
96
+
97
+ const kit = screen.getByTestId(testId)
98
+ const progress = kit.querySelector('.pb_progress_simple_kit_muted')
99
+ expect(progress).toBeInTheDocument()
100
+ })
101
+
102
+ test('renders align prop', () => {
103
+ [
104
+ "left",
105
+ "center",
106
+ "right"
107
+ ].forEach((alignProp) => {
108
+ render(
109
+ <ProgressSimple
110
+ align={alignProp}
111
+ data={{ testid: testId }}
112
+ percentage={45}
113
+ />
114
+ )
115
+ const kit = screen.getByTestId(testId)
116
+ expect(kit).toHaveClass(`pb_progress_simple_wrapper_${alignProp}`)
117
+
118
+ cleanup()
119
+ })
120
+ })
@@ -19,12 +19,11 @@ $pb_selectable_card_border: 2px;
19
19
  display: inherit;
20
20
  flex-direction: inherit;
21
21
  padding: 1px;
22
- transition-property: all;
23
- transition-duration: $transition_short;
24
- transition-timing-function: $easeIn;
25
22
  }
26
23
 
27
24
  @include pb_card;
25
+ transition-property: none;
26
+ transition-duration: 0s;
28
27
  background-color: $white;
29
28
  padding: $space_sm;
30
29
  margin-bottom: $space_sm;
@@ -55,9 +54,6 @@ $pb_selectable_card_border: 2px;
55
54
  top: -($pb_selectable_card_indicator_size/2);
56
55
  right: -($pb_selectable_card_indicator_size/2);
57
56
  opacity: 0;
58
- transition-property: opacity;
59
- transition-duration: $transition_short;
60
- transition-timing-function: $easeIn;
61
57
  }
62
58
  }
63
59
 
@@ -77,6 +73,8 @@ $pb_selectable_card_border: 2px;
77
73
 
78
74
  position: relative;
79
75
  @include pb_card_selected;
76
+ transition-property: none;
77
+ transition-duration: 0s;
80
78
 
81
79
  .pb_selectable_card_circle {
82
80
  opacity: $opacity_10;
@@ -127,9 +125,6 @@ $pb_selectable_card_border: 2px;
127
125
 
128
126
  .separator {
129
127
  align-self: stretch;
130
- transition-property: all;
131
- transition-duration: $transition_short;
132
- transition-timing-function: $easeIn;
133
128
  width: 1px;
134
129
  margin-right: 1px;
135
130
  margin-top: -1px;
@@ -18,7 +18,7 @@ import Option from './components/Option'
18
18
  import Placeholder from './components/Placeholder'
19
19
  import ValueContainer from './components/ValueContainer'
20
20
 
21
- import { noop } from '../utilities/props'
21
+ import { noop, buildDataProps } from '../utilities/props'
22
22
 
23
23
  /**
24
24
  * @typedef {object} Props
@@ -32,6 +32,8 @@ type TypeaheadProps = {
32
32
  components?: object,
33
33
  createable?: boolean,
34
34
  dark?: boolean,
35
+ data?: object,
36
+ error?: string,
35
37
  id?: string,
36
38
  label?: string,
37
39
  loadOptions?: string,
@@ -49,6 +51,8 @@ const Typeahead = ({
49
51
  async,
50
52
  components = {},
51
53
  createable,
54
+ error = "",
55
+ data = {},
52
56
  getOptionLabel,
53
57
  getOptionValue,
54
58
  id,
@@ -106,13 +110,18 @@ const Typeahead = ({
106
110
  }
107
111
  }
108
112
 
113
+ const dataProps = buildDataProps(data)
114
+
109
115
  const classes = `pb_typeahead_kit react-select ${globalProps(props)}`
110
116
  const inlineClass = selectProps.inline ? 'inline' : null
111
117
 
112
118
  return (
113
- <div className={classnames(classes, inlineClass)}>
119
+ <div {...dataProps}
120
+ className={classnames(classes, inlineClass)}
121
+ >
114
122
  <Tag
115
123
  classNamePrefix="typeahead-kit-select"
124
+ error={error}
116
125
  onChange={handleOnChange}
117
126
  {...selectProps}
118
127
  />
@@ -181,8 +181,6 @@
181
181
  }
182
182
  }
183
183
  }
184
-
185
-
186
184
 
187
185
  .typeahead-kit-select__menu {
188
186
  .typeahead-kit-select__option {
@@ -0,0 +1,95 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+ import Typeahead from './_typeahead'
4
+
5
+ const options = [
6
+ { label: 'Orange', value: '#FFA500' },
7
+ { label: 'Red', value: '#FF0000' },
8
+ { label: 'Green', value: '#00FF00' },
9
+ { label: 'Blue', value: '#0000FF' },
10
+ ]
11
+
12
+ test('typeahead classname + label renders as expected', () => {
13
+ render(
14
+ <Typeahead
15
+ data={{ testid: 'typeahead-test' }}
16
+ defaultValue={[options[0]]}
17
+ label="Colors"
18
+ options={options}
19
+ />
20
+ )
21
+
22
+ const kit = screen.getByTestId('typeahead-test')
23
+ const label = kit.querySelector(".pb_caption_kit_md.pb_text_input_kit_label")
24
+ expect(kit).toHaveClass("pb_typeahead_kit")
25
+ expect(label).toHaveTextContent("Colors")
26
+ })
27
+
28
+ test('to be error variant', () => {
29
+ render(
30
+ <Typeahead
31
+ data={{ testid: 'error-test' }}
32
+ error='Please make a valid selection'
33
+ options={options}
34
+ />
35
+ )
36
+
37
+ const kit = screen.getByTestId("error-test")
38
+ const error = kit.querySelector(".pb_body_kit_negative")
39
+ expect(error).toBeInTheDocument()
40
+ })
41
+
42
+ test('should be inline variant', () => {
43
+ render(
44
+ <Typeahead
45
+ data={{ testid: 'inline-test' }}
46
+ inline
47
+ options={options}
48
+ />
49
+ )
50
+
51
+ const kit = screen.getByTestId('inline-test')
52
+ expect(kit).toHaveClass("inline")
53
+ })
54
+
55
+ test('typeahead with pills', () => {
56
+ render(
57
+ <Typeahead
58
+ data={{ testid: 'pills-test' }}
59
+ defaultValue={[options[0]]}
60
+ isMulti
61
+ options={options}
62
+ />
63
+ )
64
+
65
+ const kit = screen.getByTestId('pills-test')
66
+ const pill = kit.querySelector(".pb_form_pill_kit_primary")
67
+ expect(pill).toBeInTheDocument()
68
+ })
69
+
70
+ test('typeahead multi select with badges and small pills', () => {
71
+ render(
72
+ <>
73
+ <Typeahead
74
+ data={{ testid: 'badge-test' }}
75
+ defaultValue={[options[0]]}
76
+ isMulti
77
+ multiKit="badge"
78
+ options={options}
79
+ />
80
+
81
+ <Typeahead
82
+ data={{ testid: 'small-pill-test' }}
83
+ defaultValue={[options[0]]}
84
+ isMulti
85
+ multiKit="smallPill"
86
+ options={options}
87
+ />
88
+ </>
89
+ )
90
+
91
+ const kit = screen.getByTestId('small-pill-test')
92
+ const badge = kit.querySelector(".pb_form_pill_kit_primary.mr_xs.small")
93
+ expect(badge).toBeInTheDocument()
94
+ })
95
+
@@ -7,7 +7,7 @@ const ClearContainer = (props: any) => {
7
7
  const { selectProps, clearValue } = props
8
8
  useEffect(() => {
9
9
  document.addEventListener(`pb-typeahead-kit-${selectProps.id}:clear`, clearValue)
10
- }, true)
10
+ }, [true])
11
11
 
12
12
  return (
13
13
  <components.ClearIndicator
@@ -14,6 +14,7 @@ const TypeaheadControl = (props: Props) => (
14
14
  <div className="pb_typeahead_wrapper">
15
15
  <TextInput
16
16
  dark={props.selectProps.dark}
17
+ error={props.selectProps.error}
17
18
  label={props.selectProps.label}
18
19
  >
19
20
  <Flex>
@@ -0,0 +1,19 @@
1
+ <%
2
+ options = [
3
+ { label: 'Windows', value: '#FFA500' },
4
+ { label: 'Siding', value: '#FF0000' },
5
+ { label: 'Doors', value: '#00FF00' },
6
+ { label: 'Roofs', value: '#0000FF' },
7
+ ]
8
+
9
+ %>
10
+
11
+ <%= pb_rails("typeahead", props: { id: "typeahead-error-example", options: options, error: "Please make a valid selection", label: "Products", name: :foo, is_multi: false }) %>
12
+
13
+ <!-- This section is an example of the available JavaScript event hooks -->
14
+ <%= javascript_tag defer: "defer" do %>
15
+ document.addEventListener("pb-typeahead-kit-typeahead-error-example-result-option-select", function(event) {
16
+ console.log('Option selected')
17
+ console.dir(event.detail)
18
+ })
19
+ <% end %>
@@ -0,0 +1,39 @@
1
+ // @flow
2
+
3
+ import React, { useState, useEffect } from 'react'
4
+
5
+ import Typeahead from '../_typeahead'
6
+
7
+ const options = [
8
+ { label: 'Orange', value: '#FFA500' },
9
+ { label: 'Red', value: '#FF0000' },
10
+ { label: 'Green', value: '#00FF00' },
11
+ { label: 'Blue', value: '#0000FF' },
12
+ ]
13
+
14
+ const TypeaheadErrorState = (props) => {
15
+ const [errorState, setErrorState] = useState("Please make a valid selection");
16
+ const [searchValue, setSearchValue] = useState(null);
17
+
18
+ const handleOnChange = (value) => setSearchValue(value)
19
+
20
+ useEffect(() => {
21
+ if(searchValue) {
22
+ setErrorState("")
23
+ } else {
24
+ setErrorState("Please make a valid selection")
25
+ }
26
+ }, [searchValue])
27
+
28
+ return (
29
+ <Typeahead
30
+ error={errorState}
31
+ label="Colors"
32
+ onChange={handleOnChange}
33
+ options={options}
34
+ {...props}
35
+ />
36
+ )
37
+ }
38
+
39
+ export default TypeaheadErrorState
@@ -0,0 +1 @@
1
+ Typeahead w/ Error shows that an option must be selected or the selected option is invalid (i.e., when used in a form it signals a user to fix an error).
@@ -8,6 +8,7 @@ examples:
8
8
  - typeahead_with_pills_async_users: With Pills (Async Data w/ Users)
9
9
  - typeahead_inline: Inline
10
10
  - typeahead_multi_kit: Multi Kit Options
11
+ - typeahead_error_state: Error State
11
12
 
12
13
  react:
13
14
  - typeahead_default: Default
@@ -20,3 +21,4 @@ examples:
20
21
  - typeahead_multi_kit: Multi Kit Options
21
22
  - typeahead_createable: Createable
22
23
  - typeahead_async_createable: Createable (+ Async Data)
24
+ - typeahead_error_state: Error State
@@ -8,3 +8,4 @@ export { default as TypeaheadInline } from './_typeahead_inline.jsx'
8
8
  export { default as TypeaheadMultiKit } from './_typeahead_multi_kit.jsx'
9
9
  export { default as TypeaheadCreateable } from './_typeahead_createable.jsx'
10
10
  export { default as TypeaheadAsyncCreateable } from './_typeahead_async_createable.jsx'
11
+ export { default as TypeaheadErrorState } from './_typeahead_error_state.jsx'
@@ -5,6 +5,8 @@ module Playbook
5
5
  class Typeahead < Playbook::KitBase
6
6
  prop :async, type: Playbook::Props::Boolean, default: false
7
7
  prop :default_options, type: Playbook::Props::HashArray, default: []
8
+ prop :error, type: Playbook::Props::String,
9
+ default: ""
8
10
  prop :get_option_label
9
11
  prop :get_option_value
10
12
  prop :id
@@ -57,6 +59,7 @@ module Playbook
57
59
  base_options = {
58
60
  dark: dark,
59
61
  defaultValue: default_options,
62
+ error: error,
60
63
  id: id,
61
64
  inline: inline,
62
65
  isMulti: is_multi,
@@ -55,6 +55,7 @@ import * as Lightbox from 'pb_lightbox/docs'
55
55
  import * as LineGraphDocs from 'pb_line_graph/docs'
56
56
  import * as List from 'pb_list/docs'
57
57
  import * as LoadingInline from 'pb_loading_inline/docs'
58
+ import * as Map from 'pb_map/docs'
58
59
  import * as Message from 'pb_message/docs'
59
60
  import * as MultipleUsers from 'pb_multiple_users/docs'
60
61
  import * as MultipleUsersStacked from 'pb_multiple_users_stacked/docs'
@@ -152,6 +153,7 @@ WebpackerReact.setup({
152
153
  ...LineGraphDocs,
153
154
  ...List,
154
155
  ...LoadingInline,
156
+ ...Map,
155
157
  ...Message,
156
158
  ...MultipleUsers,
157
159
  ...MultipleUsersStacked,
@@ -96,11 +96,13 @@ $hover_colors: (
96
96
  );
97
97
 
98
98
  /* Focus colors -----------------------*/
99
+ $focus_color: $primary;
99
100
  $focus_input_light: rgba($active_light, $opacity_5);
100
101
  $focus_input_dark: rgba(#144075, $opacity_5);
101
102
  $focus_input_colors: (
102
103
  focus_input_light: $focus_input_light,
103
- focus_input_dark: $focus_input_dark
104
+ focus_input_dark: $focus_input_dark,
105
+ focus_color: $focus_color
104
106
  );
105
107
 
106
108
  /* Border colors ----------------------*/