playbook_ui 12.16.0 → 12.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_body/_body.scss +10 -0
  3. data/app/pb_kits/playbook/pb_body/docs/_body_styled.html.erb +12 -0
  4. data/app/pb_kits/playbook/pb_body/docs/_body_styled.jsx +14 -2
  5. data/app/pb_kits/playbook/pb_body/docs/_body_styled.md +1 -1
  6. data/app/pb_kits/playbook/pb_body/docs/example.yml +2 -2
  7. data/app/pb_kits/playbook/pb_button/_button_mixins.scss +7 -1
  8. data/app/pb_kits/playbook/pb_card/docs/_card_background.jsx +1 -1
  9. data/app/pb_kits/playbook/pb_date_stacked/_date_stacked.tsx +1 -1
  10. data/app/pb_kits/playbook/pb_docs/kit_api.html.erb +295 -8
  11. data/app/pb_kits/playbook/pb_docs/kit_api.rb +42 -0
  12. data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +17 -0
  13. data/app/pb_kits/playbook/pb_docs/kit_example.rb +18 -1
  14. data/app/pb_kits/playbook/pb_image/docs/{_default_image.tsx → _default_image.jsx} +1 -1
  15. data/app/pb_kits/playbook/pb_lightbox/_lightbox.tsx +6 -1
  16. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_compound_component.jsx +1 -5
  17. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_current_photo.jsx +121 -0
  18. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_current_photo.md +1 -0
  19. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_custom_header.jsx +1 -5
  20. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_default.jsx +1 -5
  21. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_default.md +1 -1
  22. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_multiple.jsx +1 -5
  23. data/app/pb_kits/playbook/pb_lightbox/docs/example.yml +1 -0
  24. data/app/pb_kits/playbook/pb_lightbox/docs/index.js +1 -0
  25. data/app/pb_kits/playbook/pb_lightbox/lightbox.test.jsx +1 -5
  26. data/app/pb_kits/playbook/pb_table/_table.tsx +4 -0
  27. data/app/pb_kits/playbook/pb_table/docs/_table_vertical_border.html.erb +34 -0
  28. data/app/pb_kits/playbook/pb_table/docs/_table_vertical_border.jsx +48 -0
  29. data/app/pb_kits/playbook/pb_table/docs/example.yml +2 -2
  30. data/app/pb_kits/playbook/pb_table/docs/index.js +1 -0
  31. data/app/pb_kits/playbook/pb_table/styles/_all.scss +1 -0
  32. data/app/pb_kits/playbook/pb_table/styles/_vertical_border.scss +16 -0
  33. data/app/pb_kits/playbook/pb_table/table.rb +7 -1
  34. data/app/pb_kits/playbook/pb_timeline/{_item.jsx → _item.tsx} +10 -12
  35. data/app/pb_kits/playbook/pb_timeline/{_timeline.jsx → _timeline.tsx} +9 -9
  36. data/app/pb_kits/playbook/pb_timeline/timeline.test.js +88 -0
  37. data/app/pb_kits/playbook/utilities/_cursor.scss +36 -36
  38. data/lib/playbook/version.rb +2 -2
  39. metadata +11 -5
