Skip to content
This repository was archived by the owner on Mar 17, 2023. It is now read-only.

Commit 92294eb

Browse files
author
Roland Peelen
authored
Merge pull request #81
Tabs
2 parents 72c418f + a8c9197 commit 92294eb

19 files changed

+1370
-199
lines changed

CHANGELOG.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,14 @@ Every entry has a category for which we use the following visual abbreviations:
1111
- ⚡️ Breaking Change
1212
- 🐞 Bugfix
1313

14+
## [0.12.0]
15+
- 🎁 Tabs [#81](https://github.com/tenzir/ui-component-library/pull/81)
16+
We now have a tabs, and tabbed card component. They have built-in support for
17+
drag'n'drop replacing, updating, adding, duplicating and removing. Depending
18+
on which callback functions are supplied they're activated.
19+
1420
## [0.10.0]
15-
- 🎁 Sizing [#69](https://github.com/tenzir/ui-component-library/pull/71)
21+
- 🎁 Sizing [#71](https://github.com/tenzir/ui-component-library/pull/71)
1622
We now support sizes (`small` / `medium` / `large`) for buttons and alerts
1723

1824
## [0.9.0]

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ contribution ([Contributing Guidelines][contributing-url]) in these cases.
3030
### Components
3131
The following components are currently built.
3232
- Button
33-
- Card
33+
- Card (optionally with a tabbed header)
3434
- Checkbox
3535
- Icons - A script generates bindings for [React
3636
Icons](https://github.com/react-icons/react-icons). We currently generate
@@ -45,6 +45,7 @@ The following components are currently built.
4545
- Segment
4646
- Notifications
4747
- Slider
48+
- Tabs
4849

4950
Preview here: [Tenzir-Ui-Component-Library][storybook-url]
5051

bsconfig.json

+36-36
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
11
{
2-
"name": "tenzir-ui-component-library",
3-
"reason": {
4-
"react-jsx": 3
5-
},
6-
"sources": [
7-
{
8-
"dir": "src",
9-
"subdirs": true
10-
},
11-
{
12-
"dir": "__tests__",
13-
"type": "dev"
14-
}
15-
],
16-
"bsc-flags": ["-bs-super-errors", "-bs-no-version-header"],
17-
"warnings": {
18-
"number": "+A-4-41-48-102-107",
19-
"error": "+A-3-44-102-103"
20-
},
21-
"package-specs": [
22-
{
23-
"module": "es6-global",
24-
"in-source": true
25-
}
26-
],
27-
"suffix": ".bs.js",
28-
"namespace": true,
29-
"bs-dependencies": [
30-
"bs-flexboxgrid",
31-
"bs-webapi",
32-
"reason-react",
33-
"bs-css",
34-
"bs-css-emotion"
35-
],
36-
"bs-dev-dependencies": ["@glennsl/bs-jest"],
37-
"refmt": 3
2+
"name": "tenzir-ui-component-library",
3+
"reason": {
4+
"react-jsx": 3
5+
},
6+
"sources": [
7+
{
8+
"dir": "src",
9+
"subdirs": true
10+
},
11+
{
12+
"dir": "__tests__",
13+
"type": "dev"
14+
}
15+
],
16+
"bsc-flags": ["-bs-super-errors", "-bs-no-version-header"],
17+
"warnings": {
18+
"number": "+A-4-41-48-102-107",
19+
"error": "+A-3-44-102-103"
20+
},
21+
"package-specs": [
22+
{
23+
"module": "es6-global",
24+
"in-source": true
25+
}
26+
],
27+
"suffix": ".bs.js",
28+
"namespace": true,
29+
"bs-dependencies": [
30+
"bs-flexboxgrid",
31+
"bs-webapi",
32+
"reason-react",
33+
"bs-css",
34+
"bs-css-emotion"
35+
],
36+
"bs-dev-dependencies": ["@glennsl/bs-jest"],
37+
"refmt": 3
3838
}

package.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "tenzir-ui-component-library",
33
"author": "Tenzir",
4-
"version": "0.11.0",
4+
"version": "0.12.0",
55
"scripts": {
66
"build:reason": "bsb -clean-world && bsb -make-world",
77
"build:storybook": "build-storybook",
@@ -35,6 +35,7 @@
3535
"bs-css-emotion": "^3.0.0",
3636
"bs-flexboxgrid": "^3.0.0",
3737
"bs-webapi": "^0.19.1",
38+
"react-beautiful-dnd": "^13.1.0",
3839
"react-icons": "^4.2.0",
3940
"react-syntax-highlighter": "^15.4.4",
4041
"storybook-dark-mode": "^1.0.8"
@@ -43,10 +44,8 @@
4344
"@babel/core": "^7.14.3",
4445
"@glennsl/bs-jest": "^0.7.0",
4546
"@storybook/addon-actions": "^6.3.6",
46-
"@storybook/addon-postcss": "^2.0.0",
47-
"autoprefixer": "^10.3.1",
48-
"postcss-flexbugs-fixes": "^5.0.2",
4947
"@storybook/addon-links": "^6.3.6",
48+
"@storybook/addon-postcss": "^2.0.0",
5049
"@storybook/addons": "^6.3.6",
5150
"@storybook/api": "^6.3.6",
5251
"@storybook/components": "^6.3.6",
@@ -55,11 +54,13 @@
5554
"@storybook/react": "^6.3.6",
5655
"@storybook/storybook-deployer": "^2.8.10",
5756
"@storybook/theming": "^6.3.6",
57+
"autoprefixer": "^10.3.1",
5858
"babel-loader": "^8.2.2",
5959
"bs-platform": "^9.0.2",
6060
"html-webpack-plugin": "^5.3.2",
6161
"husky": "^4.3.8",
6262
"lint-staged": "^10.4.2",
63+
"postcss-flexbugs-fixes": "^5.0.2",
6364
"prettier": "^2.3.2",
6465
"react": "17.0.2",
6566
"react-dom": "17.0.2",

src/Card.re

+55-12
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,11 @@ let make =
1212
~header=?,
1313
~footer=?,
1414
~children=<Empty />,
15-
~styles=?,
1615
) => {
17-
switch (styles) {
18-
| Some(_) =>
19-
Js.log(
20-
"*Deprecated* - Adding styles this way will be removed in favour of a custom classname",
21-
)
22-
| None => ()
23-
};
24-
2516
<div
2617
?onMouseOver
2718
?onMouseOut
28-
className={
29-
className ++ " " ++ card(~spacing, ~theme, ~depth, ~styles, ()) ++ " "
30-
}>
19+
className={className ++ " " ++ card(~spacing, ~theme, ~depth, ()) ++ " "}>
3120
{header->Belt.Option.mapWithDefault(<Empty />, header =>
3221
<div className={cardHeader(~theme, ~depth, ())}> header </div>
3322
)}
@@ -43,3 +32,57 @@ let make =
4332
)}
4433
</div>;
4534
};
35+
36+
module Tabbed = {
37+
[@react.component]
38+
let make =
39+
(
40+
~onMouseOver=?,
41+
~onMouseOut=?,
42+
~spacing=Normal,
43+
~theme=Config.defaultTheme,
44+
~depth=1,
45+
~className="",
46+
~footer=?,
47+
~children=<Empty />,
48+
~activeTabId: string,
49+
~tabs: array(Tabs.t),
50+
~onAdd=?,
51+
~onMove=?,
52+
~onOpen=?,
53+
~onClose=?,
54+
~onDuplicate=?,
55+
~onRename=?,
56+
) => {
57+
<div
58+
?onMouseOver
59+
?onMouseOut
60+
className={
61+
className ++ " " ++ card(~spacing, ~theme, ~depth, ()) ++ " "
62+
}>
63+
<Tabs
64+
standalone=false
65+
tabs
66+
activeTabId
67+
theme
68+
depth
69+
?onAdd
70+
?onMove
71+
?onOpen
72+
?onClose
73+
?onDuplicate
74+
?onRename
75+
/>
76+
<div
77+
className={cardContent(
78+
~hasHeader=true,
79+
~hasFooter=footer->Belt.Option.isSome,
80+
)}>
81+
children
82+
</div>
83+
{footer->Belt.Option.mapWithDefault(<Empty />, footer =>
84+
<div className={cardFooter(~theme, ~depth, ())}> footer </div>
85+
)}
86+
</div>;
87+
};
88+
};

src/CardStyles.re

+1-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ let deteriminePadding = spacing => {
2222
};
2323
};
2424

25-
let card = (~theme, ~spacing=Normal, ~depth, ~styles, ()) => {
25+
let card = (~theme, ~spacing=Normal, ~depth, ()) => {
2626
let colors = StyleHelpers.colorsFromThemeVariant(theme);
27-
let extraStyles = Belt.Option.getWithDefault(styles, []);
2827
style([
2928
width(100.0->pct),
3029
height(100.0->pct),
@@ -39,7 +38,6 @@ let card = (~theme, ~spacing=Normal, ~depth, ~styles, ()) => {
3938
borderRadius(Misc.borderRadius),
4039
deteriminePadding(spacing),
4140
position(`relative),
42-
...extraStyles,
4341
]);
4442
};
4543

src/Dnd.js

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import React from 'react'
2+
import { Droppable } from 'react-beautiful-dnd'
3+
import { Draggable } from 'react-beautiful-dnd'
4+
5+
const Provided = ({ provided, innerRef, children }) => {
6+
const augmentedChildren = {
7+
...children,
8+
ref: innerRef,
9+
props: {
10+
...children.props,
11+
...provided.draggableProps,
12+
...provided.dragHandleProps,
13+
},
14+
}
15+
return (
16+
<>
17+
{augmentedChildren}
18+
{provided.placeholder}
19+
</>
20+
)
21+
}
22+
23+
export const DroppableWrapper = ({ direction, droppableId, children }) => {
24+
const ref = React.useRef()
25+
return (
26+
<Droppable droppableId={droppableId} direction={direction}>
27+
{(provided) => {
28+
return (
29+
<Provided provided={provided} innerRef={provided.innerRef}>
30+
{children}
31+
</Provided>
32+
)
33+
}}
34+
</Droppable>
35+
)
36+
}
37+
38+
export const DraggableWrapper = ({
39+
index,
40+
isDragDisabled,
41+
draggableId,
42+
children,
43+
}) => {
44+
const ref = React.useRef()
45+
return (
46+
<Draggable
47+
draggableId={draggableId}
48+
isDragDisabled={isDragDisabled}
49+
index={index}
50+
>
51+
{(provided) => {
52+
return (
53+
<Provided provided={provided} innerRef={provided.innerRef}>
54+
{children}
55+
</Provided>
56+
)
57+
}}
58+
</Draggable>
59+
)
60+
}

src/Dnd.re

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module Context = {
2+
type dragItem = {
3+
droppableId: string,
4+
index: int,
5+
};
6+
type dragEndEvent = {
7+
destination: Js.Nullable.t(dragItem),
8+
source: dragItem,
9+
/*combine: Js.Nullable.t(combine),*/
10+
/*draggableId: string,*/
11+
/*mode: string,*/
12+
/*reason: string,*/
13+
/*type_: string*/
14+
};
15+
type dragStartEvent = {
16+
source: dragItem,
17+
/*combine: Js.Nullable.t(combine),*/
18+
/*draggableId: string,*/
19+
/*mode: string,*/
20+
/*reason: string,*/
21+
/*type_: string*/
22+
};
23+
24+
[@bs.module "react-beautiful-dnd"] [@react.component]
25+
external make:
26+
(
27+
~onDragStart: dragStartEvent => unit=?,
28+
~onDragUpdate: ReactEvent.Synthetic.t => unit=?,
29+
~onDragEnd: dragEndEvent => unit,
30+
~children: React.element=?
31+
) =>
32+
React.element =
33+
"DragDropContext";
34+
};
35+
36+
module Draggable = {
37+
[@bs.module "./Dnd.js"] [@react.component]
38+
external make:
39+
(
40+
~isDragDisabled: bool=?,
41+
~draggableId: string,
42+
~index: int,
43+
~children: React.element=?
44+
) =>
45+
React.element =
46+
"DraggableWrapper";
47+
};
48+
49+
module Droppable = {
50+
type direction = [ | `vertical | `horizontal];
51+
[@bs.module "./Dnd.js"] [@react.component]
52+
external make:
53+
(
54+
~droppableId: string,
55+
~direction: direction=?,
56+
~children: React.element=?
57+
) =>
58+
React.element =
59+
"DroppableWrapper";
60+
};

src/Helpers/Function.re

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

src/Helpers/StyleHelpers.re

+13
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ let applyPercentageToColor =
4040
let lighten = applyPercentageToColor(Lighten);
4141
let darken = applyPercentageToColor(Darken);
4242

43+
let offsetBgColorFlt = (theme, depth: float, color) => {
44+
(
45+
switch (theme) {
46+
| UiTypes.Dark
47+
| UiTypes.TenzirBlue =>
48+
float_of_int(Misc.cardDarkeningPct) *. (depth *. (-1.) -. 1.)
49+
| _ => float_of_int(Misc.cardDarkeningPct) *. depth
50+
}
51+
)
52+
->int_of_float
53+
->darken(color);
54+
};
55+
4356
let offsetBgColor = (theme, depth, color) => {
4457
(
4558
switch (theme) {

0 commit comments

Comments
 (0)