Skip to content

Commit

Permalink
Remove React.forwardRef
Browse files Browse the repository at this point in the history
  • Loading branch information
timoclsn committed Jun 7, 2024
1 parent e504ff9 commit ab08258
Show file tree
Hide file tree
Showing 17 changed files with 690 additions and 703 deletions.
72 changes: 32 additions & 40 deletions src/design-system/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { VariantProps, cva } from 'cva';
import { ElementType, ReactNode, forwardRef } from 'react';
import { ElementType, ReactNode, RefObject } from 'react';

const styles = cva({
base: 'inline-flex items-center justify-center gap-2 leading-none whitespace-nowrap focus-visible:outline-2 outline-offset-2',
Expand Down Expand Up @@ -68,44 +68,36 @@ export interface ButtonProps extends VariantProps<typeof styles> {
href?: string;
external?: boolean;
className?: string;
ref?: RefObject<HTMLButtonElement | HTMLAnchorElement>;
}

export const Button = forwardRef<
HTMLButtonElement | HTMLAnchorElement,
ButtonProps
>(
(
{
children,
as,
variant = 'contained',
color = 'primary',
size = 'medium',
type = 'button',
onClick,
disabled,
href,
external,
className,
},
ref,
) => {
const Element = as ? as : href ? 'a' : 'button';
return (
<Element
ref={ref}
className={styles({ variant, size, color, className })}
type={Element === 'button' ? type : undefined}
onClick={onClick}
disabled={disabled}
href={href}
target={external ? '_blank' : undefined}
rel={external ? 'noopener' : undefined}
>
{children}
</Element>
);
},
);

Button.displayName = 'Button';
export const Button = ({
children,
as,
variant = 'contained',
color = 'primary',
size = 'medium',
type = 'button',
onClick,
disabled,
href,
external,
className,
ref,
}: ButtonProps) => {
const Element = as ? as : href ? 'a' : 'button';
return (
<Element
ref={ref}
className={styles({ variant, size, color, className })}
type={Element === 'button' ? type : undefined}
onClick={onClick}
disabled={disabled}
href={href}
target={external ? '_blank' : undefined}
rel={external ? 'noopener' : undefined}
>
{children}
</Element>
);
};
33 changes: 17 additions & 16 deletions src/design-system/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,51 @@
import * as DialogPrimitive from '@radix-ui/react-dialog';
import { cx } from 'cva';
import { X } from 'lucide-react';
import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react';
import { ComponentProps } from 'react';

export const Dialog = DialogPrimitive.Root;
export const DialogTrigger = DialogPrimitive.Trigger;
export const DialogPortal = DialogPrimitive.Portal;

export const DialogOverlay = forwardRef<
ElementRef<typeof DialogPrimitive.Overlay>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
export const DialogOverlay = ({
className,
ref,
...props
}: ComponentProps<typeof DialogPrimitive.Overlay>) => (
<DialogPrimitive.Overlay
ref={ref}
className={cx(
'bg-stone data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 opacity-50',
'fixed inset-0 z-50 bg-stone opacity-50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
className,
)}
{...props}
/>
));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
);

export const DialogContent = forwardRef<
ElementRef<typeof DialogPrimitive.Content>,
ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
export const DialogContent = ({
className,
children,
ref,
...props
}: ComponentProps<typeof DialogPrimitive.Content>) => (
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cx(
'bg-bg-primary 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 overflow-y-auto border p-6 shadow-lg duration-200 sm:rounded-lg md:w-full',
'fixed left-[50%] top-[50%] z-50 w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 overflow-y-auto border bg-bg-primary p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full',
className,
)}
{...props}
>
{children}
<DialogPrimitive.Close className="ring-offset-background focus-visible:ring-ring ease absolute right-4 top-4 rounded-sm opacity-70 transition-all hover:scale-110 hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 active:scale-90 disabled:pointer-events-none">
<DialogPrimitive.Close className="ease absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-all hover:scale-110 hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 active:scale-90 disabled:pointer-events-none">
<X size={18} />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPortal>
));
DialogContent.displayName = DialogPrimitive.Content.displayName;
);

export const DialogClose = DialogPrimitive.Close;
export const DialogTitle = DialogPrimitive.Title;
Expand Down
89 changes: 46 additions & 43 deletions src/design-system/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,43 @@ import {
Loader2,
XCircle,
} from 'lucide-react';
import {
ComponentProps,
ComponentPropsWithoutRef,
ElementRef,
forwardRef,
useId,
} from 'react';
import { ComponentProps, useId } from 'react';

export const Select = ({
...props
}: ComponentProps<typeof SelectPrimitive.Root>) => (
<SelectPrimitive.Root {...props} />
);

