Skip to content

Commit

Permalink
feat(Button): add ref support
Browse files Browse the repository at this point in the history
resolves #99
  • Loading branch information
McManning committed Jul 24, 2023
1 parent 0940eb7 commit f856c96
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 56 deletions.
File renamed without changes.
File renamed without changes.
88 changes: 51 additions & 37 deletions src/controls/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,72 @@

import React, { MouseEvent } from 'react';
import React, { MouseEvent, Ref } from 'react';
import { Link } from 'react-router-dom';

export interface Props {
/** Bootstrap theme name (e.g. `danger`, `success`) */
theme?: string;
/** Bootstrap theme name (e.g. `danger`, `success`) */
theme?: string;

/** Additional class names to apply to the button */
className?: string;
/** Additional class names to apply to the button */
className?: string;

/** Should click events / link redirects be ignored */
disabled?: boolean;
/** Should click events / link redirects be ignored */
disabled?: boolean;

/**
* Button link target. Will render as a React Router <Link> if supplied.
*
* Buttons with a `to` will not execute `onClick`.
*/
to?: string;
/**
* Button link target. Will render as a React Router <Link> if supplied.
*
* Buttons with a `to` will not execute `onClick`.
*/
to?: string;

/** Click event callback */
onClick?(event: MouseEvent<HTMLButtonElement>): void;
/** Click event callback */
onClick?(event: MouseEvent<HTMLButtonElement>): void;

/** Type */
type?: 'button' | 'reset' | 'submit'
/** Type */
type?: 'button' | 'reset' | 'submit';
}

const Button: React.FC<Props> = ({
const Button = React.forwardRef<HTMLButtonElement, Props>((props, ref) => {
const {
children,
to,
theme = 'primary',
className = '',
disabled = false,
onClick = undefined,
type = 'button'
}) => {
// Sanity check for developers - make sure they do not specify `to` and `onClick` at once
if (to && onClick) {
console.warn('[Button] `onClick` property will not execute if you specify `to`. These are mutually exclusive.');
}

if (to && !disabled) {
return (
<Link role="button" to={to} className={`btn btn-${theme} ${className}`}>{children}</Link>
);
}
type = 'button',
} = props;

// Sanity check for developers - make sure they do not specify `to` and `onClick` at once
if (to && onClick) {
console.warn(
'[Button] `onClick` property will not execute if you specify `to`. These are mutually exclusive.'
);
}

if (to && !disabled) {
return (
<button type={type} disabled={disabled}
className={`btn btn-${theme} ${className}`}
onClick={!disabled ? onClick : undefined}>
{children}
</button>
<Link
ref={ref as unknown as Ref<HTMLAnchorElement>}
role="button"
to={to}
className={`btn btn-${theme} ${className}`}
>
{children}
</Link>
);
};
}

return (
<button
ref={ref}
type={type}
disabled={disabled}
className={`btn btn-${theme} ${className}`}
onClick={!disabled ? onClick : undefined}
>
{children}
</button>
);
});

export default Button;
58 changes: 39 additions & 19 deletions src/controls/DropOverlay/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,47 @@ import React, { useContext } from 'react';
import { Context } from '..';

export type Props = React.ButtonHTMLAttributes<HTMLButtonElement> & {
theme?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark' | 'outline-primary' | 'outline-secondary' | 'outline-success' | 'outline-danger' | 'outline-warning' | 'outline-info' | 'outline-light' | 'outline-dark';
}
theme?:
| 'primary'
| 'secondary'
| 'success'
| 'danger'
| 'warning'
| 'info'
| 'light'
| 'dark'
| 'outline-primary'
| 'outline-secondary'
| 'outline-success'
| 'outline-danger'
| 'outline-warning'
| 'outline-info'
| 'outline-light'
| 'outline-dark';
};

const Button: React.FC<Props> = ({ className, theme = "outline-secondary", ...props }) => {
const { id } = useContext(Context);
const Button = React.forwardRef<HTMLButtonElement, Props>((props, ref) => {
const { className, theme = 'outline-secondary', children, ...other } = props;
const { id } = useContext(Context);

const classNames = `btn btn-${theme} dropdown-toggle ${className ? className : ''}`
const classNames = `btn btn-${theme} dropdown-toggle ${
className ? className : ''
}`;

return (
<button
{...props}
className={classNames}
type="button"
id={id}
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
{props.children}
</button>
)
}
return (
<button
ref={ref}
{...other}
className={classNames}
type="button"
id={id}
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
{children}
</button>
);
});

export default Button;

0 comments on commit f856c96

Please sign in to comment.