chore: replace usage of forwardRef with ref as a prop (#21956)

This commit is contained in:
ケイラ
2026-02-10 16:41:20 -07:00
committed by GitHub
parent c2c2b6f16f
commit e27c4dcd92
31 changed files with 546 additions and 654 deletions
+12 -18
View File
@@ -7,13 +7,7 @@ import {
TriangleAlertIcon,
XIcon,
} from "lucide-react";
import {
type FC,
forwardRef,
type PropsWithChildren,
type ReactNode,
useState,
} from "react";
import { type FC, type ReactNode, useState } from "react";
import { cn } from "utils/cn";
const alertVariants = cva(
@@ -131,7 +125,9 @@ export const Alert: FC<AlertProps> = ({
);
};
export const AlertDetail: FC<PropsWithChildren> = ({ children }) => {
export const AlertDetail: React.FC<React.PropsWithChildren> = ({
children,
}) => {
return (
<span className="m-0 text-sm" data-chromatic="ignore">
{children}
@@ -139,13 +135,11 @@ export const AlertDetail: FC<PropsWithChildren> = ({ children }) => {
);
};
export const AlertTitle = forwardRef<
HTMLHeadingElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h1
ref={ref}
className={cn("m-0 mb-1 text-sm font-medium", className)}
{...props}
/>
));
export const AlertTitle: React.FC<React.ComponentPropsWithRef<"h1">> = ({
className,
...props
}) => {
return (
<h1 className={cn("m-0 mb-1 text-sm font-medium", className)} {...props} />
);
};
+11 -10
View File
@@ -13,7 +13,6 @@
import { useTheme } from "@emotion/react";
import * as AvatarPrimitive from "@radix-ui/react-avatar";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { getExternalImageStylesFromUrl } from "theme/externalImages";
import { cn } from "utils/cn";
@@ -58,17 +57,22 @@ export type AvatarProps = AvatarPrimitive.AvatarProps &
VariantProps<typeof avatarVariants> & {
src?: string;
fallback?: string;
ref?: React.Ref<React.ComponentRef<typeof AvatarPrimitive.Root>>;
};
const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
AvatarProps
>(({ className, size, variant, src, fallback, children, ...props }, ref) => {
export const Avatar: React.FC<AvatarProps> = ({
className,
size,
variant,
src,
fallback,
children,
...props
}) => {
const theme = useTheme();
return (
<AvatarPrimitive.Root
ref={ref}
className={cn(avatarVariants({ size, variant, className }))}
{...props}
>
@@ -85,7 +89,4 @@ const Avatar = React.forwardRef<
{children}
</AvatarPrimitive.Root>
);
});
Avatar.displayName = AvatarPrimitive.Root.displayName;
export { Avatar };
};
+21 -24
View File
@@ -4,7 +4,6 @@
*/
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { forwardRef } from "react";
import { cn } from "utils/cn";
const badgeVariants = cva(
@@ -58,28 +57,26 @@ const badgeVariants = cva(
},
);
interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {
asChild?: boolean;
}
type BadgeProps = React.ComponentPropsWithRef<"div"> &
VariantProps<typeof badgeVariants> & {
asChild?: boolean;
};
export const Badge = forwardRef<HTMLDivElement, BadgeProps>(
(
{ className, variant, size, border, hover, asChild = false, ...props },
ref,
) => {
const Comp = asChild ? Slot : "div";
export const Badge: React.FC<BadgeProps> = ({
className,
variant,
size,
border,
hover,
asChild = false,
...props
}) => {
const Comp = asChild ? Slot : "div";
return (
<Comp
{...props}
ref={ref}
className={cn(
badgeVariants({ variant, size, border, hover }),
className,
)}
/>
);
},
);
return (
<Comp
{...props}
className={cn(badgeVariants({ variant, size, border, hover }), className)}
/>
);
};
+14 -20
View File
@@ -1,13 +1,7 @@
import { Badge } from "components/Badge/Badge";
import { Stack } from "components/Stack/Stack";
import {
type FC,
forwardRef,
type HTMLAttributes,
type PropsWithChildren,
} from "react";
export const EnabledBadge: FC = () => {
export const EnabledBadge: React.FC = () => {
return (
<Badge className="option-enabled" variant="green" border="solid">
Enabled
@@ -15,25 +9,25 @@ export const EnabledBadge: FC = () => {
);
};
export const EntitledBadge: FC = () => {
export const EntitledBadge: React.FC = () => {
return (
<Badge border="solid" variant="green">
Entitled
</Badge>
);
};
export const DisabledBadge: FC = forwardRef<
HTMLDivElement,
HTMLAttributes<HTMLDivElement>
>((props, ref) => {
export const DisabledBadge: React.FC<React.ComponentPropsWithRef<"div">> = ({
...props
}) => {
return (
<Badge ref={ref} {...props} className="option-disabled">
<Badge {...props} className="option-disabled">
Disabled
</Badge>
);
});
};
export const EnterpriseBadge: FC = () => {
export const EnterpriseBadge: React.FC = () => {
return (
<Badge variant="info" border="solid">
Enterprise
@@ -45,7 +39,7 @@ interface PremiumBadgeProps {
children?: React.ReactNode;
}
export const PremiumBadge: FC<PremiumBadgeProps> = ({
export const PremiumBadge: React.FC<PremiumBadgeProps> = ({
children = "Premium",
}) => {
return (
@@ -55,7 +49,7 @@ export const PremiumBadge: FC<PremiumBadgeProps> = ({
);
};
export const PreviewBadge: FC = () => {
export const PreviewBadge: React.FC = () => {
return (
<Badge variant="purple" border="solid">
Preview
@@ -63,7 +57,7 @@ export const PreviewBadge: FC = () => {
);
};
export const AlphaBadge: FC = () => {
export const AlphaBadge: React.FC = () => {
return (
<Badge variant="purple" border="solid">
Alpha
@@ -71,7 +65,7 @@ export const AlphaBadge: FC = () => {
);
};
export const DeprecatedBadge: FC = () => {
export const DeprecatedBadge: React.FC = () => {
return (
<Badge variant="warning" border="solid">
Deprecated
@@ -79,7 +73,7 @@ export const DeprecatedBadge: FC = () => {
);
};
export const Badges: FC<PropsWithChildren> = ({ children }) => {
export const Badges: React.FC<React.PropsWithChildren> = ({ children }) => {
return (
<Stack
css={{ margin: "0 0 16px" }}
+91 -89
View File
@@ -4,62 +4,59 @@
*/
import { Slot } from "@radix-ui/react-slot";
import { MoreHorizontal } from "lucide-react";
import {
type ComponentProps,
type ComponentPropsWithoutRef,
type FC,
forwardRef,
type ReactNode,
} from "react";
import { cn } from "utils/cn";
export const Breadcrumb = forwardRef<
HTMLElement,
ComponentPropsWithoutRef<"nav"> & {
separator?: ReactNode;
}
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />);
Breadcrumb.displayName = "Breadcrumb";
type BreadcrumbProps = React.ComponentPropsWithRef<"nav"> & {
separator?: React.ReactNode;
};
export const BreadcrumbList = forwardRef<
HTMLOListElement,
ComponentPropsWithoutRef<"ol">
>(({ className, ...props }, ref) => (
<ol
ref={ref}
className={cn(
"flex flex-wrap items-center text-sm pl-6 my-4 gap-1.5 break-words font-medium list-none sm:gap-2.5",
className,
)}
{...props}
/>
));
export const Breadcrumb: React.FC<BreadcrumbProps> = ({ ...props }) => {
return <nav aria-label="breadcrumb" {...props} />;
};
export const BreadcrumbItem = forwardRef<
HTMLLIElement,
ComponentPropsWithoutRef<"li">
>(({ className, ...props }, ref) => (
<li
ref={ref}
className={cn(
"inline-flex items-center gap-1.5 text-content-secondary",
className,
)}
{...props}
/>
));
export const BreadcrumbList: React.FC<React.ComponentPropsWithRef<"ol">> = ({
className,
...props
}) => {
return (
<ol
className={cn(
"flex flex-wrap items-center text-sm pl-6 my-4 gap-1.5 break-words font-medium list-none sm:gap-2.5",
className,
)}
{...props}
/>
);
};
export const BreadcrumbLink = forwardRef<
HTMLAnchorElement,
ComponentPropsWithoutRef<"a"> & {
asChild?: boolean;
}
>(({ asChild, className, ...props }, ref) => {
export const BreadcrumbItem: React.FC<React.ComponentPropsWithRef<"li">> = ({
className,
...props
}) => {
return (
<li
className={cn(
"inline-flex items-center gap-1.5 text-content-secondary",
className,
)}
{...props}
/>
);
};
type BreadcrumbLinkProps = React.ComponentPropsWithRef<"a"> & {
asChild?: boolean;
};
export const BreadcrumbLink: React.FC<BreadcrumbLinkProps> = ({
asChild,
className,
...props
}) => {
const Comp = asChild ? Slot : "a";
return (
<Comp
ref={ref}
className={cn(
"text-content-secondary transition-colors hover:text-content-primary no-underline hover:underline",
className,
@@ -67,49 +64,54 @@ export const BreadcrumbLink = forwardRef<
{...props}
/>
);
});
};
export const BreadcrumbPage = forwardRef<
HTMLSpanElement,
ComponentPropsWithoutRef<"span">
>(({ className, ...props }, ref) => (
<span
ref={ref}
aria-current="page"
className={cn("flex items-center gap-2 text-content-secondary", className)}
{...props}
/>
));
export const BreadcrumbSeparator: FC<ComponentProps<"li">> = ({
children,
export const BreadcrumbPage: React.FC<React.ComponentPropsWithRef<"span">> = ({
className,
...props
}) => (
<li
role="presentation"
aria-hidden="true"
className={cn(
"text-content-disabled [&>svg]:w-3.5 [&>svg]:h-3.5",
className,
)}
{...props}
>
/
</li>
);
}) => {
return (
<span
aria-current="page"
className={cn(
"flex items-center gap-2 text-content-secondary",
className,
)}
{...props}
/>
);
};
export const BreadcrumbEllipsis: FC<ComponentProps<"span">> = ({
className,
...props
}) => (
<span
role="presentation"
aria-hidden="true"
className={cn("flex h-9 w-9 items-center justify-center", className)}
{...props}
>
<MoreHorizontal className="h-4 w-4" />
<span className="sr-only">More</span>
</span>
);
export const BreadcrumbSeparator: React.FC<
Omit<React.ComponentPropsWithRef<"li">, "children">
> = ({ className, ...props }) => {
return (
<li
role="presentation"
aria-hidden="true"
className={cn(
"text-content-disabled [&>svg]:w-3.5 [&>svg]:h-3.5",
className,
)}
{...props}
>
/
</li>
);
};
export const BreadcrumbEllipsis: React.FC<
Omit<React.ComponentPropsWithRef<"span">, "children">
> = ({ className, ...props }) => {
return (
<span
role="presentation"
aria-hidden="true"
className={cn("flex h-9 w-9 items-center justify-center", className)}
{...props}
>
<MoreHorizontal className="h-4 w-4" />
<span className="sr-only">More</span>
</span>
);
};
+30 -28
View File
@@ -4,7 +4,6 @@
*/
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { forwardRef } from "react";
import { cn } from "utils/cn";
// Be careful when changing the child styles from the button such as images
@@ -58,31 +57,34 @@ const buttonVariants = cva(
},
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}
export type ButtonProps = React.ComponentPropsWithRef<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean;
};
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button";
return (
<Comp
{...props}
ref={ref}
className={cn(buttonVariants({ variant, size }), className)}
// Adding default button type to make sure that buttons don't
// accidentally trigger form actions when clicked. But because
// this Button component is so polymorphic (it's also used to
// make <a> elements look like buttons), we can only safely
// default to adding the prop when we know that we're rendering
// a real HTML button instead of an arbitrary Slot. Adding the
// type attribute to any non-buttons will produce invalid HTML
type={
props.type === undefined && Comp === "button" ? "button" : props.type
}
/>
);
},
);
export const Button: React.FC<ButtonProps> = ({
className,
variant,
size,
asChild = false,
...props
}) => {
const Comp = asChild ? Slot : "button";
// We want `type` to default to `"button"` when the component is not being
// used as a `Slot`. The default behavior of any given `<button>` element is
// to submit the closest parent `<form>` because Web Platform reasons. This
// prevents that. However, we don't want to set it on non-`<button>`s when
// `asChild` is set.
// https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/button#type
if (!asChild && !props.type) {
props.type = "button";
}
return (
<Comp
{...props}
className={cn(buttonVariants({ variant, size }), className)}
/>
);
};
+25 -26
View File
@@ -4,41 +4,40 @@
*/
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Check, Minus } from "lucide-react";
import * as React from "react";
import { cn } from "utils/cn";
/**
* To allow for an indeterminate state the checkbox must be controlled, otherwise the checked prop would remain undefined
*/
export const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
`peer size-[18px] shrink-0 rounded-sm border border-border border-solid
export const Checkbox: React.FC<
React.ComponentPropsWithRef<typeof CheckboxPrimitive.Root>
> = ({ className, ...props }) => {
return (
<CheckboxPrimitive.Root
className={cn(
`peer size-[18px] shrink-0 rounded-sm border border-border border-solid
focus-visible:outline-none focus-visible:ring-2
focus-visible:ring-content-link focus-visible:ring-offset-4 focus-visible:ring-offset-surface-primary
disabled:cursor-not-allowed disabled:bg-surface-primary disabled:data-[state=checked]:bg-surface-tertiary
data-[state=unchecked]:bg-surface-primary
data-[state=checked]:bg-surface-invert-primary data-[state=checked]:text-content-invert
hover:enabled:border-border-hover hover:data-[state=checked]:bg-surface-invert-secondary`,
className,
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current relative")}
className,
)}
{...props}
>
<div className="flex">
{(props.checked === true || props.defaultChecked === true) && (
<Check className="w-4 h-4" strokeWidth={2.5} />
)}
{props.checked === "indeterminate" && (
<Minus className="w-4 h-4" strokeWidth={2.5} />
)}
</div>
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current relative")}
>
<div className="flex">
{(props.checked === true || props.defaultChecked === true) && (
<Check className="w-4 h-4" strokeWidth={2.5} />
)}
{props.checked === "indeterminate" && (
<Minus className="w-4 h-4" strokeWidth={2.5} />
)}
</div>
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
);
};
@@ -1,19 +1,16 @@
import { useTheme } from "@emotion/react";
import { forwardRef, type ImgHTMLAttributes } from "react";
import { getExternalImageStylesFromUrl } from "theme/externalImages";
export const ExternalImage = forwardRef<
HTMLImageElement,
ImgHTMLAttributes<HTMLImageElement>
>((props, ref) => {
export const ExternalImage: React.FC<React.ComponentPropsWithRef<"img">> = ({
...props
}) => {
const theme = useTheme();
return (
// biome-ignore lint/a11y/useAltText: alt should be passed in as a prop
<img
ref={ref}
css={getExternalImageStylesFromUrl(theme.externalImages, props.src)}
{...props}
/>
);
});
};
+37 -41
View File
@@ -5,7 +5,6 @@ import {
type ComponentProps,
createContext,
type FC,
forwardRef,
type HTMLProps,
type ReactNode,
useContext,
@@ -76,53 +75,50 @@ interface FormSectionProps {
};
alpha?: boolean;
deprecated?: boolean;
ref?: React.Ref<HTMLElement>;
}
export const FormSection = forwardRef<HTMLDivElement, FormSectionProps>(
(
{
children,
title,
description,
classes = {},
alpha = false,
deprecated = false,
},
ref,
) => {
const { direction } = useContext(FormContext);
export const FormSection: FC<FormSectionProps> = ({
children,
title,
description,
classes = {},
alpha = false,
deprecated = false,
ref,
}) => {
const { direction } = useContext(FormContext);
return (
<section
ref={ref}
return (
<section
ref={ref}
css={[
styles.formSection,
direction === "horizontal" && styles.formSectionHorizontal,
]}
className={classes.root}
>
<div
css={[
styles.formSection,
direction === "horizontal" && styles.formSectionHorizontal,
styles.formSectionInfo,
direction === "horizontal" && styles.formSectionInfoHorizontal,
]}
className={classes.root}
className={classes.sectionInfo}
>
<div
css={[
styles.formSectionInfo,
direction === "horizontal" && styles.formSectionInfoHorizontal,
]}
className={classes.sectionInfo}
>
<header className="flex items-center gap-4">
<h2 css={styles.formSectionInfoTitle} className={classes.infoTitle}>
{title}
</h2>
{alpha && <AlphaBadge />}
{deprecated && <DeprecatedBadge />}
</header>
<div css={styles.formSectionInfoDescription}>{description}</div>
</div>
<header className="flex items-center gap-4">
<h2 css={styles.formSectionInfoTitle} className={classes.infoTitle}>
{title}
</h2>
{alpha && <AlphaBadge />}
{deprecated && <DeprecatedBadge />}
</header>
<div css={styles.formSectionInfoDescription}>{description}</div>
</div>
{children}
</section>
);
},
);
{children}
</section>
);
};
export const FormFields: FC<ComponentProps<typeof Stack>> = (props) => {
return (
+6 -7
View File
@@ -2,13 +2,13 @@
* Copied from shadc/ui on 11/13/2024
* @see {@link https://ui.shadcn.com/docs/components/input}
*/
import { forwardRef } from "react";
import { cn } from "utils/cn";
export const Input = forwardRef<
HTMLInputElement,
React.ComponentProps<"input">
>(({ className, type, ...props }, ref) => {
export const Input: React.FC<React.ComponentPropsWithRef<"input">> = ({
className,
type,
...props
}) => {
return (
<input
type={type}
@@ -23,8 +23,7 @@ export const Input = forwardRef<
`,
className,
)}
ref={ref}
{...props}
/>
);
});
};
+7 -12
View File
@@ -1,10 +1,9 @@
import { cva, type VariantProps } from "class-variance-authority";
import { Button, type ButtonProps } from "components/Button/Button";
import { Input } from "components/Input/Input";
import { type FC, forwardRef } from "react";
import { cn } from "utils/cn";
const InputGroup: FC<React.ComponentProps<"div">> = ({
export const InputGroup: React.FC<React.ComponentProps<"div">> = ({
className,
...props
}) => {
@@ -42,7 +41,7 @@ const inputGroupAddonVariants = cva(
},
);
const InputGroupAddon: FC<
export const InputGroupAddon: React.FC<
React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>
> = ({ className, align = "inline-start", ...props }) => {
return (
@@ -63,13 +62,11 @@ const InputGroupAddon: FC<
);
};
const InputGroupInput = forwardRef<
HTMLInputElement,
React.ComponentProps<typeof Input>
>(({ className, ...props }, ref) => {
export const InputGroupInput: React.FC<
React.ComponentPropsWithRef<typeof Input>
> = ({ className, ...props }) => {
return (
<Input
ref={ref}
className={cn(
// Reset Input's default styles that conflict with group
"flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0",
@@ -81,9 +78,9 @@ const InputGroupInput = forwardRef<
{...props}
/>
);
});
};
const InputGroupButton: FC<ButtonProps> = ({
export const InputGroupButton: React.FC<ButtonProps> = ({
className,
size = "sm",
variant = "subtle",
@@ -102,5 +99,3 @@ const InputGroupButton: FC<ButtonProps> = ({
/>
);
};
export { InputGroup, InputGroupAddon, InputGroupInput, InputGroupButton };
+11 -12
View File
@@ -4,21 +4,20 @@
*/
import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority";
import { forwardRef } from "react";
import { cn } from "utils/cn";
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);
export const Label = forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
));
type LabelProps = React.ComponentPropsWithRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>;
export const Label: React.FC<LabelProps> = ({ className, ...props }) => {
return (
<LabelPrimitive.Root
className={cn(labelVariants(), className)}
{...props}
/>
);
};
+22 -25
View File
@@ -1,7 +1,6 @@
import { Slot, Slottable } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { SquareArrowOutUpRightIcon } from "lucide-react";
import { forwardRef } from "react";
import { cn } from "utils/cn";
const linkVariants = cva(
@@ -23,28 +22,26 @@ const linkVariants = cva(
},
);
interface LinkProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement>,
VariantProps<typeof linkVariants> {
asChild?: boolean;
showExternalIcon?: boolean;
}
type LinkProps = React.AnchorHTMLAttributes<HTMLAnchorElement> &
VariantProps<typeof linkVariants> & {
asChild?: boolean;
showExternalIcon?: boolean;
ref?: React.Ref<HTMLAnchorElement>;
};
export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
(
{ className, children, size, asChild, showExternalIcon = true, ...props },
ref,
) => {
const Comp = asChild ? Slot : "a";
return (
<Comp
className={cn(linkVariants({ size }), className)}
ref={ref}
{...props}
>
<Slottable>{children}</Slottable>
{showExternalIcon && <SquareArrowOutUpRightIcon aria-hidden="true" />}
</Comp>
);
},
);
export const Link: React.FC<LinkProps> = ({
className,
children,
size,
asChild,
showExternalIcon = true,
...props
}) => {
const Comp = asChild ? Slot : "a";
return (
<Comp className={cn(linkVariants({ size }), className)} {...props}>
<Slottable>{children}</Slottable>
{showExternalIcon && <SquareArrowOutUpRightIcon />}
</Comp>
);
};
+26 -36
View File
@@ -2,16 +2,10 @@ import type { Interpolation, Theme } from "@emotion/react";
import CircularProgress, {
type CircularProgressProps,
} from "@mui/material/CircularProgress";
import {
type FC,
forwardRef,
type HTMLAttributes,
type ReactNode,
useMemo,
} from "react";
import { type FC, type ReactNode, useMemo } from "react";
import type { ThemeRole } from "theme/roles";
type PillProps = HTMLAttributes<HTMLDivElement> & {
type PillProps = React.ComponentPropsWithRef<"div"> & {
icon?: ReactNode;
type?: ThemeRole;
size?: "md" | "lg";
@@ -29,35 +23,31 @@ const PILL_HEIGHT = 24;
const PILL_ICON_SIZE = 14;
const PILL_ICON_SPACING = (PILL_HEIGHT - PILL_ICON_SIZE) / 2;
export const Pill: FC<PillProps> = forwardRef<HTMLDivElement, PillProps>(
(props, ref) => {
const {
icon,
type = "inactive",
children,
size = "md",
...divProps
} = props;
const typeStyles = useMemo(() => themeStyles(type), [type]);
export const Pill: FC<PillProps> = ({
icon,
type = "inactive",
children,
size = "md",
...divProps
}) => {
const typeStyles = useMemo(() => themeStyles(type), [type]);
return (
<div
ref={ref}
css={[
styles.pill,
Boolean(icon) && size === "md" && styles.pillWithIcon,
size === "lg" && styles.pillLg,
Boolean(icon) && size === "lg" && styles.pillLgWithIcon,
typeStyles,
]}
{...divProps}
>
{icon}
{children}
</div>
);
},
);
return (
<div
css={[
styles.pill,
Boolean(icon) && size === "md" && styles.pillWithIcon,
size === "lg" && styles.pillLg,
Boolean(icon) && size === "lg" && styles.pillLgWithIcon,
typeStyles,
]}
{...divProps}
>
{icon}
{children}
</div>
);
};
export const PillSpinner: FC<CircularProgressProps> = (props) => {
return (
+25 -30
View File
@@ -3,11 +3,6 @@
* @see {@link https://ui.shadcn.com/docs/components/popover}
*/
import * as PopoverPrimitive from "@radix-ui/react-popover";
import {
type ComponentPropsWithoutRef,
type ElementRef,
forwardRef,
} from "react";
import { cn } from "utils/cn";
export type PopoverContentProps = PopoverPrimitive.PopoverContentProps;
@@ -18,28 +13,28 @@ export const Popover = PopoverPrimitive.Root;
export const PopoverTrigger = PopoverPrimitive.Trigger;
export const PopoverContent = forwardRef<
ElementRef<typeof PopoverPrimitive.Content>,
ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
collisionPadding={16}
className={cn(
`z-50 w-72 rounded-md border border-solid bg-surface-primary
text-content-primary shadow-md outline-none
max-h-[var(--radix-popper-available-height)] overflow-y-auto
data-[state=open]:animate-in data-[state=closed]:animate-out
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0
data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95
data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2`,
className,
)}
{...props}
/>
</PopoverPrimitive.Portal>
));
export const PopoverContent: React.FC<
React.ComponentPropsWithRef<typeof PopoverPrimitive.Content>
> = ({ className, align = "center", sideOffset = 4, ...props }) => {
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
align={align}
sideOffset={sideOffset}
collisionPadding={16}
className={cn(
`z-50 w-72 rounded-md border border-solid bg-surface-primary
text-content-primary shadow-md outline-none
max-h-[var(--radix-popper-available-height)] overflow-y-auto
data-[state=open]:animate-in data-[state=closed]:animate-out
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0
data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95
data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2`,
className,
)}
{...props}
/>
</PopoverPrimitive.Portal>
);
};
+12 -18
View File
@@ -4,36 +4,30 @@
*/
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
import { Circle } from "lucide-react";
import * as React from "react";
import { cn } from "utils/cn";
export const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => {
export const RadioGroup: React.FC<
React.ComponentPropsWithRef<typeof RadioGroupPrimitive.Root>
> = ({ className, ...props }) => {
return (
<RadioGroupPrimitive.Root
className={cn("grid gap-2", className)}
{...props}
ref={ref}
/>
);
});
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
};
export const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
export const RadioGroupItem: React.FC<
React.ComponentPropsWithRef<typeof RadioGroupPrimitive.Item>
> = ({ className, ...props }) => {
return (
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
`relative aspect-square h-4 w-4 rounded-full border border-solid border-border text-content-primary bg-surface-primary
focus:outline-none focus-visible:ring-2 focus-visible:ring-content-link
focus-visible:ring-offset-4 focus-visible:ring-offset-surface-primary
disabled:cursor-not-allowed disabled:opacity-25 disabled:border-surface-invert-primary
hover:border-border-hover data-[state=checked]:border-border-hover`,
focus:outline-none focus-visible:ring-2 focus-visible:ring-content-link
focus-visible:ring-offset-4 focus-visible:ring-offset-surface-primary
disabled:cursor-not-allowed disabled:opacity-25 disabled:border-surface-invert-primary
hover:border-border-hover data-[state=checked]:border-border-hover`,
className,
)}
{...props}
@@ -43,4 +37,4 @@ export const RadioGroupItem = React.forwardRef<
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
);
});
};
+36 -38
View File
@@ -3,44 +3,42 @@
* @see {@link https://ui.shadcn.com/docs/components/scroll-area}
*/
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
import * as React from "react";
import { cn } from "utils/cn";
export const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar className="z-10" />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
));
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
export const ScrollArea: React.FC<
React.ComponentPropsWithRef<typeof ScrollAreaPrimitive.Root>
> = ({ className, children, ...props }) => {
return (
<ScrollAreaPrimitive.Root
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar className="z-10" />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
);
};
export const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = "vertical", ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
orientation={orientation}
className={cn(
"border-0 border-solid border-border flex touch-none select-none transition-colors",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
className,
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-surface-quaternary" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
));
export const ScrollBar: React.FC<
React.ComponentPropsWithRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
> = ({ className, orientation = "vertical", ...props }) => {
return (
<ScrollAreaPrimitive.ScrollAreaScrollbar
orientation={orientation}
className={cn(
"border-0 border-solid border-border flex touch-none select-none transition-colors",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
className,
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-surface-quaternary" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
);
};
+44 -71
View File
@@ -4,7 +4,6 @@
*/
import * as SelectPrimitive from "@radix-ui/react-select";
import { Check, ChevronDown, ChevronUp } from "lucide-react";
import * as React from "react";
import { cn } from "utils/cn";
export const Select = SelectPrimitive.Root;
@@ -13,17 +12,16 @@ export const SelectGroup = SelectPrimitive.Group;
export const SelectValue = SelectPrimitive.Value;
export type SelectTriggerProps = React.ComponentPropsWithoutRef<
export type SelectTriggerProps = React.ComponentPropsWithRef<
typeof SelectPrimitive.Trigger
>;
export const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
SelectTriggerProps
>(({ className, children, id, ...props }, ref) => (
export const SelectTrigger: React.FC<SelectTriggerProps> = ({
className,
children,
...props
}) => (
<SelectPrimitive.Trigger
ref={ref}
id={id}
className={cn(
`flex h-10 w-full font-medium items-center justify-between whitespace-nowrap rounded-md
border border-border border-solid bg-transparent px-3 py-2 text-sm shadow-sm
@@ -39,15 +37,12 @@ export const SelectTrigger = React.forwardRef<
<ChevronDown className="size-icon-sm cursor-pointer text-content-secondary hover:text-content-primary" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
);
const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => (
const SelectScrollUpButton: React.FC<
React.ComponentPropsWithRef<typeof SelectPrimitive.ScrollUpButton>
> = ({ className, ...props }) => (
<SelectPrimitive.ScrollUpButton
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className,
@@ -56,34 +51,29 @@ const SelectScrollUpButton = React.forwardRef<
>
<ChevronUp className="size-icon-sm" />
</SelectPrimitive.ScrollUpButton>
));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
);
const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className,
)}
{...props}
>
<ChevronDown className="size-icon-sm cursor-pointer text-content-secondary hover:text-content-primary" />
</SelectPrimitive.ScrollDownButton>
));
SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName;
const SelectScrollDownButton: React.FC<
React.ComponentPropsWithRef<typeof SelectPrimitive.ScrollDownButton>
> = ({ className, ...props }) => {
return (
<SelectPrimitive.ScrollDownButton
className={cn(
"flex cursor-default items-center justify-center py-1",
className,
)}
{...props}
>
<ChevronDown className="size-icon-sm cursor-pointer text-content-secondary hover:text-content-primary" />
</SelectPrimitive.ScrollDownButton>
);
};
export const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => (
export const SelectContent: React.FC<
React.ComponentPropsWithRef<typeof SelectPrimitive.Content>
> = ({ className, children, position = "popper", ...props }) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border ",
"border-border border-solid bg-surface-primary text-content-primary shadow-md ",
@@ -112,27 +102,23 @@ export const SelectContent = React.forwardRef<
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
));
SelectContent.displayName = SelectPrimitive.Content.displayName;
);
export const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={cn("px-2 py-1.5 text-sm font-semibold", className)}
{...props}
/>
));
SelectLabel.displayName = SelectPrimitive.Label.displayName;
export const SelectLabel: React.FC<
React.ComponentPropsWithRef<typeof SelectPrimitive.Label>
> = ({ className, ...props }) => {
return (
<SelectPrimitive.Label
className={cn("px-2 py-1.5 text-sm font-semibold", className)}
{...props}
/>
);
};
export const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
export const SelectItem: React.FC<
React.ComponentPropsWithRef<typeof SelectPrimitive.Item>
> = ({ className, children, ...props }) => (
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 ",
"pl-2 pr-8 text-sm text-content-secondary outline-none focus:bg-surface-secondary ",
@@ -148,17 +134,4 @@ export const SelectItem = React.forwardRef<
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
));
SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
);
@@ -16,7 +16,6 @@ import { CheckIcon, ChevronDownIcon } from "lucide-react";
import {
Children,
type FC,
forwardRef,
type HTMLProps,
isValidElement,
type ReactElement,
@@ -46,15 +45,16 @@ type SelectMenuButtonProps = ButtonProps & {
startIcon?: React.ReactNode;
};
export const SelectMenuButton = forwardRef<
HTMLButtonElement,
SelectMenuButtonProps
>(({ className, startIcon, children, ...props }, ref) => {
export const SelectMenuButton: React.FC<SelectMenuButtonProps> = ({
className,
startIcon,
children,
...props
}) => {
return (
<Button
variant="outline"
size="lg"
ref={ref}
// Shrink padding right slightly to account for visual weight of
// the chevron
className={cn("flex flex-row gap-2 pr-1.5", className)}
@@ -67,7 +67,7 @@ export const SelectMenuButton = forwardRef<
<ChevronDownIcon />
</Button>
);
});
};
export const SelectMenuSearch: FC<SearchFieldProps> = ({
className,
+24 -25
View File
@@ -3,36 +3,35 @@
* @see {@link https://ui.shadcn.com/docs/components/slider}
*/
import * as SliderPrimitive from "@radix-ui/react-slider";
import * as React from "react";
import { cn } from "utils/cn";
export const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn(
"relative flex w-full items-center h-1.5",
className,
"touch-none select-none",
)}
{...props}
>
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-surface-secondary data-[disabled]:opacity-40">
<SliderPrimitive.Range className="absolute h-full bg-content-primary" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb
className="block h-4 w-4 rounded-full border border-solid border-surface-invert-secondary bg-surface-primary shadow transition-colors
export const Slider: React.FC<
React.ComponentPropsWithRef<typeof SliderPrimitive.Root>
> = ({ className, ...props }) => {
return (
<SliderPrimitive.Root
className={cn(
"relative flex w-full items-center h-1.5",
className,
"touch-none select-none",
)}
{...props}
>
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-surface-secondary data-[disabled]:opacity-40">
<SliderPrimitive.Range className="absolute h-full bg-content-primary" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb
className="block h-4 w-4 rounded-full border border-solid border-surface-invert-secondary bg-surface-primary shadow transition-colors
focus-visible:outline-none hover:border-content-primary
focus-visible:ring-0 focus-visible:ring-content-primary focus-visible:ring-offset-surface-primary
disabled:pointer-events-none data-[disabled]:opacity-100 data-[disabled]:border-border"
/>
<SliderPrimitive.Thumb
className="block h-4 w-4 rounded-full border border-solid border-surface-invert-secondary bg-surface-primary shadow transition-colors
/>
<SliderPrimitive.Thumb
className="block h-4 w-4 rounded-full border border-solid border-surface-invert-secondary bg-surface-primary shadow transition-colors
focus-visible:outline-none hover:border-content-primary
focus-visible:ring-0 focus-visible:ring-content-primary focus-visible:ring-offset-surface-primary
disabled:pointer-events-none data-[disabled]:opacity-100 data-[disabled]:border-border"
/>
</SliderPrimitive.Root>
));
/>
</SliderPrimitive.Root>
);
};
+4 -9
View File
@@ -1,22 +1,18 @@
import type { CSSObject } from "@emotion/react";
import { forwardRef } from "react";
/**
* @deprecated Stack component is deprecated. Use Tailwind flex utilities instead.
*/
type StackProps = {
type StackProps = React.ComponentPropsWithRef<"div"> & {
className?: string;
direction?: "column" | "row";
spacing?: number;
alignItems?: CSSObject["alignItems"];
justifyContent?: CSSObject["justifyContent"];
wrap?: CSSObject["flexWrap"];
} & React.HTMLProps<HTMLDivElement>;
};
/**
* @deprecated Stack component is deprecated. Use Tailwind flex utilities instead.
*/
export const Stack = forwardRef<HTMLDivElement, StackProps>((props, ref) => {
export const Stack: React.FC<StackProps> = (props) => {
const {
children,
direction = "column",
@@ -30,7 +26,6 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>((props, ref) => {
return (
<div
{...divProps}
ref={ref}
css={{
display: "flex",
flexDirection: direction,
@@ -44,4 +39,4 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>((props, ref) => {
{children}
</div>
);
});
};
@@ -4,7 +4,7 @@ import {
TooltipContent,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import { createContext, type FC, forwardRef, useContext } from "react";
import { createContext, type FC, useContext } from "react";
import { cn } from "utils/cn";
const statusIndicatorVariants = cva(
@@ -34,23 +34,24 @@ type StatusIndicatorContextValue = VariantProps<typeof statusIndicatorVariants>;
const StatusIndicatorContext = createContext<StatusIndicatorContextValue>({});
export interface StatusIndicatorProps
extends React.HTMLAttributes<HTMLDivElement>,
StatusIndicatorContextValue {}
export type StatusIndicatorProps = React.ComponentPropsWithRef<"div"> &
StatusIndicatorContextValue;
export const StatusIndicator = forwardRef<HTMLDivElement, StatusIndicatorProps>(
({ size, variant, className, ...props }, ref) => {
return (
<StatusIndicatorContext.Provider value={{ size, variant }}>
<div
ref={ref}
className={cn(statusIndicatorVariants({ variant, size }), className)}
{...props}
/>
</StatusIndicatorContext.Provider>
);
},
);
export const StatusIndicator: React.FC<StatusIndicatorProps> = ({
size,
variant,
className,
...props
}) => {
return (
<StatusIndicatorContext.Provider value={{ size, variant }}>
<div
className={cn(statusIndicatorVariants({ variant, size }), className)}
{...props}
/>
</StatusIndicatorContext.Provider>
);
};
const dotVariants = cva("rounded-full inline-block border-4 border-solid", {
variants: {
+4 -7
View File
@@ -3,13 +3,11 @@
* @see {@link https://ui.shadcn.com/docs/components/switch}
*/
import * as SwitchPrimitives from "@radix-ui/react-switch";
import { forwardRef } from "react";
import { cn } from "utils/cn";
export const Switch = forwardRef<
React.ElementRef<typeof SwitchPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
>(({ className, ...props }, ref) => (
export const Switch: React.FC<
React.ComponentPropsWithRef<typeof SwitchPrimitives.Root>
> = ({ className, ...props }) => (
<SwitchPrimitives.Root
className={cn(
`peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full shadow-sm transition-colors
@@ -23,7 +21,6 @@ export const Switch = forwardRef<
className,
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb
className={cn(
@@ -32,4 +29,4 @@ export const Switch = forwardRef<
)}
/>
</SwitchPrimitives.Root>
));
);
+6 -8
View File
@@ -1,14 +1,13 @@
/**
* Copied from shadc/ui on 04/18/2025
* Copied from shadc/ui on 11/13/2024
* @see {@link https://ui.shadcn.com/docs/components/textarea}
*/
import * as React from "react";
import { cn } from "utils/cn";
export const Textarea = React.forwardRef<
HTMLTextAreaElement,
React.ComponentProps<"textarea">
>(({ className, ...props }, ref) => {
export const Textarea: React.FC<React.ComponentPropsWithRef<"textarea">> = ({
className,
...props
}) => {
return (
<textarea
className={cn(
@@ -18,8 +17,7 @@ export const Textarea = React.forwardRef<
disabled:cursor-not-allowed disabled:opacity-50 disabled:text-content-disabled md:text-sm`,
className,
)}
ref={ref}
{...props}
/>
);
});
};
@@ -1,18 +1,19 @@
import { TableRow, type TableRowProps } from "components/Table/Table";
import { forwardRef } from "react";
import { cn } from "utils/cn";
interface TimelineEntryProps extends TableRowProps {
ref?: React.Ref<HTMLTableRowElement>;
clickable?: boolean;
}
export const TimelineEntry = forwardRef<
HTMLTableRowElement,
TimelineEntryProps
>(({ children, clickable = true, className, ...props }, ref) => {
export const TimelineEntry: React.FC<TimelineEntryProps> = ({
children,
clickable = true,
className,
...props
}) => {
return (
<TableRow
ref={ref}
className={cn(
"focus:outline focus:-outline-offset-1 focus:outline-2 focus:outline-content-primary ",
"[&_td]:relative [&_td]:overflow-hidden",
@@ -25,4 +26,4 @@ export const TimelineEntry = forwardRef<
{children}
</TableRow>
);
});
};
+9 -9
View File
@@ -1,9 +1,8 @@
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
/**
* Copied from shadc/ui on 02/05/2025
* @see {@link https://ui.shadcn.com/docs/components/tooltip}
*/
import * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import { cn } from "utils/cn";
export const TooltipProvider = TooltipPrimitive.Provider;
@@ -16,19 +15,20 @@ export const TooltipTrigger = TooltipPrimitive.Trigger;
export const TooltipArrow = TooltipPrimitive.Arrow;
export type TooltipContentProps = React.ComponentPropsWithoutRef<
export type TooltipContentProps = React.ComponentPropsWithRef<
typeof TooltipPrimitive.Content
> & {
disablePortal?: boolean;
};
export const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
TooltipContentProps
>(({ className, sideOffset = 4, disablePortal, ...props }, ref) => {
export const TooltipContent: React.FC<TooltipContentProps> = ({
className,
sideOffset = 4,
disablePortal,
...props
}) => {
const content = (
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md bg-surface-primary px-3 py-2 text-xs font-medium text-content-secondary",
@@ -47,4 +47,4 @@ export const TooltipContent = React.forwardRef<
) : (
<TooltipPrimitive.Portal>{content}</TooltipPrimitive.Portal>
);
});
};
@@ -1,35 +1,29 @@
import { Button, type ButtonProps } from "components/Button/Button";
import { BellIcon } from "lucide-react";
import { forwardRef } from "react";
import { cn } from "utils/cn";
import { UnreadBadge } from "./UnreadBadge";
type InboxButtonProps = {
type InboxButtonProps = ButtonProps & {
unreadCount: number;
} & ButtonProps;
};
export const InboxButton = forwardRef<HTMLButtonElement, InboxButtonProps>(
({ unreadCount, ...props }, ref) => {
return (
<Button
size="icon-lg"
variant="outline"
className="relative"
ref={ref}
{...props}
>
<BellIcon />
{unreadCount > 0 && (
<UnreadBadge
count={unreadCount}
className={cn([
"[--offset:calc(var(--unread-badge-size)/2)]",
"absolute top-0 right-0 -mr-[--offset] -mt-[--offset]",
"animate-in fade-in zoom-in duration-200",
])}
/>
)}
</Button>
);
},
);
export const InboxButton: React.FC<InboxButtonProps> = ({
unreadCount,
...props
}) => {
return (
<Button size="icon-lg" variant="outline" className="relative" {...props}>
<BellIcon />
{unreadCount > 0 && (
<UnreadBadge
count={unreadCount}
className={cn([
"[--offset:calc(var(--unread-badge-size)/2)]",
"absolute top-0 right-0 -mr-[--offset] -mt-[--offset]",
"animate-in fade-in zoom-in duration-200",
])}
/>
)}
</Button>
);
};
+4 -6
View File
@@ -1,7 +1,5 @@
import { Button, type ButtonProps } from "components/Button/Button";
import { forwardRef } from "react";
export const AgentButton = forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
return <Button variant="outline" ref={ref} {...props} />;
},
);
export const AgentButton: React.FC<ButtonProps> = ({ ...props }) => {
return <Button variant="outline" {...props} />;
};
@@ -86,24 +86,14 @@ export const LicenseCard: FC<LicenseCardProps> = ({
</span>
</Stack>
{license.claims.nbf && (
<Stack
direction="column"
spacing={0}
alignItems="center"
width="134px" // standardize width of date column
>
<Stack direction="column" spacing={0} alignItems="center">
<span css={styles.secondaryMaincolor}>Valid From</span>
<span css={styles.licenseExpires} className="license-valid-from">
{dayjs.unix(license.claims.nbf).format("MMMM D, YYYY")}
</span>
</Stack>
)}
<Stack
direction="column"
spacing={0}
alignItems="center"
width="134px" // standardize width of date column
>
<Stack direction="column" spacing={0} alignItems="center">
{dayjs(license.claims.license_expires * 1000).isBefore(dayjs()) ? (
<Pill css={styles.expiredBadge} type="error">
Expired
+3 -6
View File
@@ -10,7 +10,6 @@ import {
type ComponentProps,
cloneElement,
type FC,
forwardRef,
type HTMLAttributes,
type ReactElement,
} from "react";
@@ -155,17 +154,15 @@ export const SectionLabel: FC<HTMLAttributes<HTMLHeadingElement>> = (props) => {
);
};
type PillProps = HTMLAttributes<HTMLDivElement> & {
type PillProps = React.ComponentPropsWithRef<"div"> & {
icon: ReactElement<HTMLAttributes<HTMLElement>>;
};
export const Pill = forwardRef<HTMLDivElement, PillProps>((props, ref) => {
export const Pill: React.FC<PillProps> = ({ icon, children, ...divProps }) => {
const theme = useTheme();
const { icon, children, ...divProps } = props;
return (
<div
ref={ref}
css={{
display: "inline-flex",
alignItems: "center",
@@ -184,7 +181,7 @@ export const Pill = forwardRef<HTMLDivElement, PillProps>((props, ref) => {
{children}
</div>
);
});
};
type BooleanPillProps = Omit<ComponentProps<typeof Pill>, "icon" | "value"> & {
value: boolean | null;
@@ -21,7 +21,7 @@ export const TemplateScheduleAutostart: FC<TemplateScheduleAutostartProps> = ({
onChange,
}) => {
return (
<Stack width="100%" alignItems="start" spacing={1}>
<Stack alignItems="start" spacing={1}>
<Stack
direction="row"
spacing={0}