pstream is dead; long live pstream
taciturnaxolotl.github.io/pstream-ng/
1import classNames from "classnames";
2import { ReactNode } from "react";
3import { useNavigate } from "react-router-dom";
4
5import { Icon, Icons } from "@/components/Icon";
6import { Heading2, Heading3, Paragraph } from "@/components/utils/Text";
7
8export function Card(props: {
9 children?: React.ReactNode;
10 className?: string;
11 onClick?: () => void;
12}) {
13 return (
14 <div
15 className={classNames(
16 {
17 "bg-onboarding-card duration-300 border border-onboarding-border rounded-lg p-7": true,
18 "hover:bg-onboarding-cardHover transition-colors cursor-pointer":
19 !!props.onClick,
20 },
21 props.className,
22 )}
23 onClick={props.onClick}
24 >
25 {props.children}
26 </div>
27 );
28}
29
30export function CardContent(props: {
31 title: ReactNode;
32 description: ReactNode;
33 subtitle: ReactNode;
34 colorClass: string;
35 children?: React.ReactNode;
36}) {
37 return (
38 <div className="grid grid-rows-[1fr,auto] h-full">
39 <div>
40 <Icon
41 icon={Icons.RISING_STAR}
42 className={classNames("text-4xl mb-8 block", props.colorClass)}
43 />
44 <Heading3
45 className={classNames(
46 "!mt-0 !mb-0 !text-xs uppercase",
47 props.colorClass,
48 )}
49 >
50 {props.subtitle}
51 </Heading3>
52 <Heading2 className="!mb-0 !mt-1 !text-base">{props.title}</Heading2>
53 <Paragraph className="max-w-[320px] !my-4">
54 {props.description}
55 </Paragraph>
56 </div>
57 <div>{props.children}</div>
58 </div>
59 );
60}
61
62export function MiniCardContent(props: {
63 title: ReactNode;
64 description: ReactNode;
65 subtitle: ReactNode;
66 colorClass: string;
67 children?: React.ReactNode;
68}) {
69 return (
70 <div className="grid grid-rows-[1fr,auto] h-full">
71 <div className="flex">
72 <div className="flex flex-col">
73 <Heading3
74 className={classNames(
75 "!mt-0 !mb-0 !text-xs uppercase !mr-2",
76 props.colorClass,
77 )}
78 >
79 {props.subtitle}
80 </Heading3>
81 <Heading2 className="!mb-0 !mt-1 !text-sm">{props.title}</Heading2>
82 </div>
83 <Icon
84 icon={Icons.ARROW_RIGHT}
85 className={classNames(
86 "text-3xl mb-4 ml-auto block",
87 props.colorClass,
88 )}
89 />
90 </div>
91 <Paragraph className="max-w-[320px] !my-2 text-sm">
92 {props.description}
93 </Paragraph>
94 <div className="text-sm">{props.children}</div>
95 </div>
96 );
97}
98
99export function Link(props: {
100 children?: React.ReactNode;
101 to?: string;
102 href?: string;
103 className?: string;
104 target?: "_blank";
105}) {
106 const navigate = useNavigate();
107 return (
108 <a
109 onClick={() => {
110 if (props.to) navigate(props.to);
111 }}
112 href={props.href}
113 target={props.target}
114 className={classNames(
115 "text-onboarding-link cursor-pointer inline-flex gap-2 items-center group hover:opacity-75 transition-opacity",
116 props.className,
117 )}
118 rel="noreferrer"
119 >
120 {props.children}
121 <Icon
122 icon={Icons.ARROW_RIGHT}
123 className="group-hover:translate-x-0.5 transition-transform text-xl group-active:translate-x-0"
124 />
125 </a>
126 );
127}