Skip to content

Commit

Permalink
feat: separate ClickableStyles from core components (#1759)
Browse files Browse the repository at this point in the history
- unlink ClickableStyle from Button
- unlink ClickableStyle from Link
- remove code that can no longer be triggered for each component
- mark desired component API changes as deprecated where appropriate
- clean up documentation and technical guidance
- update component snapshots
- clean up props shown in storybook
  • Loading branch information
booc0mtaco authored Dec 5, 2023
1 parent 04d0da2 commit c7fc2af
Show file tree
Hide file tree
Showing 29 changed files with 1,689 additions and 1,121 deletions.
88 changes: 44 additions & 44 deletions src/components/Accordion/__snapshots__/Accordion.test.tsx.snap

Large diffs are not rendered by default.

552 changes: 535 additions & 17 deletions src/components/Button/Button.module.css

Large diffs are not rendered by default.

35 changes: 2 additions & 33 deletions src/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { StoryObj, Meta } from '@storybook/react';
import React from 'react';
import { Button } from './Button';
import { SIZES, STATUSES, VARIANTS } from '../ClickableStyle';
import { SIZES, STATUSES } from '../ClickableStyle';

import Icon from '../Icon';

Expand All @@ -21,7 +21,7 @@ export default {
control: {
type: 'select',
},
options: VARIANTS,
options: ['primary', 'secondary', 'icon'],
},
status: {
control: {
Expand Down Expand Up @@ -274,37 +274,6 @@ export const IconButtonIconOnlySmall: StoryObj<Args> = {
},
};

export const Link: StoryObj<Args> = {
args: { variant: 'link' },
};

export const LinkDisabled: StoryObj<Args> = {
args: { variant: 'link', disabled: true },
};

export const LinkRightIcon: StoryObj<Args> = {
args: {
children: (
<>
Button
<Icon
name="open-in-new"
purpose="informative"
title="opens in a new tab"
/>
</>
),
variant: 'link',
},
};

export const LinkNeutral: StoryObj<Args> = {
args: {
status: 'neutral',
variant: 'link',
},
};

export const Destructive: StoryObj<Args> = {
args: {
status: 'error',
Expand Down
60 changes: 37 additions & 23 deletions src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import clsx from 'clsx';
import type { ReactNode } from 'react';
import React, { forwardRef } from 'react';
import ClickableStyle from '../ClickableStyle';
import type { ClickableStyleProps, VariantStatus } from '../ClickableStyle';
import type { Size } from '../../util/variant-types';
import type {
PrimaryStatus,
SecondaryStatus,
IconStatus,
LinkStatus,
} from '../ClickableStyle/ClickableStyle';
import LoadingIndicator from '../LoadingIndicator';

import styles from './Button.module.css';

type ButtonHTMLElementProps = React.ButtonHTMLAttributes<HTMLButtonElement>;

type ButtonVariants = IconStatus | PrimaryStatus | SecondaryStatus | LinkStatus;

export type ButtonProps = ButtonHTMLElementProps & {
/**
* The button contents or label.
Expand All @@ -18,46 +25,44 @@ export type ButtonProps = ButtonHTMLElementProps & {
* Toggles clickable that fills the full width of its container
*/
fullWidth?: boolean;
'data-testid'?: string;
size?: ClickableStyleProps<'button'>['size'];
/**
* The size of the button on screen
*/
size?: Extract<Size, 'sm' | 'md' | 'lg'>;
/**
* Disables the field and prevents editing the contents
*/
disabled?: boolean;
/**
* Loading state passed down from higher level used to trigger loader and text change
* @deprecated - This will be removed in a future release
*/
loading?: boolean;
/**
* Determines type of clickable
* Determines type of clickable:
* - **button** The clickable is a clickable button.
* - **submit** The clickable is a submit clickable (submits form data).
* - **reset** The clickable is a reset clickable (resets the form-data to its initial values)
*/
type?: 'button' | 'reset' | 'submit';
} & VariantStatus;
'data-testid'?: string;
} & ButtonVariants;

/**
* `import {Button} from "@chanzuckerberg/eds";`
*
* Component for making buttons that do not navigate the user to another page.
*
* This component is called `Button` because it should be used to make `<button>` elements;
* however, it can be styled to look like a link.
*
* If you need to style an `<a>` element to look like a button, please use the `Link` component.
* If you need to style a different element or component (e.g. `Link` from `react-router`) to
* look like a button or link, you can use the `ClickableStyle` component.
* Component for making buttons that do not navigate the user to another page. Use button to trigger actions, menus,
* or other in-page activity.
*
* In terms of the look and feel of the component in the UI, the `Button`, and `Link`, and `ClickableStyle`
* components are exactly the same.
* - If you need to style a navigation anchor, please use the `Link` component.
* - If you need to style a different element or component to
* look like a button or link, you can use the `ClickableStyle` component.
*/
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(
{
children,
className,
fullWidth,
loading,
variant = 'secondary',
status = 'brand',
Expand All @@ -71,33 +76,42 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
const componentClassName = clsx(
// Base styles
styles['button'],
// Sizes
variant !== 'link' && [
size === 'sm' && styles['button--sm'],
size === 'md' && styles['button--md'],
size === 'lg' && styles['button--lg'],
],
// Variants
variant === 'primary' && styles['button--primary'],
variant === 'secondary' && styles['button--secondary'],
variant === 'icon' && styles['button--icon'],
variant === 'link' && styles['button--link'],
// Colors
status === 'brand' && styles['button--brand'],
status === 'neutral' && styles['button--neutral'],
status === 'success' && styles['button--success'],
status === 'warning' && styles['button--warning'],
status === 'error' && styles['button--error'],
// Other options
fullWidth && styles['button--full-width'],
disabled && styles['button--disabled'],
loading && styles['eds-is-loading'],
className,
);

return (
<ClickableStyle
as="button"
<button
className={componentClassName}
disabled={disabled}
ref={ref}
size={size}
status={status}
tabIndex={disabled ? -1 : undefined}
type={type}
variant={variant}
{...other}
>
{loading && <LoadingIndicator className="eds-is-loading" size="sm" />}
{children}
</ClickableStyle>
</button>
);
},
);
Expand Down
Loading

0 comments on commit c7fc2af

Please sign in to comment.