Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 27 additions & 23 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
import React, { DetailedHTMLProps, ButtonHTMLAttributes } from 'react';
import React, {
DetailedHTMLProps,
ButtonHTMLAttributes,
forwardRef,
} from 'react';
import clsx from 'clsx';

import type { Tint } from '../types';

interface Props
extends Readonly<
DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
>
extends Omit<
Readonly<
DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
>
>,
'ref'
> {
readonly tint?: Tint;
readonly destructive?: boolean;
}

export const Button = ({
children,
tint,
destructive,
className = '',
...props
}: Props) => (
<button
{...props}
className={clsx(
'button',
className,
tint && `button--${tint}${destructive ? '-destructive' : ''}`
)}
>
{children}
</button>
export const Button = forwardRef<HTMLButtonElement, Props>(
({ children, tint, destructive, className = '', ...props }, ref) => (
<button
{...props}
className={clsx(
'button',
className,
tint && `button--${tint}${destructive ? '-destructive' : ''}`
)}
ref={ref}
>
{children}
</button>
)
);
68 changes: 37 additions & 31 deletions src/components/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,47 @@
import React, { HTMLProps } from 'react';
import React, { forwardRef, HTMLProps } from 'react';
import clsx from 'clsx';

interface Props
extends Omit<Readonly<HTMLProps<HTMLInputElement>>, 'onChange'> {
extends Omit<Readonly<HTMLProps<HTMLInputElement>>, 'ref' | 'onChange'> {
readonly containerProps?: Readonly<HTMLProps<HTMLDivElement>>;
readonly labelProps?: Readonly<HTMLProps<HTMLLabelElement>>;
readonly onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
}

export const Checkbox = ({
children,
id,
className = '',
containerProps = {},
labelProps = {},
...props
}: Props) => {
const { className: containerClassName = '', ...containerRest } =
containerProps;
const { className: labelClassName = '', ...labelRest } = labelProps;
export const Checkbox = forwardRef<HTMLInputElement, Props>(
(
{
children,
id,
className = '',
containerProps = {},
labelProps = {},
...props
},
ref
) => {
const { className: containerClassName = '', ...containerRest } =
containerProps;
const { className: labelClassName = '', ...labelRest } = labelProps;

return (
<div {...containerRest} className={clsx('checkbox', containerClassName)}>
<input
{...props}
id={id}
type="checkbox"
className={clsx('checkbox__box', className)}
/>
return (
<div {...containerRest} className={clsx('checkbox', containerClassName)}>
<input
{...props}
id={id}
type="checkbox"
className={clsx('checkbox__box', className)}
ref={ref}
/>

<label
{...labelRest}
htmlFor={id}
className={clsx('checkbox__label', labelClassName)}
>
{children}
</label>
</div>
);
};
<label
{...labelRest}
htmlFor={id}
className={clsx('checkbox__label', labelClassName)}
>
{children}
</label>
</div>
);
}
);
90 changes: 51 additions & 39 deletions src/components/Disclosure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import React, {
ReactElement,
DetailedHTMLProps,
LiHTMLAttributes,
forwardRef,
} from 'react';
import { disclosure } from 'figma-plugin-ds';
import clsx from 'clsx';

interface DisclosureProps<T> extends Readonly<HTMLProps<HTMLUListElement>> {
interface DisclosureProps<T>
extends Omit<Readonly<HTMLProps<HTMLUListElement>>, 'ref'> {
readonly items: T[];
render(...itemData: [T, number, T[]]): ReactElement;
}

interface DisclosureItemProps
extends Readonly<
DetailedHTMLProps<LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>
Omit<
DetailedHTMLProps<LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>,
'ref'
>
> {
readonly heading: string;
readonly content: string;
Expand All @@ -25,6 +30,7 @@ interface DisclosureItemProps
readonly contentProps?: Readonly<HTMLProps<HTMLDivElement>>;
}

// TODO: forward ref
export function Disclosure<T extends object>({
items,
render,
Expand All @@ -44,45 +50,51 @@ export function Disclosure<T extends object>({
);
}

export const DisclosureItem = ({
section,
expanded,
heading,
content,
className = '',
labelProps = {},
contentProps = {},
...props
}: DisclosureItemProps) => {
const { className: labelClassName = '', ...labelRest } = labelProps;
const { className: contentClassName = '', ...contentRest } = contentProps;
export const DisclosureItem = forwardRef<HTMLLIElement, DisclosureItemProps>(
(
{
section,
expanded,
heading,
content,
className = '',
labelProps = {},
contentProps = {},
...props
},
ref
) => {
const { className: labelClassName = '', ...labelRest } = labelProps;
const { className: contentClassName = '', ...contentRest } = contentProps;

return (
<li
{...props}
className={clsx(
'disclosure__item',
className,
expanded && 'disclosure--expanded'
)}
>
<div
{...labelRest}
return (
<li
{...props}
className={clsx(
'disclosure__label',
labelClassName,
section && 'disclosure--section'
'disclosure__item',
className,
expanded && 'disclosure--expanded'
)}
ref={ref}
>
{heading}
</div>
<div
{...labelRest}
className={clsx(
'disclosure__label',
labelClassName,
section && 'disclosure--section'
)}
>
{heading}
</div>

<div
{...contentRest}
className={clsx('disclosure__content', contentClassName)}
>
{content}
</div>
</li>
);
};
<div
{...contentRest}
className={clsx('disclosure__content', contentClassName)}
>
{content}
</div>
</li>
);
}
);
41 changes: 19 additions & 22 deletions src/components/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
import React, { HTMLProps } from 'react';
import React, { forwardRef, HTMLProps } from 'react';
import clsx from 'clsx';

import type { IconName, ColorName } from '../types';

export interface Props extends Readonly<HTMLProps<HTMLDivElement>> {
export interface Props
extends Omit<Readonly<HTMLProps<HTMLDivElement>>, 'ref'> {
readonly iconName?: Readonly<IconName>;
readonly spin?: boolean;
readonly colorName?: Readonly<ColorName>;
}

export const Icon = ({
children,
iconName,
className = '',
spin,
colorName,
...props
}: Props) => (
<div
{...props}
className={clsx(
'icon',
className,
iconName && `icon--${iconName}`,
spin && 'icon--spin',
colorName && `icon--${colorName}`
)}
>
{children}
</div>
export const Icon = forwardRef<HTMLDivElement, Props>(
({ children, iconName, className = '', spin, colorName, ...props }, ref) => (
<div
{...props}
className={clsx(
'icon',
className,
iconName && `icon--${iconName}`,
spin && 'icon--spin',
colorName && `icon--${colorName}`
)}
ref={ref}
>
{children}
</div>
)
);
34 changes: 16 additions & 18 deletions src/components/IconButton.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import React, { HTMLProps } from 'react';
import React, { forwardRef, HTMLProps } from 'react';
import clsx from 'clsx';

import { Icon, Props as IconProps } from './Icon';

interface Props extends Readonly<HTMLProps<HTMLDivElement>> {
interface Props extends Omit<Readonly<HTMLProps<HTMLDivElement>>, 'ref'> {
readonly selected?: boolean;
readonly iconProps: IconProps;
}

export const IconButton = ({
selected,
className = '',
iconProps,
...props
}: Props) => (
<div
{...props}
className={clsx(
'icon-button',
className,
selected && 'icon-button--selected'
)}
>
<Icon {...iconProps} />
</div>
export const IconButton = forwardRef<HTMLDivElement, Props>(
({ selected, className = '', iconProps, ...props }, ref) => (
<div
{...props}
className={clsx(
'icon-button',
className,
selected && 'icon-button--selected'
)}
ref={ref}
>
<Icon {...iconProps} />
</div>
)
);
Loading