Skip to content

Commit 52f3801

Browse files
committed
Moved tabler compoments into this project for more control
1 parent 5ad5ad4 commit 52f3801

37 files changed

+1247
-12883
lines changed

frontend/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"@typescript-eslint/eslint-plugin": "^4.28.1",
1717
"@typescript-eslint/parser": "^4.28.1",
1818
"babel-eslint": "^10.1.0",
19+
"classnames": "^2.3.1",
1920
"date-fns": "2.22.1",
2021
"eslint": "^7.30.0",
2122
"eslint-config-prettier": "^8.3.0",
@@ -46,8 +47,6 @@
4647
"rooks": "5.0.2",
4748
"styled-components": "5.3.0",
4849
"tabler-icons-react": "^1.35.0",
49-
"tabler-react": "^2.0.0-alpha.1",
50-
"tabler-react-typescript": "0.0.5",
5150
"typescript": "^4.3.5"
5251
},
5352
"scripts": {
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import React, { ReactNode, useState } from "react";
2+
3+
import cn from "classnames";
4+
5+
import { AlertLink } from "./AlertLink";
6+
7+
export interface AlertProps {
8+
/**
9+
* Child elements within
10+
*/
11+
children?: ReactNode;
12+
/**
13+
* Additional Class
14+
*/
15+
className?: string;
16+
/**
17+
* The type of this Alert, changes it's color
18+
*/
19+
type?: "info" | "success" | "warning" | "danger";
20+
/**
21+
* Alert Title
22+
*/
23+
title?: string;
24+
/**
25+
* An Icon to be displayed on the right hand side of the Alert
26+
*/
27+
icon?: ReactNode;
28+
/**
29+
* Display an Avatar on the left hand side of this Alert
30+
*/
31+
avatar?: ReactNode;
32+
/**
33+
*
34+
*/
35+
important?: boolean;
36+
/**
37+
* Adds an 'X' to the right side of the Alert that dismisses the Alert
38+
*/
39+
dismissable?: boolean;
40+
/**
41+
* Event to call after dissmissing
42+
*/
43+
onDismissClick?: React.MouseEventHandler<HTMLButtonElement>;
44+
}
45+
export const Alert: React.FC<AlertProps> = ({
46+
children,
47+
className,
48+
type = "info",
49+
title,
50+
icon,
51+
avatar,
52+
important = false,
53+
dismissable = false,
54+
onDismissClick,
55+
}) => {
56+
const [dismissed, setDismissed] = useState(false);
57+
58+
const classes = {
59+
"alert-dismissible": dismissable,
60+
"alert-important": important,
61+
};
62+
63+
const handleDismissed = (
64+
e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
65+
) => {
66+
setDismissed(true);
67+
onDismissClick && onDismissClick(e);
68+
};
69+
70+
const wrappedTitle = title ? <h4 className="alert-title">{title}</h4> : null;
71+
const wrappedChildren =
72+
children && !important ? (
73+
<div className="text-muted">{children}</div>
74+
) : (
75+
children
76+
);
77+
78+
const wrapIfIcon = (): ReactNode => {
79+
if (avatar) {
80+
return (
81+
<div className="d-flex">
82+
<div>
83+
<span className="float-start me-3">{avatar}</span>
84+
</div>
85+
<div>{wrappedChildren}</div>
86+
</div>
87+
);
88+
}
89+
if (icon) {
90+
return (
91+
<div className="d-flex">
92+
<div>
93+
<span className="alert-icon">{icon}</span>
94+
</div>
95+
<div>
96+
{wrappedTitle}
97+
{wrappedChildren}
98+
</div>
99+
</div>
100+
);
101+
}
102+
return (
103+
<>
104+
{wrappedTitle}
105+
{wrappedChildren}
106+
</>
107+
);
108+
};
109+
110+
if (!dismissed) {
111+
return (
112+
<div
113+
className={cn("alert", `alert-${type}`, classes, className)}
114+
role="alert">
115+
{wrapIfIcon()}
116+
{dismissable ? (
117+
<button
118+
className="btn-close"
119+
data-bs-dismiss="alert"
120+
aria-label="close"
121+
onClick={handleDismissed}
122+
/>
123+
) : null}
124+
</div>
125+
);
126+
}
127+
return null;
128+
};
129+
130+
Alert.Link = AlertLink;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React, { ReactNode } from "react";
2+
3+
import cn from "classnames";
4+
5+
export interface AlertLinkProps {
6+
/**
7+
* Child elements within
8+
*/
9+
children?: ReactNode;
10+
/**
11+
* Additional Class
12+
*/
13+
className?: string;
14+
/**
15+
* Href
16+
*/
17+
href?: string;
18+
/**
19+
* onClick handler
20+
*/
21+
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
22+
}
23+
export const AlertLink: React.FC<AlertLinkProps> = ({
24+
children,
25+
className,
26+
href,
27+
onClick,
28+
}) => {
29+
return (
30+
<a className={cn("alert-link", className)} href={href} onClick={onClick}>
31+
{children}
32+
</a>
33+
);
34+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./Alert";
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React, { ReactNode } from "react";
2+
3+
import cn from "classnames";
4+
5+
import { Badge } from "../Badge";
6+
7+
export interface AvatarProps {
8+
/**
9+
* Child elements within
10+
*/
11+
children?: ReactNode;
12+
/**
13+
* Additional Class
14+
*/
15+
className?: string;
16+
/**
17+
* Color only when using Initials
18+
*/
19+
color?: string;
20+
/**
21+
* Full or data url of an avatar image
22+
*/
23+
url?: string;
24+
/**
25+
* Initials to use instead of an image
26+
*/
27+
initials?: string;
28+
/**
29+
* Size of the avatar
30+
*/
31+
size?: string;
32+
/**
33+
* Display a status color
34+
*/
35+
status?: "info" | "success" | "warning" | "danger";
36+
/**
37+
* Shape of the avatar
38+
*/
39+
shape?: "rounded" | "rounded-circle" | "rounded-0" | "rounded-lg";
40+
/**
41+
* Icon instead of Image or Initials
42+
*/
43+
icon?: ReactNode;
44+
}
45+
export const Avatar: React.FC<AvatarProps> = ({
46+
children,
47+
className,
48+
color,
49+
url,
50+
initials,
51+
size,
52+
shape,
53+
status,
54+
icon,
55+
}) => {
56+
const styles = {
57+
backgroundImage: "url('" + url + "')",
58+
};
59+
60+
const classes = [];
61+
color && classes.push("bg-" + color);
62+
size && classes.push("avatar-" + size);
63+
shape && classes.push(shape);
64+
65+
return (
66+
<span style={styles} className={cn("avatar", classes, className)}>
67+
{initials && !url ? initials.toUpperCase() : null}
68+
{!initials && !url ? children : null}
69+
{icon && <span className="avatar-icon">{icon}</span>}
70+
{status ? <Badge color={status} /> : null}
71+
</span>
72+
);
73+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./Avatar";
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React, { ReactNode } from "react";
2+
3+
import cn from "classnames";
4+
5+
export interface AvatarListProps {
6+
/**
7+
* Child elements within
8+
*/
9+
children?: ReactNode;
10+
/**
11+
* Additional Class
12+
*/
13+
className?: string;
14+
/**
15+
* Displays stacked avatars
16+
*/
17+
stacked?: boolean;
18+
}
19+
export const AvatarList: React.FC<AvatarListProps> = ({
20+
children,
21+
className,
22+
stacked,
23+
}) => {
24+
return (
25+
<div
26+
className={cn(
27+
"avatar-list",
28+
stacked && "avatar-list-stacked",
29+
className,
30+
)}>
31+
{children}
32+
</div>
33+
);
34+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./AvatarList";
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React, { ReactNode } from "react";
2+
3+
import cn from "classnames";
4+
5+
export interface BadgeProps {
6+
/**
7+
* Child elements within
8+
*/
9+
children?: ReactNode;
10+
/**
11+
* Additional Class
12+
*/
13+
className?: string;
14+
/**
15+
* Color of the Badge
16+
*/
17+
color?: string;
18+
/**
19+
* Type of Badge
20+
*/
21+
type?: "pill" | "soft";
22+
}
23+
export const Badge: React.FC<BadgeProps> = ({
24+
children,
25+
className,
26+
color,
27+
type,
28+
}) => {
29+
let modifier = "";
30+
31+
type === "soft" && (modifier = "-lt");
32+
const classes = ["badge", "bg-" + (color || "blue") + modifier];
33+
type === "pill" && classes.push("badge-pill");
34+
35+
return <span className={cn(classes, className)}>{children}</span>;
36+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./Badge";

0 commit comments

Comments
 (0)