Skip to content

Commit f1f10c0

Browse files
KernButtons shared components (#39)
* Refactoring buttons and adding more to submodules * Moved IconButton to submodules * Icon button changes * PR comments * Added className to the combined classes
1 parent f83661d commit f1f10c0

File tree

4 files changed

+169
-2
lines changed

4 files changed

+169
-2
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { combineClassNames } from "@/submodules/javascript-functions/general";
2+
import { useMemo } from "react";
3+
4+
export type ButtonAsTextProps = {
5+
text: string;
6+
color?: string;
7+
onClick?: () => void;
8+
disabled?: boolean;
9+
iconLeft?: (props: any) => React.ReactNode;
10+
iconRight?: (props: any) => React.ReactNode;
11+
iconColor?: string;
12+
size?: 'small' | 'medium' | 'large';
13+
className?: string;
14+
}
15+
16+
export default function ButtonAsText(props: ButtonAsTextProps) {
17+
const classCombined = useMemo(() => combineClassNames(
18+
'disabled:text-gray-400 disabled:cursor-not-allowed flex items-center space-x-1',
19+
props.className,
20+
props.color ? (
21+
`text-${props.color}-600 hover:text-${props.color}-900`
22+
) : (
23+
'text-gray-600 hover:text-gray-900'
24+
)
25+
), [props.color]);
26+
27+
return (
28+
<button
29+
className={classCombined}
30+
disabled={props.disabled}
31+
onClick={props.onClick}>
32+
{props.iconLeft && <props.iconLeft className={combineClassNames(
33+
`text-${props.iconColor}-500 group-hover:text-${props.iconColor}-600`,
34+
props.size == 'small' ? (
35+
'w-4 h-4'
36+
) : (
37+
props.size == 'large' ? (
38+
'w-6 h-6'
39+
) : (
40+
'w-5 h-5'
41+
)
42+
)
43+
)} />}
44+
<span>
45+
{props.text}
46+
</span>
47+
<span className="sr-only">,{props.text}</span>
48+
{props.iconRight && <props.iconRight className={combineClassNames(
49+
`text-${props.iconColor}-500 group-hover:text-${props.iconColor}-600`,
50+
props.size == 'small' ? (
51+
'w-4 h-4'
52+
) : (
53+
props.size == 'large' ? (
54+
'w-6 h-6'
55+
) : (
56+
'w-5 h-5'
57+
)
58+
)
59+
)} />}
60+
</button >)
61+
}

components/kern-button/IconButton.tsx

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { combineClassNames } from "@/submodules/javascript-functions/general";
2+
import { Tooltip } from '@nextui-org/react'
3+
import { IconCheck } from "@tabler/icons-react";
4+
import { useState } from "react";
5+
6+
interface IconButtonProps {
7+
icon: (props: any) => React.ReactNode;
8+
iconColor?: string;
9+
onClick?: (e?: any) => void;
10+
buttonColor?: string;
11+
disabled?: boolean;
12+
keepOpacity?: boolean;
13+
size?: 'small' | 'medium' | 'large';
14+
tooltip?: string;
15+
tooltipPlacement?: 'top' | 'bottom' | 'left' | 'right';
16+
confirm?: boolean;
17+
onMouseDown?: (e?: any) => void;
18+
className?: string;
19+
}
20+
21+
function InnerButton(props: IconButtonProps) {
22+
const [confirmed, setConfirmed] = useState<boolean>(false);
23+
24+
return (
25+
<button
26+
onClick={(e?: any) => {
27+
if (props.onClick) props.onClick(e);
28+
if (props.confirm) {
29+
setConfirmed(true);
30+
setTimeout(() => {
31+
setConfirmed(false);
32+
}, 3000);
33+
}
34+
}}
35+
onMouseDown={props.onMouseDown ? props.onMouseDown : undefined}
36+
className={
37+
combineClassNames(
38+
'text-sm group flex items-center justify-center rounded-md h-fit hover:shadow-sm transition duration-200 ease-in-out disabled:cursor-not-allowed',
39+
props.className,
40+
props.keepOpacity ? '' : (
41+
'disabled:opacity-50 '
42+
),
43+
props.buttonColor ? (
44+
`border border-${props.buttonColor}-300 bg-${props.buttonColor}-50 hover:bg-${props.buttonColor}-100 hover:border-${props.buttonColor}-400 active:bg-${props.buttonColor}-200 active:border-${props.buttonColor}-500`
45+
) : (
46+
'border bg-white border-gray-200 hover:bg-gray-50 hover:border-gray-300 active:bg-gray-100 active:border-gray-400'
47+
),
48+
props.size == 'small' ? (
49+
'p-1'
50+
) : (
51+
props.size == 'large' ? (
52+
'p-2'
53+
) : (
54+
'p-1.5'
55+
)
56+
)
57+
)
58+
}
59+
disabled={props.disabled}
60+
>
61+
{confirmed ? (
62+
<IconCheck
63+
className={combineClassNames(
64+
`text-green-500 group-hover:text-green-600`,
65+
props.size == 'small' ? (
66+
'w-4 h-4'
67+
) : (
68+
props.size == 'large' ? (
69+
'w-6 h-6'
70+
) : (
71+
'w-5 h-5'
72+
)
73+
)
74+
)}
75+
/>
76+
) : (
77+
<props.icon className={combineClassNames(
78+
`text-${props.iconColor}-500 group-hover:text-${props.iconColor}-600`,
79+
props.size == 'small' ? (
80+
'w-4 h-4'
81+
) : (
82+
props.size == 'large' ? (
83+
'w-6 h-6'
84+
) : (
85+
'w-5 h-5'
86+
)
87+
)
88+
)} />
89+
)}
90+
91+
</button>
92+
)
93+
}
94+
95+
export default function IconButton(props: IconButtonProps) {
96+
return props.disabled ? (
97+
<InnerButton {...props} />
98+
) : (
99+
<Tooltip color="invert" content={props.tooltip} placement={props.tooltipPlacement || "bottom"} >
100+
<InnerButton {...props} />
101+
</Tooltip>
102+
)
103+
}

components/kern-button/KernButton.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ interface KernButtonProps {
2222
tooltip?: string;
2323
tooltipPlacement?: 'top' | 'bottom' | 'left' | 'right';
2424
confirm?: boolean;
25+
className?: string;
2526
}
2627

2728
export default function KernButton(props: KernButtonProps) {
@@ -44,6 +45,7 @@ export default function KernButton(props: KernButtonProps) {
4445
className={
4546
combineClassNames(
4647
'text-sm group flex gap-x-2 items-center rounded-md hover:shadow-sm transition duration-200 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed',
48+
props.className,
4749
props.buttonColor ? (
4850
props.solidTheme ? (
4951
`border border-${props.buttonColor}-600 bg-${props.buttonColor}-600 hover:bg-${props.buttonColor}-600 active:bg-${props.buttonColor}-600 active:border-${props.buttonColor}-600`

components/kern-button/SaveButton.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type SaveButtonProps = {
2020
tooltipPlacement?: 'top' | 'bottom' | 'left' | 'right';
2121
confirm?: boolean;
2222
warningCue?: any
23+
className?: string;
2324
}
2425

2526
export default function SaveButton(props: SaveButtonProps) {
@@ -47,8 +48,8 @@ export default function SaveButton(props: SaveButtonProps) {
4748

4849
const sizeClasses: string = useMemo(() => getSizeClasses(props.size), [props.size]);
4950

50-
const buttonClasses = useMemo(() => combineClassNames("flex gap-x-1 items-center hover:shadow-sm rounded-lg px-2 py-1", disabledClasses, buttonColorClasses, widthClasses, heightClasses, props.warningCue && buttonWarningColorClasses),
51-
[disabledClasses, buttonColorClasses, widthClasses, heightClasses, props.warningCue]);
51+
const buttonClasses = useMemo(() => combineClassNames("flex gap-x-1 items-center hover:shadow-sm rounded-lg px-2 py-1", disabledClasses, buttonColorClasses, widthClasses, heightClasses, props.warningCue && buttonWarningColorClasses, props.className),
52+
[disabledClasses, buttonColorClasses, widthClasses, heightClasses, props.warningCue, props.className]);
5253

5354
return (
5455
<div className='text-sm group flex items-center rounded-md transition duration-200 ease-in-out' >

0 commit comments

Comments
 (0)