Skip to content

Commit

Permalink
feat: button-style anchor (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
juanfabrega authored Oct 2, 2020
1 parent cc4916a commit 6f7b2e7
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/components/Button/Button.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
border-radius: var(--button-size-md-border-radius);
cursor: pointer;
padding: var(--button-size-md-padding-vertical) var(--button-size-md-padding-horizontal);
text-decoration: none;
line-height: 1.25;
letter-spacing: 0.2px;
font-size: var(--button-size-md-font-size);
Expand Down
13 changes: 13 additions & 0 deletions src/components/Button/Button.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,16 @@ Callback functions can be passed to `onClick`, `onBlur`, and `onFocus` events.
</Button>
</Story>
</Canvas>

## As an Anchor

You can render an anchor tag with the style of a button by passing an href attribute.
The props API when using an anchor will be the same as a standard HTML anchor.

<Canvas>
<Story name="As an Anchor">
<Button href="https://ux.palmetto.com" target="_blank">
I'm an anchor tag
</Button>
</Story>
</Canvas>
11 changes: 11 additions & 0 deletions src/components/Button/Button.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@ describe('Button', () => {
expect(buttonElement).toBeInTheDocument();
});

test('it renders an anchor tag if an href attribute is passed as a prop', () => {
render(
<Button href="http://palmetto.com">
hey there
</Button>,
);
const buttonElement = screen.getByRole('link');

expect(buttonElement).toBeInTheDocument();
});

test('it does not have a disabled attribute', () => {
render(
<Button>
Expand Down
58 changes: 40 additions & 18 deletions src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ interface ButtonProps {
* A unique identifier for the button.
*/
id?: string;
/**
* URL to navigate to when clicked. Passing this attribute automatically
* renders an anchor <a> tag, NOT a <button> element.
*/
href?: string;
/**
* Disables the button, making it inoperable.
*/
Expand Down Expand Up @@ -52,11 +57,11 @@ interface ButtonProps {
/**
* Callback when focus leaves Button.
*/
onBlur?: (event: FocusEvent<HTMLButtonElement>) => void;
onBlur?: (event: FocusEvent<HTMLButtonElement | HTMLAnchorElement>) => void;
/**
* Callback when Button receives focus.
*/
onFocus?: (event: FocusEvent<HTMLButtonElement>) => void;
onFocus?: (event: FocusEvent<HTMLButtonElement | HTMLAnchorElement>) => void;
/**
* The size of the button.
*/
Expand All @@ -72,6 +77,7 @@ const Button: FC<ButtonProps> = ({
className = '',
fullWidth = false,
id = undefined,
href = undefined,
isDisabled = false,
isLoading = false,
isOutlined = false,
Expand All @@ -82,6 +88,7 @@ const Button: FC<ButtonProps> = ({
onBlur = undefined,
size = 'md',
variant = 'primary',
...restProps
}) => {
const disabled = isLoading || isDisabled;

Expand All @@ -101,11 +108,11 @@ const Button: FC<ButtonProps> = ({
if (onClick) onClick(event);
};

const handleFocus = (event: FocusEvent<HTMLButtonElement>) => {
const handleFocus = (event: FocusEvent<HTMLButtonElement | HTMLAnchorElement>) => {
if (onFocus) onFocus(event);
};

const handleBlur = (event: FocusEvent<HTMLButtonElement>) => {
const handleBlur = (event: FocusEvent<HTMLButtonElement | HTMLAnchorElement>) => {
if (onBlur) onBlur(event);
};

Expand All @@ -125,20 +132,35 @@ const Button: FC<ButtonProps> = ({
);

return (
<button
id={id}
type={type} // eslint-disable-line react/button-has-type
disabled={disabled}
className={buttonClasses}
onClick={handleClick}
onFocus={handleFocus}
onBlur={handleBlur}
tabIndex={tabIndex}
aria-label={isLoading ? 'Loading' : undefined}
aria-busy={isLoading}
>
{content}
</button>
href ? (
<a
href={href}
className={buttonClasses}
id={id}
onFocus={handleFocus}
onBlur={handleBlur}
tabIndex={tabIndex}
{...restProps}
>
{content}
</a>
) : (
<button
id={id}
type={type} // eslint-disable-line react/button-has-type
disabled={disabled}
className={buttonClasses}
onClick={handleClick}
onFocus={handleFocus}
onBlur={handleBlur}
tabIndex={tabIndex}
aria-label={isLoading ? 'Loading' : undefined}
aria-busy={isLoading}
{...restProps}
>
{content}
</button>
)
);
};

Expand Down

0 comments on commit 6f7b2e7

Please sign in to comment.