@platformatic/ui-components 0.1.35 → 0.1.36
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/dist/main.css +4 -0
- package/index.js +2 -0
- package/package.json +1 -1
- package/src/components/BorderedText.module.css +1 -1
- package/src/components/DropDown.jsx +4 -3
- package/src/components/DropDown.module.css +5 -2
- package/src/components/FollowUs.module.css +1 -1
- package/src/components/SideBar.jsx +61 -0
- package/src/components/SideBar.module.css +43 -0
- package/src/components/TabbedWindow.module.css +1 -1
- package/src/components/icons/Icons.module.css +7 -3
- package/src/components/icons/PuzzleIcon.jsx +65 -0
- package/src/stories/SideBar.stories.jsx +55 -0
- package/tailwind.config.cjs +10 -0
package/dist/main.css
CHANGED
|
@@ -586,6 +586,10 @@ video {
|
|
|
586
586
|
flex-grow: 1;
|
|
587
587
|
}
|
|
588
588
|
|
|
589
|
+
.transform {
|
|
590
|
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
591
|
+
}
|
|
592
|
+
|
|
589
593
|
.flex-col {
|
|
590
594
|
flex-direction: column;
|
|
591
595
|
}
|
package/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import GHLoginButton from './src/components/GHLoginButton'
|
|
|
13
13
|
import HorizontalSeparator from './src/components/HorizontalSeparator'
|
|
14
14
|
import Icons from './src/components/icons'
|
|
15
15
|
import Input from './src/components/Input'
|
|
16
|
+
import Sidebar from './src/components/Sidebar'
|
|
16
17
|
import Layout from './src/components/layouts/Layout'
|
|
17
18
|
import List from './src/components/List'
|
|
18
19
|
import ListElement from './src/components/ListElement'
|
|
@@ -43,6 +44,7 @@ export {
|
|
|
43
44
|
GHLoginButton,
|
|
44
45
|
Icons,
|
|
45
46
|
Input,
|
|
47
|
+
Sidebar,
|
|
46
48
|
Layout,
|
|
47
49
|
List,
|
|
48
50
|
ListElement,
|
package/package.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
import React, { useState } from 'react'
|
|
4
4
|
import styles from './DropDown.module.css'
|
|
5
5
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
6
|
-
import {
|
|
6
|
+
import { faChevronRight, faChevronDown } from '@fortawesome/free-solid-svg-icons'
|
|
7
7
|
export default function DropDown (props) {
|
|
8
|
-
const { header, items, align = 'left' } = props
|
|
8
|
+
const { pictureUrl, header, items, align = 'left' } = props
|
|
9
9
|
const [open, setOpen] = useState(false)
|
|
10
10
|
function handleOpen () {
|
|
11
11
|
setOpen(!open)
|
|
@@ -13,8 +13,9 @@ export default function DropDown (props) {
|
|
|
13
13
|
return (
|
|
14
14
|
<div className={`${styles.dropDown} ${styles[align]}`}>
|
|
15
15
|
<span className={styles.header} onClick={handleOpen}>
|
|
16
|
+
{pictureUrl && <img src={pictureUrl} height={32} width={32} className={styles.picture} />}
|
|
16
17
|
{header}
|
|
17
|
-
{!open && <FontAwesomeIcon className={styles.arrow} icon={
|
|
18
|
+
{!open && <FontAwesomeIcon className={styles.arrow} icon={faChevronRight} />}
|
|
18
19
|
{open && <FontAwesomeIcon className={styles.arrow} icon={faChevronDown} />}
|
|
19
20
|
</span>
|
|
20
21
|
{open && (
|
|
@@ -13,13 +13,16 @@
|
|
|
13
13
|
@apply absolute top-[50%] right-0 translate-y-[-50%];
|
|
14
14
|
}
|
|
15
15
|
.header {
|
|
16
|
-
@apply hover:cursor-pointer relative pr-6;
|
|
16
|
+
@apply flex items-center hover:cursor-pointer relative pr-6 tracking-more-widest uppercase text-sm font-normal;
|
|
17
|
+
}
|
|
18
|
+
.picture {
|
|
19
|
+
@apply border border-transparent rounded-full mr-2;
|
|
17
20
|
}
|
|
18
21
|
.menu {
|
|
19
22
|
@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
23
|
}
|
|
21
24
|
.item {
|
|
22
|
-
@apply py-3 px-3 text-main-dark-blue first:border-t-0 text-sm uppercase hover:font-semibold hover:cursor-pointer tracking-
|
|
25
|
+
@apply py-3 px-3 text-main-dark-blue first:border-t-0 text-sm uppercase hover:font-semibold hover:cursor-pointer tracking-more-widest;
|
|
23
26
|
/* it's a workaround due to opacity... */
|
|
24
27
|
border-top: 1px solid rgba(0, 40, 61, 0.2);;
|
|
25
28
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import PuzzleIcon from './icons/PuzzleIcon'
|
|
3
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
4
|
+
import { faChevronLeft, faPlus } from '@fortawesome/free-solid-svg-icons'
|
|
5
|
+
import styles from './Sidebar.module.css'
|
|
6
|
+
import ReactTooltip from 'react-tooltip'
|
|
7
|
+
import HorizontalSeparator from './HorizontalSeparator'
|
|
8
|
+
export default function Sidebar (props) {
|
|
9
|
+
const { title, defaultSelected = 0, onClickItemSelectedParent = () => {}, items = [], onClickAdd = () => {}, addTitle = 'Add' } = props
|
|
10
|
+
const [collapsed, setCollapsed] = useState(false)
|
|
11
|
+
const [selectedItem, setSelectedItem] = useState(defaultSelected)
|
|
12
|
+
|
|
13
|
+
function onClickItemSelected (index) {
|
|
14
|
+
setSelectedItem(index)
|
|
15
|
+
onClickItemSelectedParent(index)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className={`${styles.container} ${collapsed && styles.collapsed}`}>
|
|
20
|
+
{collapsed
|
|
21
|
+
? (
|
|
22
|
+
<>
|
|
23
|
+
<button type='button' className={styles.buttonPuzzle} onClick={() => { setCollapsed(false) }}>
|
|
24
|
+
<PuzzleIcon tip='expand' />
|
|
25
|
+
</button>
|
|
26
|
+
<ReactTooltip />
|
|
27
|
+
</>
|
|
28
|
+
)
|
|
29
|
+
: (
|
|
30
|
+
<>
|
|
31
|
+
<button type='button' className={styles.buttonCollapse} onClick={() => { setCollapsed(true) }}>
|
|
32
|
+
<FontAwesomeIcon icon={faChevronLeft} size='1x' color='white' />
|
|
33
|
+
</button>
|
|
34
|
+
<div className={styles.title} data-testid='lateral-bar-title'>
|
|
35
|
+
{title}
|
|
36
|
+
</div>
|
|
37
|
+
<div className={styles.items} data-test-id='lateral-bar-items'>
|
|
38
|
+
{items.map((item, index) => {
|
|
39
|
+
const isSelected = selectedItem === index
|
|
40
|
+
return (
|
|
41
|
+
<React.Fragment key={index}>
|
|
42
|
+
<button className={`${styles.buttonItem} ${collapsed && styles.buttonItemCollapsed}`} type='button' onClick={() => onClickItemSelected(index)}>
|
|
43
|
+
<PuzzleIcon size='small' color={isSelected ? 'green' : 'white'} tip={item} />
|
|
44
|
+
<span className={`${styles.item} ${isSelected ? styles.itemSelected : ''}`}>{item}</span>
|
|
45
|
+
</button>
|
|
46
|
+
<ReactTooltip />
|
|
47
|
+
</React.Fragment>
|
|
48
|
+
)
|
|
49
|
+
})}
|
|
50
|
+
{/* <Button label='Add' buttonClass='transparent' icon={faPlus} color='white' size='small' inClick={onClickAdd}/> */}
|
|
51
|
+
<button className={`${styles.buttonItem} ${collapsed && styles.buttonItemCollapsed}`} onClick={onClickAdd}>
|
|
52
|
+
<FontAwesomeIcon color='white' icon={faPlus} data-tip={addTitle} />
|
|
53
|
+
{!collapsed && <span className={styles.item}>{addTitle}</span>}
|
|
54
|
+
</button>
|
|
55
|
+
</div>
|
|
56
|
+
</>
|
|
57
|
+
)}
|
|
58
|
+
<HorizontalSeparator marginBottom={2} marginTop={2} />
|
|
59
|
+
</div>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
@apply max-w-[216px] w-full p-4 border border-white rounded-md h-auto relative;
|
|
3
|
+
transition: max-width 0.2s linear;
|
|
4
|
+
}
|
|
5
|
+
.collapsed {
|
|
6
|
+
@apply max-w-[96px] text-center;
|
|
7
|
+
}
|
|
8
|
+
.buttonPuzzle {
|
|
9
|
+
@apply border-0;
|
|
10
|
+
}
|
|
11
|
+
.buttonCollapse {
|
|
12
|
+
@apply absolute border border-white rounded-full h-6 w-6 right-[-0.875rem];
|
|
13
|
+
/* Override tailwind dist button[type='button]: background: transparent*/
|
|
14
|
+
@apply bg-main-dark-blue !important;
|
|
15
|
+
top: 1rem;
|
|
16
|
+
}
|
|
17
|
+
.title {
|
|
18
|
+
@apply text-white font-bold py-3;
|
|
19
|
+
}
|
|
20
|
+
.buttonItem {
|
|
21
|
+
@apply flex items-center border-0 w-full mx-auto;
|
|
22
|
+
}
|
|
23
|
+
.buttonItemCollapsed {
|
|
24
|
+
@apply w-auto
|
|
25
|
+
}
|
|
26
|
+
.item {
|
|
27
|
+
@apply text-sm text-white ml-2 grow-0;
|
|
28
|
+
}
|
|
29
|
+
.itemSelected {
|
|
30
|
+
@apply text-light-green;
|
|
31
|
+
}
|
|
32
|
+
.items {
|
|
33
|
+
@apply flex flex-col gap-y-3 py-2;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@keyframes fadeIn {
|
|
37
|
+
0% {
|
|
38
|
+
opacity: 0;
|
|
39
|
+
}
|
|
40
|
+
100% {
|
|
41
|
+
opacity: 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
.tabs-header {
|
|
6
|
-
@apply flex justify-start text-white uppercase hover:cursor-pointer mb-4 tracking-
|
|
6
|
+
@apply flex justify-start text-white uppercase hover:cursor-pointer mb-4 tracking-super-widest h-[2rem];
|
|
7
7
|
}
|
|
8
8
|
.tab {
|
|
9
9
|
@apply mx-8 min-w-[105px] text-center text-sm first:ml-0 last:mr-0;
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
.green > circle,
|
|
2
2
|
.green > rect,
|
|
3
3
|
.green > path {
|
|
4
|
-
|
|
4
|
+
@apply stroke-main-green;
|
|
5
5
|
}
|
|
6
6
|
.red > circle,
|
|
7
7
|
.red > rect,
|
|
8
8
|
.red > path {
|
|
9
|
-
|
|
9
|
+
@apply stroke-error-red;
|
|
10
10
|
}
|
|
11
11
|
.white > circle,
|
|
12
12
|
.white > rect,
|
|
13
13
|
.white > path {
|
|
14
|
-
|
|
14
|
+
@apply stroke-white;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.noShrinkForFlex {
|
|
18
|
+
@apply shrink-0
|
|
15
19
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import styles from './Icons.module.css'
|
|
3
|
+
const PuzzleIcon = ({ color = 'green', size = 'normal', tip = '' }) => {
|
|
4
|
+
const className = `${styles.noShrinkForFlex} ` + styles[`${color}`]
|
|
5
|
+
let dimension = 40
|
|
6
|
+
switch (size) {
|
|
7
|
+
case 'small':
|
|
8
|
+
dimension = 24
|
|
9
|
+
break
|
|
10
|
+
default:
|
|
11
|
+
break
|
|
12
|
+
}
|
|
13
|
+
return (
|
|
14
|
+
<svg
|
|
15
|
+
width={dimension}
|
|
16
|
+
height={dimension}
|
|
17
|
+
viewBox='0 0 40 40'
|
|
18
|
+
fill='none'
|
|
19
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
20
|
+
className={className}
|
|
21
|
+
data-tip={tip}
|
|
22
|
+
>
|
|
23
|
+
<rect
|
|
24
|
+
x={5}
|
|
25
|
+
y={5}
|
|
26
|
+
width={10}
|
|
27
|
+
height={12.5874}
|
|
28
|
+
rx={1}
|
|
29
|
+
stroke='none'
|
|
30
|
+
strokeWidth={1.5}
|
|
31
|
+
/>
|
|
32
|
+
<rect
|
|
33
|
+
x={20}
|
|
34
|
+
y={5}
|
|
35
|
+
width={15}
|
|
36
|
+
height={12.5874}
|
|
37
|
+
rx={1}
|
|
38
|
+
stroke='none'
|
|
39
|
+
strokeWidth={1.5}
|
|
40
|
+
/>
|
|
41
|
+
<rect
|
|
42
|
+
x={35}
|
|
43
|
+
y={35}
|
|
44
|
+
width={10}
|
|
45
|
+
height={12.5874}
|
|
46
|
+
rx={1}
|
|
47
|
+
transform='rotate(-180 35 35)'
|
|
48
|
+
stroke='none'
|
|
49
|
+
strokeWidth={1.5}
|
|
50
|
+
/>
|
|
51
|
+
<rect
|
|
52
|
+
x={20}
|
|
53
|
+
y={35}
|
|
54
|
+
width={15}
|
|
55
|
+
height={12.5874}
|
|
56
|
+
rx={1}
|
|
57
|
+
transform='rotate(-180 20 35)'
|
|
58
|
+
stroke='none'
|
|
59
|
+
strokeWidth={1.5}
|
|
60
|
+
/>
|
|
61
|
+
</svg>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default PuzzleIcon
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
import Sidebar from '../components/Sidebar'
|
|
4
|
+
import BorderedBox from '../components/BorderedBox'
|
|
5
|
+
|
|
6
|
+
const divStyle = {
|
|
7
|
+
display: 'flex',
|
|
8
|
+
width: '100%',
|
|
9
|
+
minHeight: '400px',
|
|
10
|
+
gap: '10px'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
title: 'Platformatic/Sidebar',
|
|
15
|
+
component: Sidebar,
|
|
16
|
+
decorators: [
|
|
17
|
+
(Story) => (
|
|
18
|
+
<div style={divStyle}>
|
|
19
|
+
<Story />
|
|
20
|
+
<BorderedBox>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</BorderedBox>
|
|
21
|
+
</div>
|
|
22
|
+
)
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const Template = (args) => <Sidebar {...args} />
|
|
27
|
+
|
|
28
|
+
export const EmptySidebar = Template.bind({})
|
|
29
|
+
|
|
30
|
+
EmptySidebar.args = {
|
|
31
|
+
title: 'Sidebar bar empty',
|
|
32
|
+
addTitle: 'Create',
|
|
33
|
+
onClickAdd: () => alert('clicked on add EmptySidebar')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const FullSidebarTemplate = (args) => {
|
|
37
|
+
const [items, setItems] = useState(['a very very very very very long title 1', 'Title number 2'])
|
|
38
|
+
function onClickAdd () {
|
|
39
|
+
const tmpItem = items.map(item => item)
|
|
40
|
+
tmpItem.push('Title number ' + (items.length + 1))
|
|
41
|
+
setItems(tmpItem)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Sidebar items={items} onClickAdd={() => onClickAdd()} {...args} />
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const FullSidebar = FullSidebarTemplate.bind({})
|
|
50
|
+
|
|
51
|
+
FullSidebar.args = {
|
|
52
|
+
title: 'Sidebar bar Full',
|
|
53
|
+
addTitle: 'Create',
|
|
54
|
+
onClickItemSelected: (index) => alert('selected: ' + index)
|
|
55
|
+
}
|
package/tailwind.config.cjs
CHANGED
|
@@ -28,6 +28,16 @@ module.exports = {
|
|
|
28
28
|
},
|
|
29
29
|
fontFamily: {
|
|
30
30
|
sans: ['Montserrat']
|
|
31
|
+
},
|
|
32
|
+
letterSpacing: {
|
|
33
|
+
tighter: '-.05em',
|
|
34
|
+
tight: '-.025em',
|
|
35
|
+
normal: '0',
|
|
36
|
+
wide: '.025em',
|
|
37
|
+
wider: '.05em',
|
|
38
|
+
widest: '.1em',
|
|
39
|
+
'more-widest': '.15em',
|
|
40
|
+
'super-widest': '.25em',
|
|
31
41
|
}
|
|
32
42
|
},
|
|
33
43
|
safelist: [
|