Select.FilterTrigger = forwardRef<
ElementRef<typeof SelectPrimitive.Trigger>,
ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> & {
label: string;
isLoading?: boolean;
isResettable?: boolean;
onReset?: () => void;
}
>(function SelectFilterTrigger(
{ className, disabled, label, isLoading, isResettable, onReset, ...props },
Select.FilterTrigger = function SelectFilterTrigger({
className,
disabled,
label,
isLoading,
isResettable,
onReset,
ref,
) {
...props
}: ComponentProps<typeof SelectPrimitive.Trigger> & {
label: string;
isLoading?: boolean;
isResettable?: boolean;
onReset?: () => void;
}) {
const id = useId();
return (
<div className="relative min-w-[0px] flex-1 sm:max-w-[240px]">
<Label
htmlFor={id}
className="bg-bg-primary text-text-secondary absolute -top-1.5 left-5 px-1 text-xs leading-none"
className="absolute -top-1.5 left-5 bg-bg-primary px-1 text-xs leading-none text-text-secondary"
>
{!disabled && label}
</Label>
<SelectPrimitive.Trigger
id={id}
disabled={disabled}
className={cx(
'border-ghost-main-dark-bg focus-visible:border-text-secondary flex w-full items-center justify-between rounded-full border-2 px-2 py-2 text-left text-lg font-bold leading-none outline-none disabled:opacity-50 sm:gap-1 sm:px-6 [&>span]:truncate [&>span]:whitespace-nowrap',
'flex w-full items-center justify-between rounded-full border-2 border-ghost-main-dark-bg px-2 py-2 text-left text-lg font-bold leading-none outline-none focus-visible:border-text-secondary disabled:opacity-50 sm:gap-1 sm:px-6 [&>span]:truncate [&>span]:whitespace-nowrap',
className,
)}
{...props}
Expand All @@ -68,7 +65,7 @@ Select.FilterTrigger = forwardRef<
{!isLoading && (
<SelectPrimitive.Icon
className={`text-text-secondary flex-none${
isResettable ? ' opacity-0' : ''
isResettable ? 'opacity-0' : ''
}`}
>
<ArrowDown />
Expand All @@ -80,7 +77,7 @@ Select.FilterTrigger = forwardRef<
{/* Reset Button */}
{isResettable && !isLoading && (
<button
className="text-text-secondary ease active:scale-9 absolute right-0 top-0 mr-2 flex h-full items-center justify-center transition-transform hover:scale-110 sm:mr-6"
className="ease active:scale-9 absolute right-0 top-0 mr-2 flex h-full items-center justify-center text-text-secondary transition-transform hover:scale-110 sm:mr-6"
onClick={onReset}
>
<XCircle />
Expand All @@ -89,14 +86,16 @@ Select.FilterTrigger = forwardRef<
)}
</div>
);
});
};

Select.SortTrigger = forwardRef<
ElementRef<typeof SelectPrimitive.Trigger>,
ComponentPropsWithoutRef<typeof SelectPrimitive.SelectTrigger> & {
isLoading?: boolean;
}
>(function SelectSortTrigger({ className, isLoading, ...props }, ref) {
Select.SortTrigger = function SelectSortTrigger({
className,
isLoading,
ref,
...props
}: ComponentProps<typeof SelectPrimitive.SelectTrigger> & {
isLoading?: boolean;
}) {
const id = useId();
return (
<div className="flex items-center">
Expand All @@ -117,24 +116,26 @@ Select.SortTrigger = forwardRef<
{isLoading ? (
<Loader2 size={20} className="flex-none animate-spin opacity-60" />
) : (
<SelectPrimitive.Icon className="text-text-secondary flex-none">
<SelectPrimitive.Icon className="flex-none text-text-secondary">
<ChevronDown />
</SelectPrimitive.Icon>
)}
</SelectPrimitive.Trigger>
</div>
);
});
};

Select.Content = forwardRef<
ElementRef<typeof SelectPrimitive.Content>,
ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(function SelectContent({ children, className, ...props }, ref) {
Select.Content = function SelectContent({
children,
className,
ref,
...props
}: ComponentProps<typeof SelectPrimitive.Content>) {
return (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
className={cx(
'bg-primary-main-bg text-primary-contrast-text animate-in fade-in-75 zoom-in-90 z-20 rounded-2xl px-4 py-6 duration-100 ease-out',
'z-20 rounded-2xl bg-primary-main-bg px-4 py-6 text-primary-contrast-text duration-100 ease-out animate-in fade-in-75 zoom-in-90',
className,
)}
{...props}
Expand All @@ -152,16 +153,18 @@ Select.Content = forwardRef<
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
);
});
};

Select.Item = forwardRef<
ElementRef<typeof SelectPrimitive.Item>,
ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(function SelectItem({ children, className, ...props }, ref) {
Select.Item = function SelectItem({
children,
className,
ref,
...props
}: ComponentProps<typeof SelectPrimitive.Item>) {
return (
<SelectPrimitive.Item
className={cx(
'hover:bg-primary-contrast-text hover:text-primary-main-bg focus-visible:bg-primary-contrast-text focus-visible:text-primary-main-bg cursor-pointer rounded-lg py-1 pl-[29px] pr-2 outline-none',
'cursor-pointer rounded-lg py-1 pl-[29px] pr-2 outline-none hover:bg-primary-contrast-text hover:text-primary-main-bg focus-visible:bg-primary-contrast-text focus-visible:text-primary-main-bg',
className,
)}
{...props}
Expand All @@ -175,4 +178,4 @@ Select.Item = forwardRef<
</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
);
});
};
Loading

0 comments on commit ab08258

Please sign in to comment.