Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { render } from '@testing-library/react';
import sinon from 'sinon';
import userEvent from '@testing-library/user-event';
import Button from '@18f/identity-document-capture/components/button';
import { render } from '../../../support/document-capture';
import Button from './button';

describe('document-capture/components/button', () => {
it('renders with default props', () => {
const { getByText } = render(<Button>Click me</Button>);

const button = getByText('Click me');
const button = getByText('Click me') as HTMLButtonElement;
userEvent.click(button);

expect(button.nodeName).to.equal('BUTTON');
Expand Down Expand Up @@ -88,7 +88,7 @@ describe('document-capture/components/button', () => {
</Button>,
);

const button = getByText('Click me');
const button = getByText('Click me') as HTMLButtonElement;
userEvent.click(button);

expect(onClick.calledOnce).to.be.false();
Expand All @@ -103,7 +103,7 @@ describe('document-capture/components/button', () => {
</Button>,
);

const button = getByText('Click me');
const button = getByText('Click me') as HTMLButtonElement;

expect(button.classList.contains('usa-button--disabled'));
expect(button.disabled).to.be.false();
Expand All @@ -115,7 +115,7 @@ describe('document-capture/components/button', () => {
it('renders with custom type', () => {
const { getByText } = render(<Button type="submit">Click me</Button>);

const button = getByText('Click me');
const button = getByText('Click me') as HTMLButtonElement;

expect(button.type).to.equal('submit');
});
Expand Down
97 changes: 97 additions & 0 deletions app/javascript/packages/components/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import type { MouseEvent, ReactNode } from 'react';

type ButtonType = 'button' | 'reset' | 'submit';

export interface ButtonProps {
/**
* Button type, defaulting to "button".
*/
type?: ButtonType;

/**
* Click handler.
*/
onClick?: (event: MouseEvent) => void;

/**
* Element children.
*/
children?: ReactNode;

/**
* Whether button should be styled as big button.
*/
isBig?: boolean;

/**
* Whether button should be styled as flexible width, such that it shrinks to its minimum width instead of occupying full-width on mobile viewports.
*/
isFlexibleWidth?: boolean;

/**
* Whether button should be styled as primary button.
*/
isWide?: boolean;

/**
* Whether button should be styled as secondary button.
*/
isOutline?: boolean;

/**
* Whether button is disabled.
*/
isDisabled?: boolean;

/**
* Whether button should be unstyled, visually as a link.
*/
isUnstyled?: boolean;

/**
* Whether button should appear disabled (but remain clickable).
*/
isVisuallyDisabled?: boolean;

/**
* Optional additional class names.
*/
className?: string;
}

function Button({
type = 'button',
onClick,
children,
isBig,
isFlexibleWidth,
isWide,
isOutline,
isDisabled,
isUnstyled,
isVisuallyDisabled,
className,
}: ButtonProps) {
const classes = [
'usa-button',
isBig && 'usa-button--big',
isFlexibleWidth && 'usa-button--flexible-width',
isWide && 'usa-button--wide',
isOutline && 'usa-button--outline',
isUnstyled && 'usa-button--unstyled',
isVisuallyDisabled && 'usa-button--disabled',
className,
]
.filter(Boolean)
.join(' ');

return (
// Disable reason: We can assume `type` is provided as valid, or the default `button`.
// eslint-disable-next-line react/button-has-type
<button type={type} onClick={onClick} disabled={isDisabled} className={classes}>
{children}
</button>
);
}

export default Button;
1 change: 1 addition & 0 deletions app/javascript/packages/components/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { default as Alert } from './alert';
export { default as Button } from './button';
export { default as BlockLink } from './block-link';
export { default as Icon } from './icon';
export { default as SpinnerDots } from './spinner-dots';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import {
} from 'react';
import { useI18n } from '@18f/identity-react-i18n';
import { useIfStillMounted, useDidUpdateEffect } from '@18f/identity-react-hooks';
import { Button } from '@18f/identity-components';
import AnalyticsContext from '../context/analytics';
import AcuantContext from '../context/acuant';
import FailedCaptureAttemptsContext from '../context/failed-capture-attempts';
import AcuantCamera from './acuant-camera';
import AcuantCaptureCanvas from './acuant-capture-canvas';
import FileInput from './file-input';
import FullScreen from './full-screen';
import Button from './button';
import DeviceContext from '../context/device';
import UploadContext from '../context/upload';
import useCounter from '../hooks/use-counter';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useContext, useRef } from 'react';
import { createPortal } from 'react-dom';
import { Button } from '@18f/identity-components';
import UploadContext from '../context/upload';
import Button from './button';

/** @typedef {import('./button').ButtonProps} ButtonProps */
/** @typedef {import('@18f/identity-components/button').ButtonProps} ButtonProps */

/**
* @typedef NativeButtonToProps
Expand Down
60 changes: 0 additions & 60 deletions app/javascript/packages/document-capture/components/button.jsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useEffect, useRef, useState, createContext, useContext } from 'react';
import type { RefCallback, FormEventHandler, FC } from 'react';
import { useI18n } from '@18f/identity-react-i18n';
import { Alert } from '@18f/identity-components';
import { Alert, Button } from '@18f/identity-components';
import { useDidUpdateEffect, useIfStillMounted } from '@18f/identity-react-hooks';
import Button from './button';
import FormErrorMessage, { RequiredValueMissingError } from './form-error-message';
import PromptOnNavigate from './prompt-on-navigate';
import useHistoryParam from '../hooks/use-history-param';
Expand Down