@@ -0,0 +1,121 @@
1
+ /* @flow */
2
+ /* eslint-disable jsx-control-statements/jsx-use-if-tag */
3
+ import React, { useState } from 'react'
4
+ import { Flex, Image, Button, Body, FlexItem } from '../../'
5
+ import Lightbox from '../_lightbox.tsx'
6
+
7
+ const LightboxCurrentPhoto = (props) => {
8
+ const photos = [
9
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
10
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
11
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
12
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
13
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
14
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
15
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
16
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
17
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
18
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
19
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
20
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
21
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
22
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
23
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
24
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
25
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
26
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
27
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
28
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
29
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
30
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
31
+ ]
32
+ const [light, toggleLight] = useState(false)
33
+ //Setting state with the index of the current slide exposed by the onChange prop
34
+ const [active, setActive] = useState(0)
35
+ //Setting state for the current photo to pass to the kit
36
+ const [currentPhoto, setCurrentPhoto] = useState(active)
37
+
38
+ const handleCloseLightbox = () => {
39
+ toggleLight(!light)
40
+ }
41
+
42
+ const onPhotoClick = () => {
43
+ toggleLight(!light)
44
+ }
45
+
46
+ const exampleStyles = {
47
+ width: "100%",
48
+ overflow: "auto"
49
+ }
50
+
51
+ return (
52
+ <div className="lightbox_doc_example_custom">
53
+ {light ? (
54
+ <>
55
+ <Flex alignItems="center"
56
+ className='custom_lightbox_sidebar'
57
+ justifyContent="center"
58
+ >
59
+ <Flex margin='lg'
60
+ orientation='column'
61
+ >
62
+ <Body marginBottom='md'>
63
+ This UI is for demonstration purposes only to demonstrate how external buttons can be used to change the slides.
64
+ </Body>
65
+ <FlexItem alignSelf="center">
66
+ <Flex justifyContent="center">
67
+ <Button
68
+ onClick={()=> setCurrentPhoto(active > 0 ? active - 1 : 0)}
69
+ >
70
+ Back
71
+ </Button>
72
+ <Button marginLeft='sm'
73
+ onClick={() => setCurrentPhoto(active < photos.length - 1 ? active + 1 : photos.length - 1)}
74
+ >
75
+ Next
76
+ </Button>
77
+ </Flex>
78
+ </FlexItem>
79
+ </Flex>
80
+ </Flex>
81
+ <Lightbox
82
+ currentPhotoIndex={currentPhoto}
83
+ icon="times"
84
+ onChange={(index) => setActive(index)}
85
+ onClose={handleCloseLightbox}
86
+ photos={photos}
87
+ {...props}
88
+ />
89
+ </>
90
+ ) : (
91
+ <div
92
+ className="PhotoViewer"
93
+ style={exampleStyles}
94
+ >
95
+ <Flex>
96
+ {photos.map((photo, index) => {
97
+ return (
98
+ <div
99
+ key={index}
100
+ onClick={() => onPhotoClick(index)}
101
+ >
102
+ <Image
103
+ cursor="pointer"
104
+ marginRight="xl"
105
+ rounded
106
+ size="lg"
107
+ url={photo}
108
+ />
109
+
110
+ <div className="overlay" />
111
+ </div>
112
+ )
113
+ })}
114
+ </Flex>
115
+ </div>
116
+ )}
117
+ </div>
118
+ )
119
+ }
120
+
121
+ export default LightboxCurrentPhoto
@@ -0,0 +1 @@
1
+ The `currentPhotoIndex` prop allows the user to pass a number to the lightbox that will set the current slide by index. This can be leveraged if the user wants to change slides using custom buttons. To do this, the user must also make use of the current slide's index that is exposed by the `onChange` prop.
@@ -10,17 +10,14 @@ const LightboxCustomHeader = (props) => {
10
10
  "https://images.unsplash.com/photo-1501045337096-542a73dafa4f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2052&q=80",
11
11
  "https://images.unsplash.com/photo-1563693998336-93c10e5d8f91?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80,",
12
12
  ];
13
- const [selectedPhoto, setSelectedPhoto] = useState(0);
14
13
  const [showLightbox, toggleShowLightbox] = useState(false);
15
14
 
16
15
  const handleCloseLightbox = () => {
17
16
  toggleShowLightbox(!showLightbox);
18
- setSelectedPhoto(null);
19
17
  };
20
18
 
