Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/resources/scripts/components/elements/Button.tsx
7461 views
1
import React from 'react';
2
import styled, { css } from 'styled-components/macro';
3
import tw from 'twin.macro';
4
import Spinner from '@/components/elements/Spinner';
5
6
interface Props {
7
isLoading?: boolean;
8
size?: 'xsmall' | 'small' | 'large' | 'xlarge';
9
color?: 'green' | 'red' | 'primary' | 'grey';
10
isSecondary?: boolean;
11
}
12
13
const ButtonStyle = styled.button<Omit<Props, 'isLoading'>>`
14
${tw`relative inline-block rounded p-2 uppercase tracking-wide text-sm transition-all duration-150 border`};
15
16
${(props) =>
17
((!props.isSecondary && !props.color) || props.color === 'primary') &&
18
css<Props>`
19
${(props) => !props.isSecondary && tw`bg-primary-500 border-primary-600 border text-primary-50`};
20
21
&:hover:not(:disabled) {
22
${tw`bg-primary-600 border-primary-700`};
23
}
24
`};
25
26
${(props) =>
27
props.color === 'grey' &&
28
css`
29
${tw`border-neutral-600 bg-neutral-500 text-neutral-50`};
30
31
&:hover:not(:disabled) {
32
${tw`bg-neutral-600 border-neutral-700`};
33
}
34
`};
35
36
${(props) =>
37
props.color === 'green' &&
38
css<Props>`
39
${tw`border-green-600 bg-green-500 text-green-50`};
40
41
&:hover:not(:disabled) {
42
${tw`bg-green-600 border-green-700`};
43
}
44
45
${(props) =>
46
props.isSecondary &&
47
css`
48
&:active:not(:disabled) {
49
${tw`bg-green-600 border-green-700`};
50
}
51
`};
52
`};
53
54
${(props) =>
55
props.color === 'red' &&
56
css<Props>`
57
${tw`border-red-600 bg-red-500 text-red-50`};
58
59
&:hover:not(:disabled) {
60
${tw`bg-red-600 border-red-700`};
61
}
62
63
${(props) =>
64
props.isSecondary &&
65
css`
66
&:active:not(:disabled) {
67
${tw`bg-red-600 border-red-700`};
68
}
69
`};
70
`};
71
72
${(props) => props.size === 'xsmall' && tw`px-2 py-1 text-xs`};
73
${(props) => (!props.size || props.size === 'small') && tw`px-4 py-2`};
74
${(props) => props.size === 'large' && tw`p-4 text-sm`};
75
${(props) => props.size === 'xlarge' && tw`p-4 w-full`};
76
77
${(props) =>
78
props.isSecondary &&
79
css<Props>`
80
${tw`border-neutral-600 bg-transparent text-neutral-200`};
81
82
&:hover:not(:disabled) {
83
${tw`border-neutral-500 text-neutral-100`};
84
${(props) => props.color === 'red' && tw`bg-red-500 border-red-600 text-red-50`};
85
${(props) => props.color === 'primary' && tw`bg-primary-500 border-primary-600 text-primary-50`};
86
${(props) => props.color === 'green' && tw`bg-green-500 border-green-600 text-green-50`};
87
}
88
`};
89
90
&:disabled {
91
opacity: 0.55;
92
cursor: default;
93
}
94
`;
95
96
type ComponentProps = Omit<JSX.IntrinsicElements['button'], 'ref' | keyof Props> & Props;
97
98
const Button: React.FC<ComponentProps> = ({ children, isLoading, ...props }) => (
99
<ButtonStyle {...props}>
100
{isLoading && (
101
<div css={tw`flex absolute justify-center items-center w-full h-full left-0 top-0`}>
102
<Spinner size={'small'} />
103
</div>
104
)}
105
<span css={isLoading ? tw`text-transparent` : undefined}>{children}</span>
106
</ButtonStyle>
107
);
108
109
type LinkProps = Omit<JSX.IntrinsicElements['a'], 'ref' | keyof Props> & Props;
110
111
const LinkButton: React.FC<LinkProps> = (props) => <ButtonStyle as={'a'} {...props} />;
112
113
export { LinkButton, ButtonStyle };
114
export default Button;
115
116