@platformatic/ui-components 0.1.33 → 0.1.35
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.
- package/README.md +4 -0
- package/dist/main.css +4 -5
- package/index.js +4 -0
- package/package.json +1 -1
- package/src/components/Box.module.css +1 -1
- package/src/components/Button.jsx +10 -10
- package/src/components/Button.module.css +54 -7
- package/src/components/ButtonFullRounded.jsx +17 -0
- package/src/components/ButtonFullRounded.module.css +28 -0
- package/src/components/Checkbox.jsx +11 -0
- package/src/components/Checkbox.module.css +18 -0
- package/src/components/DropDown.module.css +6 -4
- package/src/components/FollowUs.jsx +2 -2
- package/src/components/FollowUs.module.css +3 -3
- package/src/components/HorizontalSeparator.jsx +2 -1
- package/src/components/HorizontalSeparator.module.css +23 -0
- package/src/components/Modal.jsx +52 -20
- package/src/components/Modal.module.css +14 -2
- package/src/components/TabbedWindow.jsx +8 -3
- package/src/components/icons/CloseModalGreenHoverIcon.jsx +37 -0
- package/src/components/icons/CloseModalGreenIcon.jsx +27 -0
- package/src/components/icons/Icons.module.css +15 -0
- package/src/components/icons/MetricsIcon.jsx +52 -0
- package/src/components/icons/PullRequestIcon.jsx +32 -28
- package/src/components/icons/index.js +4 -1
- package/src/components/layouts/TwoColumnsLayout.module.css +1 -1
- package/src/stories/Button.stories.jsx +41 -24
- package/src/stories/ButtonFullRounded.stories.jsx +61 -0
- package/src/stories/Checkbox.stories.jsx +27 -0
- package/src/stories/Modal.stories.jsx +33 -4
- package/src/stories/icons/PullRequestIcon.stories.jsx +20 -0
- package/tailwind.config.cjs +7 -2
package/README.md
CHANGED
package/dist/main.css
CHANGED
|
@@ -548,11 +548,6 @@ video {
|
|
|
548
548
|
margin: 0.75rem;
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
-
.my-4 {
|
|
552
|
-
margin-top: 1rem;
|
|
553
|
-
margin-bottom: 1rem;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
551
|
.mx-auto {
|
|
557
552
|
margin-left: auto;
|
|
558
553
|
margin-right: auto;
|
|
@@ -563,6 +558,10 @@ video {
|
|
|
563
558
|
margin-bottom: 1.25rem;
|
|
564
559
|
}
|
|
565
560
|
|
|
561
|
+
.mr-3 {
|
|
562
|
+
margin-right: 0.75rem;
|
|
563
|
+
}
|
|
564
|
+
|
|
566
565
|
.mr-2 {
|
|
567
566
|
margin-right: 0.5rem;
|
|
568
567
|
}
|
package/index.js
CHANGED
|
@@ -4,6 +4,8 @@ import BorderedBox from './src/components/BorderedBox'
|
|
|
4
4
|
import BorderedText from './src/components/BorderedText'
|
|
5
5
|
import Box from './src/components/Box'
|
|
6
6
|
import Button from './src/components/Button'
|
|
7
|
+
import ButtonFullRounded from './src/components/ButtonFullRounded'
|
|
8
|
+
import Checkbox from './src/components/Checkbox'
|
|
7
9
|
import DetailedMetric from './src/components/DetailedMetric'
|
|
8
10
|
import DropDown from './src/components/DropDown'
|
|
9
11
|
import FollowUs from './src/components/FollowUs'
|
|
@@ -32,6 +34,8 @@ export {
|
|
|
32
34
|
BorderedText,
|
|
33
35
|
Box,
|
|
34
36
|
Button,
|
|
37
|
+
ButtonFullRounded,
|
|
38
|
+
Checkbox,
|
|
35
39
|
DetailedMetric,
|
|
36
40
|
DropDown,
|
|
37
41
|
FollowUs,
|
package/package.json
CHANGED
|
@@ -4,19 +4,19 @@ import React from 'react'
|
|
|
4
4
|
import styles from './Button.module.css'
|
|
5
5
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
6
6
|
export default function Button (props) {
|
|
7
|
-
const { icon, label,
|
|
8
|
-
let
|
|
9
|
-
if (
|
|
10
|
-
|
|
7
|
+
const { icon, label, buttonClass = 'secondary', color = 'green', disabled, size = 'large', bold = false, ...rest } = props
|
|
8
|
+
let className = `${styles.button} ${styles[buttonClass + '-' + color]} ${styles['button-' + size]}`
|
|
9
|
+
if (disabled) {
|
|
10
|
+
className += ` ${styles.disabled}`
|
|
11
|
+
if (buttonClass === 'transparent') {
|
|
12
|
+
className += ` ${styles['disabled-transparent']}`
|
|
13
|
+
}
|
|
11
14
|
}
|
|
15
|
+
if (bold) className += ` ${styles.fontBold}`
|
|
12
16
|
|
|
13
|
-
let colorClass = 'green'
|
|
14
|
-
if (color === 'red') {
|
|
15
|
-
colorClass = 'red'
|
|
16
|
-
}
|
|
17
17
|
return (
|
|
18
|
-
<button className={
|
|
19
|
-
{icon ? <FontAwesomeIcon icon={icon} className='
|
|
18
|
+
<button className={className} disabled={disabled} alt={label} {...rest}>
|
|
19
|
+
{icon ? <FontAwesomeIcon icon={icon} className={`${styles['margin-right-' + size]}`} data-testid='button-icon' /> : null}
|
|
20
20
|
<span>{label}</span>
|
|
21
21
|
</button>
|
|
22
22
|
)
|
|
@@ -1,21 +1,68 @@
|
|
|
1
1
|
.button {
|
|
2
|
-
@apply
|
|
2
|
+
@apply rounded text-center cursor-pointer font-normal;
|
|
3
|
+
}
|
|
4
|
+
.fontBold {
|
|
5
|
+
@apply font-semibold;
|
|
6
|
+
}
|
|
7
|
+
.button-small {
|
|
8
|
+
@apply p-1 text-sm;
|
|
9
|
+
}
|
|
10
|
+
.button-medium {
|
|
11
|
+
@apply p-1;
|
|
12
|
+
}
|
|
13
|
+
.button-large {
|
|
14
|
+
@apply p-2;
|
|
15
|
+
}
|
|
16
|
+
.button-extra-large {
|
|
17
|
+
@apply p-2 md:p-2.5;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.margin-right-medium,
|
|
21
|
+
.margin-right-small {
|
|
22
|
+
@apply mr-1;
|
|
23
|
+
}
|
|
24
|
+
.margin-right-large {
|
|
25
|
+
@apply mr-2;
|
|
26
|
+
}
|
|
27
|
+
.margin-right-extra-large {
|
|
28
|
+
@apply mr-3;
|
|
3
29
|
}
|
|
4
30
|
|
|
5
31
|
.primary-green {
|
|
6
|
-
@apply
|
|
32
|
+
@apply text-main-dark-blue bg-light-green;
|
|
7
33
|
}
|
|
8
34
|
.secondary-green {
|
|
9
|
-
@apply border-main-green text-main-green bg-none border border-solid box-border rounded-md
|
|
35
|
+
@apply border-main-green text-main-green bg-none border border-solid box-border rounded-md;
|
|
36
|
+
}
|
|
37
|
+
.transparent-green {
|
|
38
|
+
@apply text-main-green border-0 bg-transparent hover:underline;
|
|
10
39
|
}
|
|
11
40
|
|
|
41
|
+
|
|
12
42
|
.primary-red {
|
|
13
|
-
@apply
|
|
43
|
+
@apply text-main-dark-blue bg-error-red;
|
|
14
44
|
}
|
|
15
45
|
.secondary-red {
|
|
16
|
-
@apply border-error-red text-error-red bg-none border border-solid box-border rounded-md
|
|
46
|
+
@apply border-error-red text-error-red bg-none border border-solid box-border rounded-md;
|
|
47
|
+
}
|
|
48
|
+
.transparent-red {
|
|
49
|
+
@apply text-error-red border-0 bg-transparent hover:underline;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.primary-white {
|
|
53
|
+
@apply text-main-dark-blue bg-white;
|
|
54
|
+
}
|
|
55
|
+
.secondary-white {
|
|
56
|
+
@apply border-white text-white bg-none border border-solid box-border rounded-md;
|
|
57
|
+
}
|
|
58
|
+
.transparent-white {
|
|
59
|
+
@apply text-white border-0 bg-transparent hover:underline;
|
|
17
60
|
}
|
|
18
61
|
|
|
19
62
|
.disabled {
|
|
20
|
-
@apply
|
|
21
|
-
}
|
|
63
|
+
@apply opacity-30 cursor-default;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.disabled-transparent {
|
|
67
|
+
@apply hover:no-underline;
|
|
68
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import styles from './ButtonFullRounded.module.css'
|
|
4
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
5
|
+
export default function ButtonFullRounded (props) {
|
|
6
|
+
// colorClass: white
|
|
7
|
+
// size: small|medium|large
|
|
8
|
+
const { icon, color = 'white', disabled, size = 'small' } = props
|
|
9
|
+
let className = `${styles.buttonRoundedFull} ${styles[color]} ${styles['button-' + size]}`
|
|
10
|
+
if (disabled) className += ` ${styles.disabled}`
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<button className={className} disabled={disabled} {...props}>
|
|
14
|
+
<FontAwesomeIcon icon={icon} data-testid='button-icon' />
|
|
15
|
+
</button>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
.buttonRoundedFull {
|
|
2
|
+
@apply rounded-full flex justify-center cursor-pointer font-normal bg-main-dark-blue border items-center;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
.button-small {
|
|
7
|
+
@apply p-0 text-sm h-5 w-5;
|
|
8
|
+
}
|
|
9
|
+
.button-medium {
|
|
10
|
+
@apply p-1 h-6 w-6;
|
|
11
|
+
}
|
|
12
|
+
.button-large {
|
|
13
|
+
@apply p-2 h-7 w-7;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.green {
|
|
17
|
+
@apply border-light-green text-light-green ;
|
|
18
|
+
}
|
|
19
|
+
.red {
|
|
20
|
+
@apply border-error-red text-error-red;
|
|
21
|
+
}
|
|
22
|
+
.white {
|
|
23
|
+
@apply border-white text-white;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.disabled {
|
|
27
|
+
@apply bg-opacity-30 cursor-default;
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import styles from './Checkbox.module.css'
|
|
4
|
+
export default function Checkbox (props) {
|
|
5
|
+
const { disabled, ...rest } = props
|
|
6
|
+
let className = `${styles.checkbox}`
|
|
7
|
+
if (disabled) className += ` ${styles.disabled}`
|
|
8
|
+
return (
|
|
9
|
+
<input type='checkbox' className={className} disabled={disabled} {...rest} />
|
|
10
|
+
)
|
|
11
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
.checkbox {
|
|
2
|
+
@apply border border-light-green p-2 rounded-sm bg-main-dark-blue relative inline-block h-2 w-2;
|
|
3
|
+
-webkit-appearance: none;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.checkbox:checked {
|
|
7
|
+
@apply bg-light-green text-main-dark-blue;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.checkbox:checked:after {
|
|
11
|
+
@apply absolute top-[-2px] left-[1px] h-full w-full;
|
|
12
|
+
content: '\2714';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.disabled {
|
|
16
|
+
@apply border-white;
|
|
17
|
+
}
|
|
18
|
+
|
|
@@ -10,14 +10,16 @@
|
|
|
10
10
|
@apply items-start;
|
|
11
11
|
}
|
|
12
12
|
.arrow {
|
|
13
|
-
@apply
|
|
13
|
+
@apply absolute top-[50%] right-0 translate-y-[-50%];
|
|
14
14
|
}
|
|
15
15
|
.header {
|
|
16
|
-
@apply hover:cursor-pointer
|
|
16
|
+
@apply hover:cursor-pointer relative pr-6;
|
|
17
17
|
}
|
|
18
18
|
.menu {
|
|
19
|
-
@apply absolute border-solid border border-
|
|
19
|
+
@apply absolute border-solid border border-white px-0 py-1 bg-light-blue mt-8 rounded-md z-[999] text-sm min-w-[175px];
|
|
20
20
|
}
|
|
21
21
|
.item {
|
|
22
|
-
@apply
|
|
22
|
+
@apply py-3 px-3 text-main-dark-blue first:border-t-0 text-sm uppercase hover:font-semibold hover:cursor-pointer tracking-[0.15em];
|
|
23
|
+
/* it's a workaround due to opacity... */
|
|
24
|
+
border-top: 1px solid rgba(0, 40, 61, 0.2);;
|
|
23
25
|
}
|
|
@@ -11,12 +11,12 @@ export default function FollowUs ({ label = 'FOLLOW US ON' }) {
|
|
|
11
11
|
</div>
|
|
12
12
|
<div className={styles.icon}>
|
|
13
13
|
<a href='https://twitter.com/platformatic' target='_blank' rel='noopener noreferrer'>
|
|
14
|
-
<FontAwesomeIcon icon={faTwitter} className='mr-
|
|
14
|
+
<FontAwesomeIcon icon={faTwitter} className='mr-3 text-white' />
|
|
15
15
|
</a>
|
|
16
16
|
</div>
|
|
17
17
|
<div className={styles.icon}>
|
|
18
18
|
<a href='https://www.linkedin.com/company/platformatic/' target='_blank' rel='noopener noreferrer'>
|
|
19
|
-
<FontAwesomeIcon icon={faLinkedin} className='mr-
|
|
19
|
+
<FontAwesomeIcon icon={faLinkedin} className='mr-3 text-white' />
|
|
20
20
|
</a>
|
|
21
21
|
</div>
|
|
22
22
|
<div className={styles.icon}>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
.container {
|
|
2
|
-
@apply flex w-
|
|
2
|
+
@apply flex w-full items-center;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
.label {
|
|
6
|
-
@apply uppercase text-light-green
|
|
6
|
+
@apply uppercase text-light-green tracking-[.15em] text-sm mr-8;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.icon {
|
|
10
|
-
@apply text-white
|
|
10
|
+
@apply text-white mx-4 text-xl;
|
|
11
11
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
import React from 'react'
|
|
3
|
+
import styles from './HorizontalSeparator.module.css'
|
|
3
4
|
export default function HorizontalSeparator ({ marginTop = 4, marginBottom = 4 }) {
|
|
4
5
|
function getClassName () {
|
|
5
|
-
return 'text-dark-green ' + (marginTop === marginBottom ?
|
|
6
|
+
return 'text-dark-green ' + (marginTop === marginBottom ? `${styles['marginY-' + marginTop]}` : `${styles['marginT-' + marginTop]} ${styles['marginB-' + marginBottom]}`)
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
return <hr className={getClassName()} />
|
package/src/components/Modal.jsx
CHANGED
|
@@ -1,29 +1,61 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
2
|
import useEscapeKey from '../hooks/useEscapeKey'
|
|
3
3
|
import CloseModalIcon from './icons/CloseModalIcon'
|
|
4
|
+
import CloseModalGreenIcon from './icons/CloseModalGreenIcon'
|
|
5
|
+
import CloseModalGreenHoverIcon from './icons/CloseModalGreenHoverIcon'
|
|
4
6
|
import styles from './Modal.module.css'
|
|
5
7
|
export default function Modal (props) {
|
|
6
|
-
const { setIsOpen, title } = props
|
|
8
|
+
const { setIsOpen, title, layout = 'info' } = props
|
|
9
|
+
const [isHoverCloseModal, setIsHoverCloseModal] = useState(false)
|
|
7
10
|
useEscapeKey(() => setIsOpen(false))
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
|
|
12
|
+
let whichModal = <></>
|
|
13
|
+
switch (layout) {
|
|
14
|
+
case 'info':
|
|
15
|
+
whichModal = (
|
|
16
|
+
<>
|
|
17
|
+
<div className={styles.blur} onClick={() => setIsOpen(false)} />
|
|
18
|
+
<div className={`${styles.container} ${styles.centered}`}>
|
|
19
|
+
<div className={`${styles.modal} ${styles.modalInfo}`}>
|
|
20
|
+
<div className={styles.header}>
|
|
21
|
+
<div className={styles.title}>{title}</div>
|
|
22
|
+
<div className={styles.close} onClick={() => setIsOpen(false)}>
|
|
23
|
+
<CloseModalIcon />
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<div>
|
|
27
|
+
{props.children}
|
|
28
|
+
</div>
|
|
17
29
|
</div>
|
|
18
30
|
</div>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
</>
|
|
32
|
+
)
|
|
33
|
+
break
|
|
34
|
+
case 'invite':
|
|
35
|
+
whichModal = (
|
|
36
|
+
<>
|
|
37
|
+
<div className={styles.blur} onClick={() => setIsOpen(false)} />
|
|
38
|
+
<div className={`${styles.container} ${styles.centered}`}>
|
|
39
|
+
<div className={`${styles.modal} ${styles.modalInvite}`}>
|
|
40
|
+
<div className={styles.headerInvite}>
|
|
41
|
+
<div
|
|
42
|
+
className={styles.close}
|
|
43
|
+
onClick={() => setIsOpen(false)}
|
|
44
|
+
onMouseEnter={() => setIsHoverCloseModal(true)}
|
|
45
|
+
onMouseLeave={() => setIsHoverCloseModal(false)}
|
|
46
|
+
>
|
|
47
|
+
{isHoverCloseModal ? <CloseModalGreenHoverIcon /> : <CloseModalGreenIcon />}
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<p className={styles.titleInvite}>{title}</p>
|
|
51
|
+
<div>{props.children}</div>
|
|
52
|
+
</div>
|
|
22
53
|
</div>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
54
|
+
</>
|
|
55
|
+
)
|
|
56
|
+
break
|
|
57
|
+
default:
|
|
58
|
+
break
|
|
59
|
+
}
|
|
60
|
+
return whichModal
|
|
29
61
|
}
|
|
@@ -9,11 +9,20 @@
|
|
|
9
9
|
@apply fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]
|
|
10
10
|
}
|
|
11
11
|
.modal {
|
|
12
|
-
@apply
|
|
12
|
+
@apply p-4 rounded-md mx-auto my-auto min-w-[480px] max-h-[85vh] overflow-y-auto;
|
|
13
|
+
}
|
|
14
|
+
.modalInfo {
|
|
15
|
+
@apply bg-light-blue;
|
|
16
|
+
}
|
|
17
|
+
.modalInvite {
|
|
18
|
+
@apply bg-main-dark-blue border-light-green border shadow-wrap shadow-main-green max-w-[432px] max-h-[300px];
|
|
13
19
|
}
|
|
14
20
|
.header {
|
|
15
21
|
@apply flex justify-between items-center;
|
|
16
22
|
}
|
|
23
|
+
.headerInvite {
|
|
24
|
+
@apply flex justify-end;
|
|
25
|
+
}
|
|
17
26
|
.close {
|
|
18
27
|
@apply hover:cursor-pointer;
|
|
19
28
|
}
|
|
@@ -22,4 +31,7 @@
|
|
|
22
31
|
}
|
|
23
32
|
.title {
|
|
24
33
|
@apply font-bold text-lg;
|
|
25
|
-
}
|
|
34
|
+
}
|
|
35
|
+
.titleInvite {
|
|
36
|
+
@apply font-bold text-lg text-main-green text-center;
|
|
37
|
+
}
|
|
@@ -3,8 +3,8 @@ import React, { useEffect, useState } from 'react'
|
|
|
3
3
|
import styles from './TabbedWindow.module.css'
|
|
4
4
|
|
|
5
5
|
export default function TabbedWindow (props) {
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const { tabs, defaultSelected = 0, callbackSelected = () => {} } = props
|
|
7
|
+
const [selected, setSelected] = useState(defaultSelected)
|
|
8
8
|
const headers = []
|
|
9
9
|
const components = []
|
|
10
10
|
tabs.forEach((tab) => {
|
|
@@ -17,12 +17,17 @@ export default function TabbedWindow (props) {
|
|
|
17
17
|
currentComponent = components[selected]
|
|
18
18
|
}, [selected])
|
|
19
19
|
|
|
20
|
+
function setCurrentTab (index) {
|
|
21
|
+
setSelected(index)
|
|
22
|
+
callbackSelected(index)
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
return (
|
|
21
26
|
<div className={styles['tabbed-container']}>
|
|
22
27
|
<div className={styles['tabs-header']}>
|
|
23
28
|
{headers.map((header, index) => {
|
|
24
29
|
return (
|
|
25
|
-
<span onClick={() =>
|
|
30
|
+
<span onClick={() => setCurrentTab(index)} key={index} className={`${styles.tab} ${selected === index ? styles['selected-tab'] : ''}`}>
|
|
26
31
|
{header}
|
|
27
32
|
</span>
|
|
28
33
|
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
const CloseModalGreenHoverIcon = () => (
|
|
4
|
+
<svg
|
|
5
|
+
width={24}
|
|
6
|
+
height={24}
|
|
7
|
+
viewBox='0 0 24 24'
|
|
8
|
+
fill='none'
|
|
9
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
10
|
+
>
|
|
11
|
+
<circle
|
|
12
|
+
cx={12}
|
|
13
|
+
cy={12}
|
|
14
|
+
r={11.25}
|
|
15
|
+
fill='#21FA90'
|
|
16
|
+
fillOpacity={0.2}
|
|
17
|
+
stroke='#21FA90'
|
|
18
|
+
strokeWidth={1.5}
|
|
19
|
+
/>
|
|
20
|
+
<path
|
|
21
|
+
d='M6 6L18 18'
|
|
22
|
+
stroke='#21FA90'
|
|
23
|
+
strokeWidth={1.5}
|
|
24
|
+
strokeLinecap='round'
|
|
25
|
+
strokeLinejoin='round'
|
|
26
|
+
/>
|
|
27
|
+
<path
|
|
28
|
+
d='M6 18L18 6'
|
|
29
|
+
stroke='#21FA90'
|
|
30
|
+
strokeWidth={1.5}
|
|
31
|
+
strokeLinecap='round'
|
|
32
|
+
strokeLinejoin='round'
|
|
33
|
+
/>
|
|
34
|
+
</svg>
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
export default CloseModalGreenHoverIcon
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
const CloseModalGreenIcon = () => (
|
|
4
|
+
<svg
|
|
5
|
+
width={24}
|
|
6
|
+
height={24}
|
|
7
|
+
viewBox='0 0 24 24'
|
|
8
|
+
fill='none'
|
|
9
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
10
|
+
>
|
|
11
|
+
<circle cx={12} cy={12} r={11.5} stroke='#21FA90' />
|
|
12
|
+
<path
|
|
13
|
+
d='M6 6L18 18'
|
|
14
|
+
stroke='#21FA90'
|
|
15
|
+
strokeLinecap='round'
|
|
16
|
+
strokeLinejoin='round'
|
|
17
|
+
/>
|
|
18
|
+
<path
|
|
19
|
+
d='M6 18L18 6'
|
|
20
|
+
stroke='#21FA90'
|
|
21
|
+
strokeLinecap='round'
|
|
22
|
+
strokeLinejoin='round'
|
|
23
|
+
/>
|
|
24
|
+
</svg>
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
export default CloseModalGreenIcon
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import styles from './Icons.module.css'
|
|
3
|
+
const MetricsIcon = ({ color = 'white' }) => {
|
|
4
|
+
const className = styles[`${color}`]
|
|
5
|
+
return (
|
|
6
|
+
<svg
|
|
7
|
+
width={40}
|
|
8
|
+
height={40}
|
|
9
|
+
viewBox='0 0 40 40'
|
|
10
|
+
fill='none'
|
|
11
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
12
|
+
className={className}
|
|
13
|
+
>
|
|
14
|
+
<rect
|
|
15
|
+
x={10}
|
|
16
|
+
y={12.5}
|
|
17
|
+
width={5}
|
|
18
|
+
height={17.5}
|
|
19
|
+
rx={0.5}
|
|
20
|
+
stroke='none'
|
|
21
|
+
strokeWidth={2}
|
|
22
|
+
/>
|
|
23
|
+
<rect
|
|
24
|
+
x={20}
|
|
25
|
+
y={20}
|
|
26
|
+
width={5}
|
|
27
|
+
height={10}
|
|
28
|
+
rx={0.5}
|
|
29
|
+
stroke='none'
|
|
30
|
+
strokeWidth={2}
|
|
31
|
+
/>
|
|
32
|
+
<rect
|
|
33
|
+
x={30}
|
|
34
|
+
y={5}
|
|
35
|
+
width={5}
|
|
36
|
+
height={25}
|
|
37
|
+
rx={0.5}
|
|
38
|
+
stroke='none'
|
|
39
|
+
strokeWidth={2}
|
|
40
|
+
/>
|
|
41
|
+
<path
|
|
42
|
+
d='M5 5V35H35'
|
|
43
|
+
stroke='none'
|
|
44
|
+
strokeWidth={2}
|
|
45
|
+
strokeLinecap='round'
|
|
46
|
+
strokeLinejoin='round'
|
|
47
|
+
/>
|
|
48
|
+
</svg>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default MetricsIcon
|
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
|
|
3
|
-
const PullRequestIcon = () =>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
stroke='
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
2
|
+
import styles from './Icons.module.css'
|
|
3
|
+
const PullRequestIcon = ({ color = 'white' }) => {
|
|
4
|
+
const className = styles[`${color}`]
|
|
5
|
+
return (
|
|
6
|
+
<svg
|
|
7
|
+
width={40}
|
|
8
|
+
height={40}
|
|
9
|
+
fill='none'
|
|
10
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
11
|
+
className={className}
|
|
12
|
+
>
|
|
13
|
+
<circle cx={9.5} cy={30.5} r={4.5} stroke='none' strokeWidth={2} />
|
|
14
|
+
<circle cx={9.5} cy={9.5} r={4.5} stroke='none' strokeWidth={2} />
|
|
15
|
+
<path stroke='none' strokeWidth={2} d='M9 14v12' />
|
|
16
|
+
<circle cx={30.5} cy={30.5} r={4.5} stroke='none' strokeWidth={2} />
|
|
17
|
+
<path
|
|
18
|
+
d='M30.5 26V10.5a1 1 0 0 0-1-1H23'
|
|
19
|
+
stroke='none'
|
|
20
|
+
strokeWidth={2}
|
|
21
|
+
strokeLinecap='round'
|
|
22
|
+
strokeLinejoin='round'
|
|
23
|
+
/>
|
|
24
|
+
<path
|
|
25
|
+
d='m26 5-4.5 4.5L26 14'
|
|
26
|
+
stroke='none'
|
|
27
|
+
strokeWidth={2}
|
|
28
|
+
strokeLinecap='round'
|
|
29
|
+
strokeLinejoin='round'
|
|
30
|
+
/>
|
|
31
|
+
</svg>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
30
34
|
|
|
31
35
|
export default PullRequestIcon
|
|
@@ -2,8 +2,11 @@ import ApiIcon from './ApiIcon'
|
|
|
2
2
|
import ApiIconClosed from './ApiIconClosed'
|
|
3
3
|
import ApiEmptyIcon from './ApiEmptyIcon'
|
|
4
4
|
import CloseModalIcon from './CloseModalIcon'
|
|
5
|
+
import CloseModalGreenIcon from './CloseModalGreenIcon'
|
|
6
|
+
import CloseModalGreenHoverIcon from './CloseModalGreenHoverIcon'
|
|
7
|
+
import MetricsIcon from './MetricsIcon'
|
|
5
8
|
import PullRequestIcon from './PullRequestIcon'
|
|
6
9
|
|
|
7
10
|
export default {
|
|
8
|
-
ApiIcon, ApiIconClosed, ApiEmptyIcon, CloseModalIcon, PullRequestIcon
|
|
11
|
+
ApiIcon, ApiIconClosed, ApiEmptyIcon, CloseModalIcon, CloseModalGreenIcon, CloseModalGreenHoverIcon, MetricsIcon, PullRequestIcon
|
|
9
12
|
}
|
|
@@ -11,14 +11,31 @@ export default {
|
|
|
11
11
|
type: 'string',
|
|
12
12
|
control: 'text'
|
|
13
13
|
},
|
|
14
|
-
|
|
14
|
+
bold: {
|
|
15
15
|
type: 'boolean'
|
|
16
16
|
},
|
|
17
|
+
buttonClass: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
control: {
|
|
20
|
+
type: 'radio',
|
|
21
|
+
options: ['primary', 'secondary', 'transparent']
|
|
22
|
+
}
|
|
23
|
+
},
|
|
17
24
|
color: {
|
|
18
25
|
type: 'string',
|
|
19
26
|
control: {
|
|
20
27
|
type: 'radio',
|
|
21
|
-
options: ['green', 'red']
|
|
28
|
+
options: ['green', 'red', 'white']
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
disabled: {
|
|
32
|
+
type: 'boolean'
|
|
33
|
+
},
|
|
34
|
+
size: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
control: {
|
|
37
|
+
type: 'radio',
|
|
38
|
+
options: ['small', 'medium', 'large', 'extra-large']
|
|
22
39
|
}
|
|
23
40
|
}
|
|
24
41
|
}
|
|
@@ -29,48 +46,48 @@ const Template = (args) => <Button {...args} />
|
|
|
29
46
|
export const PrimaryGreen = Template.bind({})
|
|
30
47
|
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
|
31
48
|
PrimaryGreen.args = {
|
|
32
|
-
|
|
49
|
+
buttonClass: 'primary',
|
|
33
50
|
label: 'Primary Green',
|
|
34
|
-
color: 'green'
|
|
51
|
+
color: 'green',
|
|
52
|
+
bold: true
|
|
35
53
|
}
|
|
36
54
|
|
|
37
|
-
export const
|
|
38
|
-
|
|
39
|
-
primary: false,
|
|
55
|
+
export const SecondaryRed = Template.bind({})
|
|
56
|
+
SecondaryRed.args = {
|
|
40
57
|
label: 'Secondary Green',
|
|
41
|
-
color: '
|
|
58
|
+
color: 'red'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const TransparentWhite = Template.bind({})
|
|
62
|
+
TransparentWhite.args = {
|
|
63
|
+
buttonClass: 'transparent',
|
|
64
|
+
label: 'Secondary Green',
|
|
65
|
+
color: 'white'
|
|
42
66
|
}
|
|
43
67
|
|
|
44
68
|
export const PrimaryWithIcon = Template.bind({})
|
|
45
69
|
PrimaryWithIcon.args = {
|
|
46
|
-
|
|
70
|
+
buttonClass: 'primary',
|
|
47
71
|
label: 'Primary with Icon',
|
|
48
72
|
icon: faCheck
|
|
49
73
|
}
|
|
50
74
|
|
|
51
75
|
export const SecondaryWithIcon = Template.bind({})
|
|
52
76
|
SecondaryWithIcon.args = {
|
|
53
|
-
|
|
77
|
+
buttonClass: 'secondary',
|
|
54
78
|
label: 'Secondary with Icon',
|
|
55
|
-
icon: faCheck
|
|
56
|
-
|
|
79
|
+
icon: faCheck,
|
|
80
|
+
color: 'white'
|
|
57
81
|
}
|
|
58
82
|
|
|
59
83
|
export const PrimaryRed = Template.bind({})
|
|
60
84
|
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
|
61
85
|
PrimaryRed.args = {
|
|
62
|
-
|
|
86
|
+
buttonClass: 'primary',
|
|
63
87
|
label: 'Primary Red',
|
|
64
88
|
color: 'red'
|
|
65
89
|
}
|
|
66
90
|
|
|
67
|
-
export const SecondaryRed = Template.bind({})
|
|
68
|
-
SecondaryRed.args = {
|
|
69
|
-
primary: false,
|
|
70
|
-
label: 'Secondary Red',
|
|
71
|
-
color: 'red'
|
|
72
|
-
}
|
|
73
|
-
|
|
74
91
|
const DisabledTemplate = (args) => {
|
|
75
92
|
const [enabled, setEnabled] = useState(false)
|
|
76
93
|
return (
|
|
@@ -91,17 +108,17 @@ const DisabledTemplate = (args) => {
|
|
|
91
108
|
export const DisabledGreen = DisabledTemplate.bind({})
|
|
92
109
|
|
|
93
110
|
DisabledGreen.args = {
|
|
94
|
-
|
|
111
|
+
buttonClass: 'primary',
|
|
95
112
|
label: 'A simple button',
|
|
96
113
|
color: 'green',
|
|
97
|
-
|
|
114
|
+
disabled: true
|
|
98
115
|
}
|
|
99
116
|
|
|
100
117
|
export const DisabledRed = DisabledTemplate.bind({})
|
|
101
118
|
|
|
102
119
|
DisabledRed.args = {
|
|
103
|
-
|
|
120
|
+
buttonClass: 'primary',
|
|
104
121
|
label: 'A simple button',
|
|
105
122
|
color: 'red',
|
|
106
|
-
|
|
123
|
+
disabled: true
|
|
107
124
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
import { faStop, faRefresh } from '@fortawesome/free-solid-svg-icons'
|
|
3
|
+
import ButtonFullRounded from '../components/ButtonFullRounded'
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Platformatic/ButtonFullRounded',
|
|
7
|
+
component: ButtonFullRounded,
|
|
8
|
+
argTypes: {
|
|
9
|
+
label: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
control: 'text'
|
|
12
|
+
},
|
|
13
|
+
bold: {
|
|
14
|
+
type: 'boolean'
|
|
15
|
+
},
|
|
16
|
+
color: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
control: {
|
|
19
|
+
type: 'radio',
|
|
20
|
+
options: ['green', 'red', 'white']
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
control: {
|
|
26
|
+
type: 'radio',
|
|
27
|
+
options: ['small', 'medium', 'large']
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const Template = (args) => <ButtonFullRounded {...args} />
|
|
34
|
+
|
|
35
|
+
export const WhiteLarge = Template.bind({})
|
|
36
|
+
WhiteLarge.args = {
|
|
37
|
+
icon: faStop,
|
|
38
|
+
size: 'large'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const GreenSmall = Template.bind({})
|
|
42
|
+
GreenSmall.args = {
|
|
43
|
+
icon: faStop,
|
|
44
|
+
color: 'green',
|
|
45
|
+
size: 'small'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const Disabled = Template.bind({})
|
|
49
|
+
|
|
50
|
+
Disabled.args = {
|
|
51
|
+
icon: faRefresh,
|
|
52
|
+
disabled: true
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const DisabledRed = Template.bind({})
|
|
56
|
+
|
|
57
|
+
DisabledRed.args = {
|
|
58
|
+
icon: faRefresh,
|
|
59
|
+
color: 'red',
|
|
60
|
+
disabled: true
|
|
61
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
import Checkbox from '../components/Checkbox'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Platformatic/Checkbox',
|
|
6
|
+
component: Checkbox,
|
|
7
|
+
argTypes: {
|
|
8
|
+
id: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
control: 'text'
|
|
11
|
+
},
|
|
12
|
+
disabled: {
|
|
13
|
+
type: 'boolean'
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Template = (args) => <Checkbox {...args} />
|
|
19
|
+
|
|
20
|
+
export const CheckboxRegular = Template.bind({})
|
|
21
|
+
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
|
22
|
+
CheckboxRegular.args = {}
|
|
23
|
+
|
|
24
|
+
export const CheckboxDisabled = Template.bind({})
|
|
25
|
+
CheckboxDisabled.args = {
|
|
26
|
+
disabled: true
|
|
27
|
+
}
|
|
@@ -6,17 +6,39 @@ import DropDown from '../components/DropDown'
|
|
|
6
6
|
import HorizontalSeparator from '../components/HorizontalSeparator'
|
|
7
7
|
export default {
|
|
8
8
|
title: 'Platformatic/Modal',
|
|
9
|
-
component: Modal
|
|
9
|
+
component: Modal,
|
|
10
|
+
argTypes: {
|
|
11
|
+
layout: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
control: {
|
|
14
|
+
type: 'radio',
|
|
15
|
+
options: ['info', 'invite']
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
10
19
|
}
|
|
11
20
|
|
|
12
21
|
const Template = (args) => {
|
|
22
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
23
|
+
const { text, ...rest } = args
|
|
24
|
+
return (
|
|
25
|
+
<main>
|
|
26
|
+
<BorderedBox>This Is another Content</BorderedBox>
|
|
27
|
+
<ContentThatLoads />
|
|
28
|
+
<Button color='green' buttonClass='primary' onClick={() => setIsOpen(true)} label='Open Modal' />
|
|
29
|
+
{isOpen && <Modal setIsOpen={setIsOpen} {...rest}>{text}</Modal>}
|
|
30
|
+
</main>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const TemplateInvite = (args) => {
|
|
13
35
|
const [isOpen, setIsOpen] = useState(false)
|
|
14
36
|
return (
|
|
15
37
|
<main>
|
|
16
38
|
<BorderedBox>This Is another Content</BorderedBox>
|
|
17
39
|
<ContentThatLoads />
|
|
18
|
-
<Button color='green'
|
|
19
|
-
{isOpen && <Modal setIsOpen={setIsOpen}
|
|
40
|
+
<Button color='green' buttonClass='primary' onClick={() => setIsOpen(true)} label='Open Modal' />
|
|
41
|
+
{isOpen && <Modal setIsOpen={setIsOpen} {...args}><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed</p><Button buttonClass='primary' onClick={() => setIsOpen(false)} label='Discard invite' /></Modal>}
|
|
20
42
|
</main>
|
|
21
43
|
)
|
|
22
44
|
}
|
|
@@ -33,7 +55,8 @@ const ContentThatLoads = () => {
|
|
|
33
55
|
export const Default = Template.bind({})
|
|
34
56
|
Default.args = {
|
|
35
57
|
title: 'List Title',
|
|
36
|
-
text: 'Hello World'
|
|
58
|
+
text: 'Hello World',
|
|
59
|
+
layout: 'info'
|
|
37
60
|
}
|
|
38
61
|
|
|
39
62
|
export const WithLongText = Template.bind({})
|
|
@@ -63,3 +86,9 @@ const MenuTemplate = () => {
|
|
|
63
86
|
)
|
|
64
87
|
}
|
|
65
88
|
export const WithDropDown = MenuTemplate.bind({})
|
|
89
|
+
|
|
90
|
+
export const InviteLayout = TemplateInvite.bind({})
|
|
91
|
+
InviteLayout.args = {
|
|
92
|
+
title: 'Give me an invite',
|
|
93
|
+
layout: 'invite'
|
|
94
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PullRequestIcon from '../../components/icons/PullRequestIcon'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Platformatic/Icons',
|
|
6
|
+
component: PullRequestIcon,
|
|
7
|
+
argTypes: {
|
|
8
|
+
color: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
control: {
|
|
11
|
+
type: 'radio',
|
|
12
|
+
options: ['green', 'white', 'red']
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Template = (args) => <PullRequestIcon {...args} />
|
|
19
|
+
export const PullRequestIconDefault = Template.bind({})
|
|
20
|
+
PullRequestIconDefault.args = {}
|
package/tailwind.config.cjs
CHANGED
|
@@ -9,7 +9,10 @@ module.exports = {
|
|
|
9
9
|
screens: {
|
|
10
10
|
'lg': '1440px',
|
|
11
11
|
// => @media (min-width: 1440px) { ... }
|
|
12
|
-
},
|
|
12
|
+
},
|
|
13
|
+
boxShadow: {
|
|
14
|
+
'wrap': '0px 0px 20px rgba(0, 0, 0, 0.6)'
|
|
15
|
+
}
|
|
13
16
|
},
|
|
14
17
|
colors: {
|
|
15
18
|
'main-green': '#21FA90',
|
|
@@ -17,9 +20,11 @@ module.exports = {
|
|
|
17
20
|
'light-green': '#21F190',
|
|
18
21
|
'main-dark-blue': '#00283D',
|
|
19
22
|
'dark-blue': '#00344F',
|
|
23
|
+
'light-blue': '#E9F7FF',
|
|
20
24
|
white: '#FFFFFF',
|
|
21
25
|
'error-red': '#FA2121',
|
|
22
|
-
'tertiary-blue': '#2588E4'
|
|
26
|
+
'tertiary-blue': '#2588E4',
|
|
27
|
+
'transparent': 'transparent'
|
|
23
28
|
},
|
|
24
29
|
fontFamily: {
|
|
25
30
|
sans: ['Montserrat']
|