21
- const onPhotoClick = (photo) => {
19
+ const onPhotoClick = () => {
22
20
  toggleShowLightbox(!showLightbox);
23
- setSelectedPhoto(photo);
24
21
  };
25
22
 
26
23
  const exampleStyles = {
@@ -55,7 +52,6 @@ const LightboxCustomHeader = (props) => {
55
52
  {showLightbox ? (
56
53
  <Lightbox
57
54
  description={customDescription}
58
- initialPhoto={selectedPhoto}
59
55
  navRight="All Photos"
60
56
  onClickRight={()=> alert("Clicked!")}
61
57
  onClose={handleCloseLightbox}
@@ -8,17 +8,14 @@ const LightboxDefault = (props) => {
8
8
  const photos = [
9
9
  'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
10
10
  ]
11
- const [selectedPhoto, setSelectedPhoto] = useState(0)
12
11
  const [showLightbox, toggleShowLightbox] = useState(false)
13
12
 
14
13
  const handleCloseLightbox = () => {
15
14
  toggleShowLightbox(!showLightbox)
16
- setSelectedPhoto(null)
17
15
  }
18
16
 
19
- const onPhotoClick = (photoIndex) => {
17
+ const onPhotoClick = () => {
20
18
  toggleShowLightbox(!showLightbox)
21
- setSelectedPhoto(photoIndex)
22
19
  }
23
20
 
24
21
  return (
@@ -27,7 +24,6 @@ const LightboxDefault = (props) => {
27
24
  {showLightbox ? (
28
25
  <Lightbox
29
26
  icon="times"
30
- initialPhoto={selectedPhoto}
31
27
  onClose={handleCloseLightbox}
32
28
  photos={photos}
33
29
  {...props}
@@ -1 +1 @@
1
- Lightbox contains several props: `photos` (an array of urls), `initialPhoto` (a number), `onClickLeft` (an optional callback function for top left close button), `title` and `description` (string or custom components), `icon` ( optional prop for the close button in the top left of the header), `navRight` (optional prop that renders clickable text in the top right section of the header), `onClickRight` (optional callback function of navRight) and `onChange` (optional event handler prop exposing index of current photo).
1
+ Lightbox contains several props: `photos` (an array of urls), `onClickLeft` (an optional callback function for top left close button), `title` and `description` (string or custom components), `icon` ( optional prop for the close button in the top left of the header), `navRight` (optional prop that renders clickable text in the top right section of the header), `onClickRight` (optional callback function of navRight) and `onChange` (optional event handler prop exposing index of current photo).
@@ -29,17 +29,14 @@ const LightboxMultiple = (props) => {
29
29
  'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
30
30
  'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
31
31
  ]
32
- const [selectedPhoto, setSelectedPhoto] = useState(0)
33
32
  const [light, toggleLight] = useState(false)
34
33
 
35
34
  const handleCloseLightbox = () => {
36
35
  toggleLight(!light)
37
- setSelectedPhoto(null)
38
36
  }
39
37
 
40
- const onPhotoClick = (photo) => {
38
+ const onPhotoClick = () => {
41
39
  toggleLight(!light)
42
- setSelectedPhoto(photo)
43
40
  }
44
41
 
45
42
  const exampleStyles = {
@@ -52,7 +49,6 @@ const LightboxMultiple = (props) => {
52
49
  {light ? (
53
50
  <Lightbox
54
51
  icon="times"
55
- initialPhoto={selectedPhoto}
56
52
  onChange={(index) => console.log(`current photo index: ${index}`)}
57
53
  onClose={handleCloseLightbox}
58
54
  photos={photos}
@@ -5,3 +5,4 @@ examples:
5
5
  - lightbox_multiple: Multiple
6
6
  - lightbox_compound_component: Compound Component
7
7
  - lightbox_custom_header: Custom Header
8
+ - lightbox_current_photo: Current Photo
@@ -2,3 +2,4 @@ export { default as LightboxDefault } from './_lightbox_default.jsx'
2
2
  export { default as LightboxMultiple } from './_lightbox_multiple.jsx'
3
3
  export { default as LightboxCompoundComponent } from './_lightbox_compound_component.jsx'
4
4
  export { default as LightboxCustomHeader } from './_lightbox_custom_header'
5
+ export { default as LightboxCurrentPhoto } from './_lightbox_current_photo'
@@ -18,7 +18,6 @@ test('Kit renders', () => {
18
18
  data={{ testid: testId }}
19
19
  icon="close"
20
20
  id="test1"
21
- initialPhoto={1}
22
21
  onClose={() => {}}
23
22
  photos={TEST_PHOTOS}
24
23
  />
@@ -35,7 +34,6 @@ test('Shows selected images', () => {
35
34
  data={{ testid: testId }}
36
35
  icon="close"
37
36
  id="test1"
38
- initialPhoto={1}
39
37
  onClose={() => {}}
40
38
  photos={TEST_PHOTOS}
41
39
  />
@@ -43,7 +41,7 @@ test('Shows selected images', () => {
43
41
  const kit = screen.getByTestId(testId)
44
42
  const slide = kit.getElementsByClassName('Slide')[0]
45
43
  const image = slide.getElementsByTagName('img')[0]
46
- expect(image).toHaveAttribute('src', TEST_PHOTOS[1])
44
+ expect(image).toHaveAttribute('src', TEST_PHOTOS[0])
47
45
 
48
46
  const thumbnails = kit.getElementsByClassName('Thumbnail')
49
47
 
@@ -77,7 +75,6 @@ test('Closes on escape key', async () => {
77
75
  data={{ testid: testId }}
78
76
  icon="close"
79
77
  id="test1"
80
- initialPhoto={0}
81
78
  onClose={mockClose}
82
79
  photos={TEST_PHOTOS}
83
80
  />
@@ -106,7 +103,6 @@ test('Closes on close button', async () => {
106
103
  data={{ testid: testId }}
107
104
  icon="close"
108
105
  id="test1"
109
- initialPhoto={0}
110
106
  onClose={mockClose}
111
107
  photos={TEST_PHOTOS}
112
108
  />
@@ -19,6 +19,7 @@ type TableProps = {
19
19
  singleLine: boolean,
20
20
  size: "sm" | "md" | "lg",
21
21
  sticky?: boolean,
22
+ verticalBorder?: boolean,
22
23
  }
23
24
 
24
25
  const Table = (props: TableProps) => {
@@ -37,11 +38,13 @@ const Table = (props: TableProps) => {
37
38
  singleLine = false,
38
39
  size = 'sm',
39
40
  sticky = false,
41
+ verticalBorder = false,
40
42
  } = props
41
43
 
42
44
  const ariaProps = buildAriaProps(aria)
43
45
  const dataProps = buildDataProps(data)
44
46
  const tableCollapseCss = responsive !== 'none' ? `table-collapse-${collapse}` : ''
47
+ const verticalBorderCss = verticalBorder ? 'vertical-border' : ''
45
48
 
46
49
  useEffect(() => {
47
50
  const instance = new PbTable()
@@ -66,6 +69,7 @@ const Table = (props: TableProps) => {
66
69
  },
67
70
  globalProps(props),
68
71
  tableCollapseCss,
72
+ verticalBorderCss,
69
73
  className
70
74
  )}
71
75
  id={id}
@@ -0,0 +1,34 @@
1
+ <%= pb_rails("table", props: { size: "sm", vertical_border: true }) do %>
2
+ <thead>
3
+ <tr>
4
+ <th>Column 1</th>
5
+ <th>Column 2</th>
6
+ <th>Column 3</th>
7
+ <th>Column 4</th>
8
+ <th>Column 5</th>
9
+ </tr>
10
+ </thead>
11
+ <tbody>
12
+ <tr>
13
+ <td>Value 1</td>
14
+ <td>Value 2</td>
15
+ <td>Value 3</td>
16
+ <td>Value 4</td>
17
+ <td>Value 5</td>
18
+ </tr>
19
+ <tr>
20
+ <td>Value 1</td>
21
+ <td>Value 2</td>
22
+ <td>Value 3</td>
23
+ <td>Value 4</td>
24
+ <td>Value 5</td>
25
+ </tr>
26
+ <tr>
27
+ <td>Value 1</td>
28
+ <td>Value 2</td>
29
+ <td>Value 3</td>
30
+ <td>Value 4</td>
31
+ <td>Value 5</td>
32
+ </tr>
33
+ </tbody>
34
+ <% end %>
@@ -0,0 +1,48 @@
1
+ import React from 'react'
2
+
3
+ import Table from '../_table'
4
+
5
+ const TableVerticalBorder = (props) => {
6
+ return (
7
+ <Table
8
+ size="sm"
9
+ verticalBorder
10
+ {...props}
11
+ >
12
+ <thead>
13
+ <tr>
14
+ <th>{'Column 1'}</th>
15
+ <th>{'Column 2'}</th>
16
+ <th>{'Column 3'}</th>
17
+ <th>{'Column 4'}</th>
18
+ <th>{'Column 5'}</th>
19
+ </tr>
20
+ </thead>
21
+ <tbody>
22
+ <tr>
23
+ <td>{'Value 1'}</td>
24
+ <td>{'Value 2'}</td>
25
+ <td>{'Value 3'}</td>
26
+ <td>{'Value 4'}</td>
27
+ <td>{'Value 5'}</td>
28
+ </tr>
29
+ <tr>
30
+ <td>{'Value 1'}</td>
31
+ <td>{'Value 2'}</td>
32
+ <td>{'Value 3'}</td>
33
+ <td>{'Value 4'}</td>
34
+ <td>{'Value 5'}</td>
35
+ </tr>
36
+ <tr>
37
+ <td>{'Value 1'}</td>
38
+ <td>{'Value 2'}</td>
39
+ <td>{'Value 3'}</td>
40
+ <td>{'Value 4'}</td>
41
+ <td>{'Value 5'}</td>
42
+ </tr>
43
+ </tbody>
44
+ </Table>
45
+ )
46
+ }
47
+
48
+ export default TableVerticalBorder
@@ -21,7 +21,7 @@ examples:
21
21
  - table_action_middle: Table with Actions in the Middle
22
22
  - table_icon_buttons: Table with Icon Buttons
23
23
  - table_with_background_kit: Table With Background Kit
24
-
24
+ - table_vertical_border: Vertical Borders
25
25
 
26
26
  react:
27
27
  - table_sm: Small
@@ -45,4 +45,4 @@ examples:
45
45
  - table_action_middle: Table with Actions in the Middle
46
46
  - table_icon_buttons: Table with Icon Buttons
47
47
  - table_with_background_kit: Table With Background Kit
48
-
48
+ - table_vertical_border: Vertical Borders
@@ -19,3 +19,4 @@ export { default as TableAlignmentRow } from './_table_alignment_row.jsx'
19
19
  export { default as TableAlignmentShiftRow } from './_table_alignment_shift_row.jsx'
20
20
  export { default as TableAlignmentShiftData } from './_table_alignment_shift_data.jsx'
21
21
  export { default as TableWithBackgroundKit } from './_table_with_background_kit.jsx'
22
+ export { default as TableVerticalBorder } from './_table_vertical_border.jsx'
@@ -16,3 +16,4 @@
16
16
  @import "tablet_collapse";
17
17
  @import "desktop_collapse";
18
18
  @import "sticky_header";
19
+ @import "vertical_border";
@@ -0,0 +1,16 @@
1
+ [class^=pb_table] {
2
+ &.vertical-border {
3
+ td,
4
+ th {
5
+ border-right: 1px solid $border_light !important;
6
+ }
7
+
8
+ @media screen and (min-width: $screen-xs-min) {
9
+ tr:hover {
10
+ td:last-child {
11
+ border-right-color: darken($border_light, 10%) !important;
12
+ }
13
+ }
14
+ }
15
+ }
16
+ }
@@ -23,12 +23,14 @@ module Playbook
23
23
  prop :text
24
24
  prop :sticky, type: Playbook::Props::Boolean,
25
25
  default: false
26
+ prop :vertical_border, type: Playbook::Props::Boolean,
27
+ default: false
26
28
 
27
29
  def classname
28
30
  generate_classname(
29
31
  "pb_table", "table-#{size}", single_line_class, dark_class,
30
32
  disable_hover_class, container_class, data_table_class, sticky_class, collapse_class,
31
- "table-responsive-#{responsive}", separator: " "
33
+ vertical_border_class, "table-responsive-#{responsive}", separator: " "
32
34
  )
33
35
  end
34
36
 
@@ -61,6 +63,10 @@ module Playbook
61
63
  def sticky_class
62
64
  sticky ? "sticky-header" : nil
63
65
  end
66
+
67
+ def vertical_border_class
68
+ vertical_border ? "vertical-border" : nil
69
+ end
64
70
  end
65
71
  end
66
72
  end
@@ -1,5 +1,3 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import classnames from 'classnames'
5
3
 
@@ -10,8 +8,8 @@ import IconCircle from '../pb_icon_circle/_icon_circle'
10
8
 
11
9
  type ItemProps = {
12
10
  className?: string,
13
- children?: array<React.Node>,
14
- date?: date,
11
+ children?: React.ReactNode[] | React.ReactNode,
12
+ date?: Date,
15
13
  icon?: string,
16
14
  iconColor?: 'default' | 'royal' | 'blue' | 'purple' | 'teal' | 'red' | 'yellow' | 'green',
17
15
  lineStyle?: 'solid' | 'dotted',
@@ -31,19 +29,19 @@ const TimelineItem = ({
31
29
  return (
32
30
  <div className={classnames(timelineItemCss, className)}>
33
31
  <div className="pb_timeline_item_left_block">
34
- <If condition={date}>
32
+ {date &&
35
33
  <DateStacked
36
- align="center"
37
- date={date}
38
- size="sm"
34
+ align="center"
35
+ date={date}
36
+ size="sm"
39
37
  />
40
- </If>
38
+ }
41
39
  </div>
42
40
  <div className="pb_timeline_item_step">
43
41
  <IconCircle
44
- icon={icon}
45
- size="xs"
46
- variant={iconColor}
42
+ icon={icon}
43
+ size="xs"
44
+ variant={iconColor}
47
45
  />
48
46
  <div className="pb_timeline_item_connector" />
49
47
  </div>
@@ -1,17 +1,15 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import classnames from 'classnames'
5
3
 
6
4
  import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
7
5
 
8
- import TimelineItem from './_item.jsx'
6
+ import TimelineItem from './_item'
9
7
 
10
8
  type TimelineProps = {
11
- aria?: object,
12
- children?: array<React.ReactChild>,
9
+ aria?: { [key: string]: string },
10
+ children?: React.ReactChild[] | React.ReactChild,
13
11
  className?: string,
14
- data?: string,
12
+ data?: { [key: string]: string },
15
13
  id?: string,
16
14
  orientation?: string,
17
15
  showDate?: boolean,
@@ -22,6 +20,7 @@ const Timeline = ({
22
20
  className,
23
21
  children,
24
22
  data = {},
23
+ id,
25
24
  orientation = 'horizontal',
26
25
  showDate = false,
27
26
  }: TimelineProps) => {
@@ -31,9 +30,10 @@ const Timeline = ({
31
30
  const timelineCss = buildCss('pb_timeline_kit', `_${orientation}`, dateStyle)
32
31
  return (
33
32
  <div
34
- {...ariaProps}
35
- {...dataProps}
36
- className={classnames(timelineCss, className)}
33
+ {...ariaProps}
34
+ {...dataProps}
35
+ className={classnames(timelineCss, className)}
36
+ id={id}
37
37
  >
38
38
  {children}
39
39
  </div>
@@ -0,0 +1,88 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import Timeline from './_timeline'
5
+ import TitleDetail from '../pb_title_detail/_title_detail'
6
+
7
+ const testId = 'timeline'
8
+ const className = 'custom-class-name'
9
+
10
+ const TimelineDefault = (props) => (
11
+ <>
12
+ <Timeline
13
+ aria={{ label: testId }}
14
+ className={className}
15
+ data={{ testid: testId }}
16
+ id={testId}
17
+ {...props}
18
+ >
19
+ <Timeline.Item
20
+ icon="user"
21
+ iconColor="royal"
22
+ lineStyle="dotted"
23
+ {...props}
24
+ >
25
+ <TitleDetail
26
+ detail="37-27 74th Street"
27
+ title="Jackson heights"
28
+ {...props}
29
+ />
30
+ </Timeline.Item>
31
+ <Timeline.Item
32
+ icon="check"
33
+ iconColor="teal"
34
+ {...props}
35
+ >
36
+ <TitleDetail
37
+ detail="81 Gate St Brooklyn"
38
+ title="Greenpoint"
39
+ {...props}
40
+ />
41
+ </Timeline.Item>
42
+ </Timeline>
43
+ </>
44
+ )
45
+
46
+ test('should pass data prop', () => {
47
+ render(<TimelineDefault />)
48
+ const kit = screen.getByTestId(testId)
49
+ expect(kit).toBeInTheDocument()
50
+ })
51
+
52
+ test('should pass className prop', () => {
53
+ render(<TimelineDefault />)
54
+ const kit = screen.getByTestId(testId)
55
+ expect(kit).toHaveClass(className)
56
+ })
57
+
58
+ test('should pass aria prop', () => {
59
+ render(<TimelineDefault />)
60
+ const kit = screen.getByTestId(testId)
61
+ expect(kit).toHaveAttribute('aria-label', testId)
62
+ })
63
+
64
+ test('should pass id prop', () => {
65
+ render(<TimelineDefault />)
66
+ const kit = screen.getByTestId(testId)
67
+ expect(kit).toHaveProperty('id', testId)
68
+ })
69
+
70
+ test('should have horizontal orientation by default', () => {
71
+ render(<TimelineDefault />)
72
+ const kit = screen.getByTestId(testId)
73
+ expect(kit).toHaveClass('pb_timeline_kit__horizontal')
74
+ })
75
+
76
+ test('should pass vertical orientation', () => {
77
+ const props = { orientation: 'vertical' }
78
+ render(<TimelineDefault {...props} />)
79
+ const kit = screen.getByTestId(testId)
80
+ expect(kit).toHaveClass('pb_timeline_kit__vertical')
81
+ })
82
+
83
+ test('should pass showDate prop', () => {
84
+ const props = { showDate: true }
85
+ render(<TimelineDefault {...props} />)
86
+ const kit = screen.getByTestId(testId)
87
+ expect(kit).toHaveClass('pb_timeline_kit__horizontal__with_date')
88
+ })