fix(Button): redesign of existing Button component for consistency (#3473)

This commit is contained in:
Joe Boccanfuso 2023-06-15 12:58:21 -04:00 committed by GitHub
parent 3dce70e624
commit cc73f15c8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 738 additions and 397 deletions

View File

@ -1,3 +1,4 @@
import { ButtonEnums } from '@ohif/ui';
import hydrateRTDisplaySet from './_hydrateRT'; import hydrateRTDisplaySet from './_hydrateRT';
const RESPONSE = { const RESPONSE = {
@ -38,12 +39,12 @@ function _askHydrate(uiViewportDialogService, viewportIndex) {
const message = 'Do you want to open this Segmentation?'; const message = 'Do you want to open this Segmentation?';
const actions = [ const actions = [
{ {
type: 'secondary', type: ButtonEnums.type.secondary,
text: 'No', text: 'No',
value: RESPONSE.CANCEL, value: RESPONSE.CANCEL,
}, },
{ {
type: 'primary', type: ButtonEnums.type.primary,
text: 'Yes', text: 'Yes',
value: RESPONSE.HYDRATE_SEG, value: RESPONSE.HYDRATE_SEG,
}, },

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Input, Dialog } from '@ohif/ui'; import { Input, Dialog, ButtonEnums } from '@ohif/ui';
function callInputDialog(uiDialogService, label, callback) { function callInputDialog(uiDialogService, label, callback) {
const dialogId = 'enter-segment-label'; const dialogId = 'enter-segment-label';
@ -29,8 +29,8 @@ function callInputDialog(uiDialogService, label, callback) {
noCloseButton: true, noCloseButton: true,
onClose: () => uiDialogService.dismiss({ id: dialogId }), onClose: () => uiDialogService.dismiss({ id: dialogId }),
actions: [ actions: [
{ id: 'cancel', text: 'Cancel', type: 'primary' }, { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Confirm', type: 'secondary' }, { id: 'save', text: 'Confirm', type: ButtonEnums.type.primary },
], ],
onSubmit: onSubmitHandler, onSubmit: onSubmitHandler,
body: ({ value, setValue }) => { body: ({ value, setValue }) => {

View File

@ -1,3 +1,4 @@
import { ButtonEnums } from '@ohif/ui';
import hydrateSEGDisplaySet from './_hydrateSEG'; import hydrateSEGDisplaySet from './_hydrateSEG';
const RESPONSE = { const RESPONSE = {
@ -6,11 +7,7 @@ const RESPONSE = {
HYDRATE_SEG: 5, HYDRATE_SEG: 5,
}; };
function promptHydrateSEG({ function promptHydrateSEG({ servicesManager, segDisplaySet, viewportIndex }) {
servicesManager,
segDisplaySet,
viewportIndex,
}) {
const { uiViewportDialogService } = servicesManager.services; const { uiViewportDialogService } = servicesManager.services;
return new Promise(async function(resolve, reject) { return new Promise(async function(resolve, reject) {
@ -36,12 +33,12 @@ function _askHydrate(uiViewportDialogService, viewportIndex) {
const message = 'Do you want to open this Segmentation?'; const message = 'Do you want to open this Segmentation?';
const actions = [ const actions = [
{ {
type: 'secondary', type: ButtonEnums.type.secondary,
text: 'No', text: 'No',
value: RESPONSE.CANCEL, value: RESPONSE.CANCEL,
}, },
{ {
type: 'primary', type: ButtonEnums.type.primary,
text: 'Yes', text: 'Yes',
value: RESPONSE.HYDRATE_SEG, value: RESPONSE.HYDRATE_SEG,
}, },

View File

@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import DicomFileUploader from '../../utils/DicomFileUploader'; import DicomFileUploader from '../../utils/DicomFileUploader';
import DicomUploadProgress from './DicomUploadProgress'; import DicomUploadProgress from './DicomUploadProgress';
import { Button } from '@ohif/ui'; import { Button, ButtonEnums } from '@ohif/ui';
import './DicomUpload.css'; import './DicomUpload.css';
type DicomUploadProps = { type DicomUploadProps = {
@ -46,12 +46,7 @@ function DicomUpload({
<Dropzone onDrop={onDrop} noDrag> <Dropzone onDrop={onDrop} noDrag>
{({ getRootProps, getInputProps }) => ( {({ getRootProps, getInputProps }) => (
<div {...getRootProps()}> <div {...getRootProps()}>
<Button <Button disabled={false} onClick={() => {}}>
variant="contained"
color="primary"
disabled={false}
onClick={() => {}}
>
{'Add files'} {'Add files'}
<input {...getInputProps()} /> <input {...getInputProps()} />
</Button> </Button>
@ -62,9 +57,7 @@ function DicomUpload({
{({ getRootProps, getInputProps }) => ( {({ getRootProps, getInputProps }) => (
<div {...getRootProps()}> <div {...getRootProps()}>
<Button <Button
variant="contained" type={ButtonEnums.type.secondary}
color="primaryDark"
border="primaryActive"
disabled={false} disabled={false}
onClick={() => {}} onClick={() => {}}
> >

View File

@ -308,13 +308,7 @@ function DicomUploadProgress({
} ${ } ${
dicomFileUploaderArr.length > 1 ? 'files' : 'file' dicomFileUploaderArr.length > 1 ? 'files' : 'file'
} completed.`}</span> } completed.`}</span>
<Button <Button disabled={false} className="ml-auto" onClick={onComplete}>
variant="contained"
color="primary"
disabled={false}
className="ml-auto"
onClick={onComplete}
>
{'Close'} {'Close'}
</Button> </Button>
</> </>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Input, Dialog } from '@ohif/ui'; import { Input, Dialog, ButtonEnums } from '@ohif/ui';
/** /**
* *
@ -60,8 +60,8 @@ function callInputDialog(
noCloseButton: true, noCloseButton: true,
onClose: () => uiDialogService.dismiss({ id: dialogId }), onClose: () => uiDialogService.dismiss({ id: dialogId }),
actions: [ actions: [
{ id: 'cancel', text: 'Cancel', type: 'primary' }, { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: 'secondary' }, { id: 'save', text: 'Save', type: ButtonEnums.type.primary },
], ],
onSubmit: onSubmitHandler, onSubmit: onSubmitHandler,
body: ({ value, setValue }) => { body: ({ value, setValue }) => {

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Button, ButtonGroup } from '@ohif/ui'; import { LegacyButton, ButtonGroup } from '@ohif/ui';
function ActionButtons({ onExportClick, onCreateReportClick }) { function ActionButtons({ onExportClick, onCreateReportClick }) {
const { t } = useTranslation('MeasurementTable'); const { t } = useTranslation('MeasurementTable');
@ -10,12 +10,16 @@ function ActionButtons({ onExportClick, onCreateReportClick }) {
return ( return (
<React.Fragment> <React.Fragment>
<ButtonGroup color="black" size="inherit"> <ButtonGroup color="black" size="inherit">
<Button className="px-2 py-2 text-base" onClick={onExportClick}> {/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<LegacyButton className="px-2 py-2 text-base" onClick={onExportClick}>
{t('Export CSV')} {t('Export CSV')}
</Button> </LegacyButton>
<Button className="px-2 py-2 text-base" onClick={onCreateReportClick}> <LegacyButton
className="px-2 py-2 text-base"
onClick={onCreateReportClick}
>
{t('Create Report')} {t('Create Report')}
</Button> </LegacyButton>
</ButtonGroup> </ButtonGroup>
</React.Fragment> </React.Fragment>
); );

View File

@ -3,7 +3,7 @@ import classnames from 'classnames';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useAppConfig } from '@state'; import { useAppConfig } from '@state';
import { Button } from '@ohif/ui'; import { Button, ButtonEnums } from '@ohif/ui';
function DataSourceSelector() { function DataSourceSelector() {
const [appConfig] = useAppConfig(); const [appConfig] = useAppConfig();
@ -33,7 +33,8 @@ function DataSourceSelector() {
<div key={ds.sourceName}> <div key={ds.sourceName}>
<h1 className="text-white">{ds.friendlyName}</h1> <h1 className="text-white">{ds.friendlyName}</h1>
<Button <Button
className={classnames('font-bold', 'ml-2')} type={ButtonEnums.type.primary}
className={classnames('ml-2')}
onClick={() => { onClick={() => {
navigate({ navigate({
pathname: '/', pathname: '/',

View File

@ -1,7 +1,13 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { utils, ServicesManager } from '@ohif/core'; import { utils, ServicesManager } from '@ohif/core';
import { MeasurementTable, Dialog, Input, useViewportGrid } from '@ohif/ui'; import {
MeasurementTable,
Dialog,
Input,
useViewportGrid,
ButtonEnums,
} from '@ohif/ui';
import ActionButtons from './ActionButtons'; import ActionButtons from './ActionButtons';
import debounce from 'lodash.debounce'; import debounce from 'lodash.debounce';
@ -189,9 +195,8 @@ export default function PanelMeasurementTable({
); );
}, },
actions: [ actions: [
// temp: swap button types until colors are updated { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'cancel', text: 'Cancel', type: 'primary' }, { id: 'save', text: 'Save', type: ButtonEnums.type.primary },
{ id: 'save', text: 'Save', type: 'secondary' },
], ],
onSubmit: onSubmitHandler, onSubmit: onSubmitHandler,
}, },

View File

@ -1,6 +1,6 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import React from 'react'; import React from 'react';
import { Dialog, Input, Select } from '@ohif/ui'; import { ButtonEnums, Dialog, Input, Select } from '@ohif/ui';
export const CREATE_REPORT_DIALOG_RESPONSE = { export const CREATE_REPORT_DIALOG_RESPONSE = {
CANCEL: 0, CANCEL: 0,
@ -81,8 +81,8 @@ export default function createReportDialogPrompt(
noCloseButton: true, noCloseButton: true,
onClose: _handleClose, onClose: _handleClose,
actions: [ actions: [
{ id: 'cancel', text: 'Cancel', type: 'primary' }, { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: 'secondary' }, { id: 'save', text: 'Save', type: ButtonEnums.type.primary },
], ],
// TODO: Should be on button press... // TODO: Should be on button press...
onSubmit: _handleFormSubmit, onSubmit: _handleFormSubmit,

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Input, Dialog } from '@ohif/ui'; import { Input, Dialog, ButtonEnums } from '@ohif/ui';
/** /**
* *
@ -14,7 +14,7 @@ export default function callInputDialog({
uiDialogService, uiDialogService,
title = 'Annotation', title = 'Annotation',
defaultValue = '', defaultValue = '',
callback = (value: string, action: string) => {} callback = (value: string, action: string) => {},
}) { }) {
const dialogId = 'microscopy-input-dialog'; const dialogId = 'microscopy-input-dialog';
@ -43,8 +43,8 @@ export default function callInputDialog({
noCloseButton: true, noCloseButton: true,
onClose: () => uiDialogService.dismiss({ id: dialogId }), onClose: () => uiDialogService.dismiss({ id: dialogId }),
actions: [ actions: [
{ id: 'cancel', text: 'Cancel', type: 'primary' }, { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: 'secondary' }, { id: 'save', text: 'Save', type: ButtonEnums.type.primary },
], ],
onSubmit: onSubmitHandler, onSubmit: onSubmitHandler,
body: ({ value, setValue }) => { body: ({ value, setValue }) => {

View File

@ -1,6 +1,6 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import React from 'react'; import React from 'react';
import { Dialog, Input } from '@ohif/ui'; import { ButtonEnums, Dialog, Input } from '@ohif/ui';
import RESPONSE from './PROMPT_RESPONSES'; import RESPONSE from './PROMPT_RESPONSES';
export default function createReportDialogPrompt(uiDialogService) { export default function createReportDialogPrompt(uiDialogService) {
@ -43,8 +43,8 @@ export default function createReportDialogPrompt(uiDialogService) {
noCloseButton: true, noCloseButton: true,
onClose: _handleClose, onClose: _handleClose,
actions: [ actions: [
{ id: 'cancel', text: 'Cancel', type: 'primary' }, { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'save', text: 'Save', type: 'secondary' }, { id: 'save', text: 'Save', type: ButtonEnums.type.primary },
], ],
// TODO: Should be on button press... // TODO: Should be on button press...
onSubmit: _handleFormSubmit, onSubmit: _handleFormSubmit,

View File

@ -1,3 +1,5 @@
import { ButtonEnums } from '@ohif/ui';
const RESPONSE = { const RESPONSE = {
NO_NEVER: -1, NO_NEVER: -1,
CANCEL: 0, CANCEL: 0,
@ -31,19 +33,19 @@ function _askTrackMeasurements(uiViewportDialogService, viewportIndex) {
const actions = [ const actions = [
{ {
id: 'prompt-begin-tracking-cancel', id: 'prompt-begin-tracking-cancel',
type: 'cancel', type: ButtonEnums.type.secondary,
text: 'No', text: 'No',
value: RESPONSE.CANCEL, value: RESPONSE.CANCEL,
}, },
{ {
id: 'prompt-begin-tracking-no-do-not-ask-again', id: 'prompt-begin-tracking-no-do-not-ask-again',
type: 'secondary', type: ButtonEnums.type.secondary,
text: 'No, do not ask again', text: 'No, do not ask again',
value: RESPONSE.NO_NEVER, value: RESPONSE.NO_NEVER,
}, },
{ {
id: 'prompt-begin-tracking-yes', id: 'prompt-begin-tracking-yes',
type: 'primary', type: ButtonEnums.type.primary,
text: 'Yes', text: 'Yes',
value: RESPONSE.SET_STUDY_AND_SERIES, value: RESPONSE.SET_STUDY_AND_SERIES,
}, },

View File

@ -1,4 +1,5 @@
import { hydrateStructuredReport } from '@ohif/extension-cornerstone-dicom-sr'; import { hydrateStructuredReport } from '@ohif/extension-cornerstone-dicom-sr';
import { ButtonEnums } from '@ohif/ui';
const RESPONSE = { const RESPONSE = {
NO_NEVER: -1, NO_NEVER: -1,
@ -61,12 +62,12 @@ function _askTrackMeasurements(uiViewportDialogService, viewportIndex) {
'Do you want to continue tracking measurements for this study?'; 'Do you want to continue tracking measurements for this study?';
const actions = [ const actions = [
{ {
type: 'secondary', type: ButtonEnums.type.secondary,
text: 'No', text: 'No',
value: RESPONSE.CANCEL, value: RESPONSE.CANCEL,
}, },
{ {
type: 'primary', type: ButtonEnums.type.primary,
text: 'Yes', text: 'Yes',
value: RESPONSE.HYDRATE_REPORT, value: RESPONSE.HYDRATE_REPORT,
}, },

View File

@ -1,3 +1,5 @@
import { ButtonEnums } from '@ohif/ui';
const RESPONSE = { const RESPONSE = {
NO_NEVER: -1, NO_NEVER: -1,
CANCEL: 0, CANCEL: 0,
@ -38,14 +40,18 @@ function _askShouldAddMeasurements(uiViewportDialogService, viewportIndex) {
const message = const message =
'Do you want to add this measurement to the existing report?'; 'Do you want to add this measurement to the existing report?';
const actions = [ const actions = [
{ type: 'cancel', text: 'Cancel', value: RESPONSE.CANCEL },
{ {
type: 'secondary', type: ButtonEnums.type.secondary,
text: 'Cancel',
value: RESPONSE.CANCEL,
},
{
type: ButtonEnums.type.primary,
text: 'Create new report', text: 'Create new report',
value: RESPONSE.CREATE_REPORT, value: RESPONSE.CREATE_REPORT,
}, },
{ {
type: 'primary', type: ButtonEnums.type.primary,
text: 'Add to existing report', text: 'Add to existing report',
value: RESPONSE.ADD_SERIES, value: RESPONSE.ADD_SERIES,
}, },

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Button, ButtonGroup } from '@ohif/ui'; import { Button, ButtonEnums } from '@ohif/ui';
function ActionButtons({ onExportClick, onCreateReportClick, disabled }) { function ActionButtons({ onExportClick, onCreateReportClick, disabled }) {
const { t } = useTranslation('MeasurementTable'); const { t } = useTranslation('MeasurementTable');
@ -10,23 +10,18 @@ function ActionButtons({ onExportClick, onCreateReportClick, disabled }) {
return ( return (
<React.Fragment> <React.Fragment>
<Button <Button
className="text-base px-2 py-2"
size="initial"
variant={disabled ? 'disabled' : 'outlined'}
color="black"
border="primaryActive"
onClick={onExportClick} onClick={onExportClick}
disabled={disabled} disabled={disabled}
type={ButtonEnums.type.secondary}
size={ButtonEnums.size.small}
> >
{t('Export')} {t('Export')}
</Button> </Button>
<Button <Button
className="ml-2 px-2 text-base" className="ml-2"
variant={disabled ? 'disabled' : 'outlined'}
size="initial"
color="black"
border="primaryActive"
onClick={onCreateReportClick} onClick={onCreateReportClick}
type={ButtonEnums.type.secondary}
size={ButtonEnums.size.small}
disabled={disabled} disabled={disabled}
> >
{t('Create Report')} {t('Create Report')}

View File

@ -6,6 +6,7 @@ import {
Dialog, Dialog,
Input, Input,
useViewportGrid, useViewportGrid,
ButtonEnums,
} from '@ohif/ui'; } from '@ohif/ui';
import { DicomMetadataStore, utils } from '@ohif/core'; import { DicomMetadataStore, utils } from '@ohif/core';
import { useDebounce } from '@hooks'; import { useDebounce } from '@hooks';
@ -217,9 +218,8 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
); );
}, },
actions: [ actions: [
// temp: swap button types until colors are updated { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'cancel', text: 'Cancel', type: 'primary' }, { id: 'save', text: 'Save', type: ButtonEnums.type.primary },
{ id: 'save', text: 'Save', type: 'secondary' },
], ],
onSubmit: onSubmitHandler, onSubmit: onSubmitHandler,
}, },

View File

@ -6,6 +6,7 @@ import {
useImageViewer, useImageViewer,
useViewportGrid, useViewportGrid,
Dialog, Dialog,
ButtonEnums,
} from '@ohif/ui'; } from '@ohif/ui';
import { useTrackedMeasurements } from '../../getContextModule'; import { useTrackedMeasurements } from '../../getContextModule';
@ -507,11 +508,15 @@ function _mapDisplaySets(
</div> </div>
), ),
actions: [ actions: [
{ id: 'cancel', text: 'Cancel', type: 'secondary' }, {
id: 'cancel',
text: 'Cancel',
type: ButtonEnums.type.secondary,
},
{ {
id: 'yes', id: 'yes',
text: 'Yes', text: 'Yes',
type: 'primary', type: ButtonEnums.type.primary,
classes: ['reject-yes-button'], classes: ['reject-yes-button'],
}, },
], ],

View File

@ -225,9 +225,7 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
value={metadata.SeriesTime || ''} value={metadata.SeriesTime || ''}
onChange={() => {}} onChange={() => {}}
/> />
<Button color="primary" onClick={updateMetadata}> <Button onClick={updateMetadata}>Reload Data</Button>
Reload Data
</Button>
</div> </div>
</div> </div>
} }

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Button, ButtonGroup } from '@ohif/ui'; import { LegacyButton, ButtonGroup } from '@ohif/ui';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
function ExportReports({ segmentations, tmtvValue, config, commandsManager }) { function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
@ -9,8 +9,9 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
<> <>
{segmentations?.length ? ( {segmentations?.length ? (
<div className="flex justify-center mt-4 space-x-2"> <div className="flex justify-center mt-4 space-x-2">
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<ButtonGroup color="black" size="inherit"> <ButtonGroup color="black" size="inherit">
<Button <LegacyButton
className="px-2 py-2 text-base" className="px-2 py-2 text-base"
disabled={tmtvValue === null} disabled={tmtvValue === null}
onClick={() => { onClick={() => {
@ -22,10 +23,10 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
}} }}
> >
{t('Export CSV')} {t('Export CSV')}
</Button> </LegacyButton>
</ButtonGroup> </ButtonGroup>
<ButtonGroup color="black" size="inherit"> <ButtonGroup color="black" size="inherit">
<Button <LegacyButton
className="px-2 py-2 text-base" className="px-2 py-2 text-base"
onClick={() => { onClick={() => {
commandsManager.runCommand('createTMTVRTReport'); commandsManager.runCommand('createTMTVRTReport');
@ -33,7 +34,7 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
disabled={tmtvValue === null} disabled={tmtvValue === null}
> >
{t('Create RT Report')} {t('Create RT Report')}
</Button> </LegacyButton>
</ButtonGroup> </ButtonGroup>
</div> </div>
) : null} ) : null}

View File

@ -181,7 +181,6 @@ export default function PanelRoiThresholdSegmentation({
<div className="overflow-x-hidden overflow-y-auto invisible-scrollbar"> <div className="overflow-x-hidden overflow-y-auto invisible-scrollbar">
<div className="flex mx-4 my-4 mb-4 space-x-4"> <div className="flex mx-4 my-4 mb-4 space-x-4">
<Button <Button
color="primary"
onClick={() => { onClick={() => {
setLabelmapLoading(true); setLabelmapLoading(true);
setTimeout(() => { setTimeout(() => {
@ -194,9 +193,7 @@ export default function PanelRoiThresholdSegmentation({
> >
{labelmapLoading ? 'loading ...' : 'New Label'} {labelmapLoading ? 'loading ...' : 'New Label'}
</Button> </Button>
<Button color="primary" onClick={handleROIThresholding}> <Button onClick={handleROIThresholding}>Run</Button>
Run
</Button>
</div> </div>
<div <div
className="flex items-center justify-around h-8 mb-2 border-t outline-none cursor-pointer select-none bg-secondary-dark first:border-0 border-secondary-light" className="flex items-center justify-around h-8 mb-2 border-t outline-none cursor-pointer select-none bg-secondary-dark first:border-0 border-secondary-light"

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Input, Label, Select, Button, ButtonGroup } from '@ohif/ui'; import { Input, Label, Select, LegacyButton, ButtonGroup } from '@ohif/ui';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
export const ROI_STAT = 'roi_stat'; export const ROI_STAT = 'roi_stat';
@ -38,8 +38,9 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
/> />
</div> </div>
<div className="w-1/2"> <div className="w-1/2">
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<ButtonGroup> <ButtonGroup>
<Button <LegacyButton
size="initial" size="initial"
className="px-2 py-2 text-base text-white" className="px-2 py-2 text-base text-white"
color="primaryLight" color="primaryLight"
@ -47,8 +48,8 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
onClick={() => runCommand('setStartSliceForROIThresholdTool')} onClick={() => runCommand('setStartSliceForROIThresholdTool')}
> >
{t('Start')} {t('Start')}
</Button> </LegacyButton>
<Button <LegacyButton
size="initial" size="initial"
color="primaryLight" color="primaryLight"
variant="outlined" variant="outlined"
@ -56,7 +57,7 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
onClick={() => runCommand('setEndSliceForROIThresholdTool')} onClick={() => runCommand('setEndSliceForROIThresholdTool')}
> >
{t('End')} {t('End')}
</Button> </LegacyButton>
</ButtonGroup> </ButtonGroup>
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Input, Dialog } from '@ohif/ui'; import { Input, Dialog, ButtonEnums } from '@ohif/ui';
function segmentationItemEditHandler({ id, servicesManager }) { function segmentationItemEditHandler({ id, servicesManager }) {
const { segmentationService, uiDialogService } = servicesManager.services; const { segmentationService, uiDialogService } = servicesManager.services;
@ -44,23 +44,20 @@ function segmentationItemEditHandler({ id, servicesManager }) {
} }
}; };
return ( return (
<div className="p-4 bg-primary-dark">
<Input <Input
autoFocus autoFocus
className="mt-2 bg-black border-primary-main" className="bg-black border-primary-main"
type="text" type="text"
containerClassName="mr-2" containerClassName="mr-2"
value={value.label} value={value.label}
onChange={onChangeHandler} onChange={onChangeHandler}
onKeyPress={onKeyPressHandler} onKeyPress={onKeyPressHandler}
/> />
</div>
); );
}, },
actions: [ actions: [
// temp: swap button types until colors are updated { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
{ id: 'cancel', text: 'Cancel', type: 'primary' }, { id: 'save', text: 'Save', type: ButtonEnums.type.primary },
{ id: 'save', text: 'Save', type: 'secondary' },
], ],
onSubmit: onSubmitHandler, onSubmit: onSubmitHandler,
}, },

View File

@ -13,7 +13,7 @@ describe('OHIF Context Menu', function () {
it('checks context menu customization', function() { it('checks context menu customization', function() {
// Add length measurement // Add length measurement
cy.addLengthMeasurement(); cy.addLengthMeasurement();
cy.get('[data-cy="prompt-begin-tracking-yes"]').click(); cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
cy.get('[data-cy="measurement-item"]').click(); cy.get('[data-cy="measurement-item"]').click();
const [x1, y1] = [150, 100]; const [x1, y1] = [150, 100];

View File

@ -113,7 +113,7 @@ describe('OHIF Cornerstone Toolbar', () => {
cy.addLengthMeasurement(); cy.addLengthMeasurement();
cy.get('[data-cy="viewport-notification"]').should('exist'); cy.get('[data-cy="viewport-notification"]').should('exist');
cy.get('[data-cy="viewport-notification"]').should('be.visible'); cy.get('[data-cy="viewport-notification"]').should('be.visible');
cy.get('[data-cy="prompt-begin-tracking-yes"]').click(); cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
//Verify the measurement exists in the table //Verify the measurement exists in the table
cy.get('@measurementsPanel').should('be.visible'); cy.get('@measurementsPanel').should('be.visible');

View File

@ -27,7 +27,7 @@ describe('OHIF Measurement Panel', function() {
cy.addLengthMeasurement(); cy.addLengthMeasurement();
cy.get('[data-cy="viewport-notification"]').should('exist'); cy.get('[data-cy="viewport-notification"]').should('exist');
cy.get('[data-cy="viewport-notification"]').should('be.visible'); cy.get('[data-cy="viewport-notification"]').should('be.visible');
cy.get('[data-cy="prompt-begin-tracking-yes"]').click(); cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
cy.get('[data-cy="measurement-item"]').click(); cy.get('[data-cy="measurement-item"]').click();
cy.get('[data-cy="measurement-item"]') cy.get('[data-cy="measurement-item"]')
@ -46,7 +46,7 @@ describe('OHIF Measurement Panel', function() {
it('checks if image would jump when clicked on a measurement item', function() { it('checks if image would jump when clicked on a measurement item', function() {
// Add length measurement // Add length measurement
cy.addLengthMeasurement(); cy.addLengthMeasurement();
cy.get('[data-cy="prompt-begin-tracking-yes"]').click(); cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
cy.scrollToIndex(13); cy.scrollToIndex(13);

View File

@ -15,7 +15,7 @@ import { utils, hotkeys, ServicesManager } from '@ohif/core';
import { import {
Icon, Icon,
StudyListExpandedRow, StudyListExpandedRow,
Button, LegacyButton,
EmptyStudies, EmptyStudies,
StudyListTable, StudyListTable,
StudyListPagination, StudyListPagination,
@ -363,16 +363,17 @@ function WorkList({
''}?${query.toString()}`} ''}?${query.toString()}`}
// to={`${mode.routeName}/dicomweb?StudyInstanceUIDs=${studyInstanceUid}`} // to={`${mode.routeName}/dicomweb?StudyInstanceUIDs=${studyInstanceUid}`}
> >
<Button {/* TODO revisit the completely rounded style of buttons used for launching a mode from the worklist later - for now use LegacyButton*/}
<LegacyButton
rounded="full" rounded="full"
variant={isValidMode ? 'contained' : 'disabled'} variant={isValidMode ? 'contained' : 'disabled'}
disabled={!isValidMode} disabled={!isValidMode}
endIcon={<Icon name="launch-arrow" />} // launch-arrow | launch-info endIcon={<Icon name="launch-arrow" />} // launch-arrow | launch-info
className={classnames('font-medium ', { 'ml-2': !isFirst })} className={classnames({ 'ml-2': !isFirst })}
onClick={() => {}} onClick={() => {}}
> >
{t(`Modes:${mode.displayName}`)} {t(`Modes:${mode.displayName}`)}
</Button> </LegacyButton>
</Link> </Link>
); );
})} })}

View File

@ -74,9 +74,16 @@ module.exports = {
}, },
customblue: { customblue: {
10: '#0A163F',
20: '#0B1F54',
30: '#09286e',
40: '#0E307F',
50: '#0F3A94',
80: '#1454D4',
100: '#c4fdff', 100: '#c4fdff',
200: '#38daff', 200: '#38daff',
300: '#1D204D', 300: '#1D204D',
400: '#90A0C1',
}, },
customgray: { customgray: {

View File

@ -1,181 +1,89 @@
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import * as ButtonEnums from './ButtonEnums';
const baseClasses = const sizeClasses = {
'leading-none font-sans text-center justify-center items-center outline-none transition duration-300 ease-in-out focus:outline-none'; [ButtonEnums.size.small]: 'h-[26px] text-[13px]',
[ButtonEnums.size.medium]: 'h-[32px] text-[14px]',
};
const layoutClasses =
'box-content inline-flex flex-row items-center justify-center gap-[5px] justify center px-[10px] outline-none rounded';
const baseFontTextClasses =
'leading-[1.2] font-sans text-center whitespace-nowrap';
const fontTextClasses = {
[ButtonEnums.type.primary]: classnames(baseFontTextClasses, 'font-semibold'),
[ButtonEnums.type.secondary]: classnames(baseFontTextClasses, 'font-400'),
};
const baseEnabledEffectClasses =
'transition duration-300 ease-in-out focus:outline-none';
const enabledEffectClasses = {
[ButtonEnums.type.primary]: classnames(
baseEnabledEffectClasses,
'hover:bg-customblue-80 active:bg-customblue-40'
),
[ButtonEnums.type.secondary]: classnames(
baseEnabledEffectClasses,
'hover:bg-customblue-50 active:bg-customblue-20'
),
};
const baseEnabledClasses = 'text-white';
const enabledClasses = {
[ButtonEnums.type.primary]: classnames(
'bg-primary-main',
baseEnabledClasses,
enabledEffectClasses[ButtonEnums.type.primary]
),
[ButtonEnums.type.secondary]: classnames(
'bg-customblue-30',
baseEnabledClasses,
enabledEffectClasses[ButtonEnums.type.secondary]
),
};
const disabledClasses =
'bg-inputfield-placeholder text-common-light cursor-default';
const defaults = { const defaults = {
color: 'default', color: 'default',
disabled: false, disabled: false,
fullWidth: false, rounded: 'small',
rounded: 'medium', size: ButtonEnums.size.medium,
border: 'none', type: ButtonEnums.type.primary,
size: 'medium',
type: 'button',
variant: 'contained',
};
const roundedClasses = {
none: '',
small: 'rounded',
medium: 'rounded-md',
large: 'rounded-lg',
full: 'rounded-full',
};
const variants = {
text: {
default:
'text-primary-light hover:bg-primary-light hover:text-white active:opacity-80 focus:bg-primary-light focus:text-white',
primary:
'text-primary-main hover:bg-primary-main hover:text-white active:opacity-80 focus:bg-primary-main focus:text-white',
secondary:
'text-secondary-light hover:bg-secondary-light hover:text-white active:opacity-80 focus:bg-secondary-light focus:text-white',
white:
'text-white hover:bg-white hover:text-black active:opacity-80 focus:bg-white focus:text-black',
black:
'text-black hover:bg-black hover:text-white focus:bg-black focus:text-white active:opacity-80',
},
outlined: {
default:
'text-primary-light hover:bg-primary-light hover:text-black focus:text-black focus:bg-primary-light active:opacity-80',
primary:
'text-primary-main hover:opacity-80 active:opacity-100 focus:opacity-80',
secondary:
'text-secondary-light hover:opacity-80 active:opacity-100 focus:opacity-80',
translucent:
'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
white:
'text-black hover:bg-primary-main focus:bg-primary-main hover:border-black focus:border-black',
black:
'text-white hover:bg-primary-main focus:bg-primary-main hover:border-black focus:border-black',
primaryActive:
'text-primary-active hover:opacity-80 active:opacity-100 focus:opacity-80',
primaryLight:
'border bg-transparent border-primary-main text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
},
contained: {
default: 'text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
primary: 'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
primaryDark:
'text-primary-active hover:opacity-80 active:opacity-100 focus:opacity-80',
secondary:
'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
white: 'text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
black: 'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
light:
'border text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
},
disabled: {
default: 'cursor-not-allowed opacity-50 text-black',
primary: 'cursor-not-allowed opacity-50 text-white',
secondary: 'cursor-not-allowed opacity-50 text-white',
white: 'cursor-not-allowed opacity-50 text-black',
black: 'cursor-not-allowed opacity-50 text-white',
light: 'cursor-not-allowed opacity-50 border text-black',
},
};
const defaultVariantBackGroundColor = {
text: {
default: '',
primary: '',
secondary: '',
white: '',
black: '',
},
outlined: {
default: 'bg-transparent',
primary: 'bg-transparent',
secondary: 'bg-transparent',
black: 'bg-black',
white: '',
},
contained: {
default: 'bg-primary-light',
primary: 'bg-primary-main',
primaryDark: 'bg-primary-dark',
secondary: 'bg-secondary-light',
white: 'bg-white',
black: 'bg-black',
light: 'bg-primary-light',
},
disabled: {
default: 'bg-primary-light',
primary: 'bg-primary-main',
secondary: 'bg-secondary-light',
white: 'bg-white',
black: 'bg-black',
light: 'bg-primary-light',
},
};
const _getVariantClass = (variant, color, bgColor = null) => {
const defaultBackgroundColor = defaultVariantBackGroundColor[variant][color];
if (!bgColor) {
bgColor = defaultBackgroundColor;
}
return `${variants[variant][color]} ${bgColor}`;
};
const borderClasses = {
none: '',
light: 'border border-primary-light',
primary: 'border border-primary-main',
primaryActive: 'border border-primary-active',
secondary: 'border border-secondary-light',
white: 'border border-white',
black: 'border border-black',
};
const sizeClasses = {
small: 'py-2 px-2 text-sm min-w-md',
medium: 'py-2 px-2 text-lg min-w-md',
large: 'py-2 px-6 text-xl min-w-md',
initial: '',
};
const fullWidthClasses = {
true: 'flex w-full',
false: 'inline-flex',
}; };
const Button = ({ const Button = ({
children, children,
variant = defaults.variant,
color = defaults.color,
border = defaults.border,
size = defaults.size, size = defaults.size,
rounded = defaults.rounded,
disabled = defaults.disabled, disabled = defaults.disabled,
type = defaults.type, type = defaults.type,
fullWidth = defaults.fullWidth,
bgColor = null,
startIcon: startIconProp, startIcon: startIconProp,
endIcon: endIconProp, endIcon: endIconProp,
name, name,
className, className,
onClick, onClick,
/** TODO: All possible props should be explicitly defined -- avoid spreading props */
...rest
}) => { }) => {
const startIcon = startIconProp && ( const startIcon = startIconProp && (
<div className="mr-2"> <>
{React.cloneElement(startIconProp, { {React.cloneElement(startIconProp, {
className: classnames('w-4 h-4 fill-current'), className: classnames('w-4 h-4 fill-current'),
})} })}
</div> </>
); );
const endIcon = endIconProp && ( const endIcon = endIconProp && (
<div className="ml-2"> <>
{React.cloneElement(endIconProp, { {React.cloneElement(endIconProp, {
className: classnames('w-4 h-4 fill-current'), className: classnames('w-4 h-4 fill-current'),
})} })}
</div> </>
); );
const buttonElement = useRef(null); const buttonElement = useRef(null);
@ -187,12 +95,11 @@ const Button = ({
}; };
const finalClassName = classnames( const finalClassName = classnames(
baseClasses, layoutClasses,
_getVariantClass(variant, color, bgColor), fontTextClasses[type],
borderClasses[border], disabled ? disabledClasses : enabledClasses[type],
roundedClasses[rounded],
sizeClasses[size], sizeClasses[size],
fullWidthClasses[fullWidth], children ? 'min-w-[32px]' : '', // minimum width for buttons with text; icon only button does NOT get a minimum width
className className
); );
@ -202,9 +109,7 @@ const Button = ({
disabled={disabled} disabled={disabled}
ref={buttonElement} ref={buttonElement}
onClick={handleOnClick} onClick={handleOnClick}
type={type}
data-cy={`${name}-btn`} data-cy={`${name}-btn`}
{...rest}
> >
{startIcon} {startIcon}
{children} {children}
@ -214,10 +119,11 @@ const Button = ({
}; };
Button.defaultProps = { Button.defaultProps = {
color: defaults.color,
disabled: false, disabled: false,
children: '', children: '',
onClick: () => {}, onClick: () => {},
type: defaults.type,
size: defaults.size,
}; };
Button.propTypes = { Button.propTypes = {
@ -226,39 +132,11 @@ Button.propTypes = {
/** Callback to be called when the button is clicked */ /** Callback to be called when the button is clicked */
onClick: PropTypes.func.isRequired, onClick: PropTypes.func.isRequired,
/** Button size */ /** Button size */
size: PropTypes.oneOf(['small', 'medium', 'large', 'initial', 'inherit']), size: PropTypes.oneOf([ButtonEnums.size.medium, ButtonEnums.size.small]),
/** Button corner roundness */
rounded: PropTypes.oneOf(['none', 'small', 'medium', 'large', 'full']),
variant: PropTypes.oneOf(['text', 'outlined', 'contained', 'disabled']),
/* color prop must have all the possible keys of variants defined above */
color: PropTypes.oneOf([
'default',
'primary',
'primaryDark',
'primaryActive',
'secondary',
'white',
'black',
'inherit',
'light',
'translucent',
]),
border: PropTypes.oneOf([
'none',
'light',
'default',
'primary',
'primaryActive',
'secondary',
'white',
'black',
]),
/** Whether the button should have full width */
fullWidth: PropTypes.bool,
/** Whether the button should be disabled */ /** Whether the button should be disabled */
disabled: PropTypes.bool, disabled: PropTypes.bool,
/** Button type */ /** Button type */
type: PropTypes.string, type: PropTypes.oneOf([ButtonEnums.type.primary, ButtonEnums.type.secondary]),
name: PropTypes.string, name: PropTypes.string,
/** Button start icon name - if any icon is specified */ /** Button start icon name - if any icon is specified */
startIcon: PropTypes.node, startIcon: PropTypes.node,
@ -266,8 +144,6 @@ Button.propTypes = {
endIcon: PropTypes.node, endIcon: PropTypes.node,
/** Additional TailwindCSS classnames */ /** Additional TailwindCSS classnames */
className: PropTypes.string, className: PropTypes.string,
/** Background color for the button to override*/
bgColor: PropTypes.string,
}; };
export default Button; export default Button;

View File

@ -0,0 +1,10 @@
enum type {
primary = 'primary',
secondary = 'secondary',
}
enum size {
medium = 'medium',
small = 'small',
}
export { type, size };

View File

@ -1,4 +1,4 @@
import Button from '../Button'; import Button, {ButtonType, ButtonSize} from '../Button';
import { ArgsTable, Story, Canvas, Meta } from '@storybook/addon-docs'; import { ArgsTable, Story, Canvas, Meta } from '@storybook/addon-docs';
import { import {
createComponentTemplate, createComponentTemplate,
@ -24,7 +24,7 @@ export const buttonTemplate = createComponentTemplate(Button);
## Overview ## Overview
You can use the button component to create a button. It can be used in different You can use the button component to create a button. It can be used in different
ways, the default button is a simple button with a text. ways, the default button is a simple button with text.
<Canvas> <Canvas>
<Story name="Overview" args={{ children: 'Button', color: 'default' }}> <Story name="Overview" args={{ children: 'Button', color: 'default' }}>
@ -38,37 +38,29 @@ ways, the default button is a simple button with a text.
## Usage ## Usage
### Variants ### Types
There can be different variants of buttons: `text`, `outlined`, `contained`, and There can be different types of buttons: `primary`, and `secondary`.
`disabled`.
<Canvas> <Canvas>
<Story name="Variants"> <Story name="Types">
<div className="flex space-x-2"> <div className="flex space-x-2">
<Button variant="text">Text Button</Button> <Button type={ButtonType.primary}>Primary Button</Button>
<Button variant="outlined">Outlined Button</Button> <Button type={ButtonType.secondary}>Secondary Button</Button>
<Button variant="contained">Contained Button</Button>
<Button variant="disabled">Disabled Button</Button>
</div> </div>
</Story> </Story>
</Canvas> </Canvas>
### Colors ### Sizes
There are different colors for the button: `default`, `primary`, `secondary`, There are different sizes for the button: `small`, and `medium`. The size refers
`white`, `black`, `inherit`, `light`. to the button's height.
<Canvas> <Canvas>
<Story name="Colors"> <Story name="Colors">
<div className="flex space-x-2"> <div className="flex items-center space-x-2">
<Button color="default">Default Button</Button> <Button size={ButtonSize.small}>Small Button</Button>
<Button color="primary">Primary Button</Button> <Button size={ButtonSize.medium}>Medium Button</Button>
<Button color="secondary">Secondary Button</Button>
<Button color="white">White Button</Button>
<Button color="black">Black Button</Button>
<Button color="inherit">Inherit Button</Button>
<Button color="light">Light Button</Button>
</div> </div>
</Story> </Story>
</Canvas> </Canvas>
@ -79,19 +71,19 @@ You can mix different props together to create a button.
<Canvas> <Canvas>
<Story name="Custom"> <Story name="Custom">
<Button color="secondary" variant="outlined"> <Button type={ButtonType.secondary} size={ButtonSize.small}>
Custom Button Small, Secondary Button
</Button> </Button>
</Story> </Story>
</Canvas> </Canvas>
### Disabled ### Disabled
You can disable the button by setting the variant to `disabled`. You can disable the button by setting the `disabled` property to true.
<Canvas> <Canvas>
<Story name="Disabled"> <Story name="Disabled">
<Button variant="disabled">Disabled Button</Button> <Button disabled={true}>Disabled Button</Button>
</Story> </Story>
</Canvas> </Canvas>
@ -159,18 +151,6 @@ End Icon is the same as start icon, but for the end of the button.
</Story> </Story>
</Canvas> </Canvas>
### Full width
You can make the button full width by setting the `fullWidth` prop to `true`.
<Canvas>
<Story name="Full Width">
<Button fullWidth color="secondary">
Full Width Button
</Button>
</Story>
</Canvas>
## Contribute ## Contribute
<Footer componentRelativePath="Button/__stories__/button.stories.mdx" /> <Footer componentRelativePath="Button/__stories__/button.stories.mdx" />

View File

@ -1,2 +1,5 @@
import Button from './Button'; import Button from './Button';
import * as ButtonEnums from './ButtonEnums';
export { ButtonEnums };
export default Button; export default Button;

View File

@ -2,7 +2,7 @@ import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Button from '../Button'; import Button, { ButtonEnums } from '../Button';
const Footer = ({ actions, className, onSubmit, value }) => { const Footer = ({ actions, className, onSubmit, value }) => {
const flex = 'flex items-center justify-end'; const flex = 'flex items-center justify-end';
@ -12,7 +12,6 @@ const Footer = ({ actions, className, onSubmit, value }) => {
<div className={classNames(flex, padding, className)}> <div className={classNames(flex, padding, className)}>
{actions.map((action, index) => { {actions.map((action, index) => {
const isFirst = index === 0; const isFirst = index === 0;
const isPrimary = action.type === 'primary';
const onClickHandler = event => onSubmit({ action, value, event }); const onClickHandler = event => onSubmit({ action, value, event });
@ -20,9 +19,8 @@ const Footer = ({ actions, className, onSubmit, value }) => {
<Button <Button
key={index} key={index}
className={classNames({ 'ml-2': !isFirst }, action.classes)} className={classNames({ 'ml-2': !isFirst }, action.classes)}
color={isPrimary ? 'primary' : undefined} type={action.type}
onClick={onClickHandler} onClick={onClickHandler}
style={{ transition: 'all .15s ease', height: 34 }}
> >
{action.text} {action.text}
</Button> </Button>
@ -42,7 +40,10 @@ Footer.propTypes = {
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,
text: PropTypes.string.isRequired, text: PropTypes.string.isRequired,
value: PropTypes.any, value: PropTypes.any,
type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired, type: PropTypes.oneOf([
ButtonEnums.type.primary,
ButtonEnums.type.secondary,
]).isRequired,
classes: PropTypes.arrayOf(PropTypes.string), classes: PropTypes.arrayOf(PropTypes.string),
}) })
).isRequired, ).isRequired,

View File

@ -0,0 +1,273 @@
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
const baseClasses =
'leading-none font-sans text-center justify-center items-center outline-none transition duration-300 ease-in-out focus:outline-none';
const defaults = {
color: 'default',
disabled: false,
fullWidth: false,
rounded: 'medium',
border: 'none',
size: 'medium',
type: 'button',
variant: 'contained',
};
const roundedClasses = {
none: '',
small: 'rounded',
medium: 'rounded-md',
large: 'rounded-lg',
full: 'rounded-full',
};
const variants = {
text: {
default:
'text-primary-light hover:bg-primary-light hover:text-white active:opacity-80 focus:bg-primary-light focus:text-white',
primary:
'text-primary-main hover:bg-primary-main hover:text-white active:opacity-80 focus:bg-primary-main focus:text-white',
secondary:
'text-secondary-light hover:bg-secondary-light hover:text-white active:opacity-80 focus:bg-secondary-light focus:text-white',
white:
'text-white hover:bg-white hover:text-black active:opacity-80 focus:bg-white focus:text-black',
black:
'text-black hover:bg-black hover:text-white focus:bg-black focus:text-white active:opacity-80',
},
outlined: {
default:
'text-primary-light hover:bg-primary-light hover:text-black focus:text-black focus:bg-primary-light active:opacity-80',
primary:
'text-primary-main hover:opacity-80 active:opacity-100 focus:opacity-80',
secondary:
'text-secondary-light hover:opacity-80 active:opacity-100 focus:opacity-80',
translucent:
'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
white:
'text-black hover:bg-primary-main focus:bg-primary-main hover:border-black focus:border-black',
black:
'text-white hover:bg-primary-main focus:bg-primary-main hover:border-black focus:border-black',
primaryActive:
'text-primary-active hover:opacity-80 active:opacity-100 focus:opacity-80',
primaryLight:
'border bg-transparent border-primary-main text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
},
contained: {
default: 'text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
primary: 'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
primaryDark:
'text-primary-active hover:opacity-80 active:opacity-100 focus:opacity-80',
secondary:
'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
white: 'text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
black: 'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
light:
'border text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
},
disabled: {
default: 'cursor-not-allowed opacity-50 text-black',
primary: 'cursor-not-allowed opacity-50 text-white',
secondary: 'cursor-not-allowed opacity-50 text-white',
white: 'cursor-not-allowed opacity-50 text-black',
black: 'cursor-not-allowed opacity-50 text-white',
light: 'cursor-not-allowed opacity-50 border text-black',
},
};
const defaultVariantBackGroundColor = {
text: {
default: '',
primary: '',
secondary: '',
white: '',
black: '',
},
outlined: {
default: 'bg-transparent',
primary: 'bg-transparent',
secondary: 'bg-transparent',
black: 'bg-black',
white: '',
},
contained: {
default: 'bg-primary-light',
primary: 'bg-primary-main',
primaryDark: 'bg-primary-dark',
secondary: 'bg-secondary-light',
white: 'bg-white',
black: 'bg-black',
light: 'bg-primary-light',
},
disabled: {
default: 'bg-primary-light',
primary: 'bg-primary-main',
secondary: 'bg-secondary-light',
white: 'bg-white',
black: 'bg-black',
light: 'bg-primary-light',
},
};
const _getVariantClass = (variant, color, bgColor = null) => {
const defaultBackgroundColor = defaultVariantBackGroundColor[variant][color];
if (!bgColor) {
bgColor = defaultBackgroundColor;
}
return `${variants[variant][color]} ${bgColor}`;
};
const borderClasses = {
none: '',
light: 'border border-primary-light',
primary: 'border border-primary-main',
primaryActive: 'border border-primary-active',
secondary: 'border border-secondary-light',
white: 'border border-white',
black: 'border border-black',
};
const sizeClasses = {
small: 'py-2 px-2 text-sm min-w-md',
medium: 'py-2 px-2 text-lg min-w-md',
large: 'py-2 px-6 text-xl min-w-md',
initial: '',
};
const fullWidthClasses = {
true: 'flex w-full',
false: 'inline-flex',
};
const LegacyButton = ({
children,
variant = defaults.variant,
color = defaults.color,
border = defaults.border,
size = defaults.size,
rounded = defaults.rounded,
disabled = defaults.disabled,
type = defaults.type,
fullWidth = defaults.fullWidth,
bgColor = null,
startIcon: startIconProp,
endIcon: endIconProp,
name,
className,
onClick,
/** TODO: All possible props should be explicitly defined -- avoid spreading props */
...rest
}) => {
const startIcon = startIconProp && (
<div className="mr-2">
{React.cloneElement(startIconProp, {
className: classnames('w-4 h-4 fill-current'),
})}
</div>
);
const endIcon = endIconProp && (
<div className="ml-2">
{React.cloneElement(endIconProp, {
className: classnames('w-4 h-4 fill-current'),
})}
</div>
);
const buttonElement = useRef(null);
const handleOnClick = e => {
buttonElement.current.blur();
if (!disabled) {
onClick(e);
}
};
const finalClassName = classnames(
baseClasses,
_getVariantClass(variant, color, bgColor),
borderClasses[border],
roundedClasses[rounded],
sizeClasses[size],
fullWidthClasses[fullWidth],
className
);
return (
<button
className={finalClassName}
disabled={disabled}
ref={buttonElement}
onClick={handleOnClick}
type={type}
data-cy={`${name}-btn`}
{...rest}
>
{startIcon}
{children}
{endIcon}
</button>
);
};
LegacyButton.defaultProps = {
color: defaults.color,
disabled: false,
children: '',
onClick: () => {},
};
LegacyButton.propTypes = {
/** What is inside the button, can be text or react component */
children: PropTypes.node,
/** Callback to be called when the button is clicked */
onClick: PropTypes.func.isRequired,
/** Button size */
size: PropTypes.oneOf(['small', 'medium', 'large', 'initial', 'inherit']),
/** Button corner roundness */
rounded: PropTypes.oneOf(['none', 'small', 'medium', 'large', 'full']),
variant: PropTypes.oneOf(['text', 'outlined', 'contained', 'disabled']),
/* color prop must have all the possible keys of variants defined above */
color: PropTypes.oneOf([
'default',
'primary',
'primaryDark',
'primaryActive',
'secondary',
'white',
'black',
'inherit',
'light',
'translucent',
]),
border: PropTypes.oneOf([
'none',
'light',
'default',
'primary',
'primaryActive',
'secondary',
'white',
'black',
]),
/** Whether the button should have full width */
fullWidth: PropTypes.bool,
/** Whether the button should be disabled */
disabled: PropTypes.bool,
/** Button type */
type: PropTypes.string,
name: PropTypes.string,
/** Button start icon name - if any icon is specified */
startIcon: PropTypes.node,
/** Button end icon name - if any icon is specified */
endIcon: PropTypes.node,
/** Additional TailwindCSS classnames */
className: PropTypes.string,
/** Background color for the button to override*/
bgColor: PropTypes.string,
};
export default LegacyButton;

View File

@ -0,0 +1,176 @@
import LegacyButton from '../LegacyButton';
import { ArgsTable, Story, Canvas, Meta } from '@storybook/addon-docs';
import {
createComponentTemplate,
createStoryMetaSettings,
} from '../../../storybook/functions/create-component-story';
export const argTypes = {
component: LegacyButton,
title: 'Components/LegacyButton',
};
<Meta title="Components/LegacyButton" component={LegacyButton} />
export const buttonTemplate = createComponentTemplate(LegacyButton);
<Heading title="LegacyButton" componentRelativePath="LegacyButton/LegacyButton.tsx" />
- [Overview](#overview)
- [Props](#props)
- [Usage](#usage)
- [Contribute](#contribute)
## Overview
You can use the legacy button component to create a button. It can be used in different
ways, the default button is a simple button with a text.
<Canvas>
<Story name="Overview" args={{ children: 'LegacyButton', color: 'default' }}>
{buttonTemplate.bind({})}
</Story>
</Canvas>
## Props
<ArgsTable of={LegacyButton} />
## Usage
### Variants
There can be different variants of buttons: `text`, `outlined`, `contained`, and
`disabled`.
<Canvas>
<Story name="Variants">
<div className="flex space-x-2">
<LegacyButton variant="text">Text LegacyButton</LegacyButton>
<LegacyButton variant="outlined">Outlined LegacyButton</LegacyButton>
<LegacyButton variant="contained">Contained LegacyButton</LegacyButton>
<LegacyButton variant="disabled">Disabled LegacyButton</LegacyButton>
</div>
</Story>
</Canvas>
### Colors
There are different colors for the legacy button: `default`, `primary`, `secondary`,
`white`, `black`, `inherit`, `light`.
<Canvas>
<Story name="Colors">
<div className="flex space-x-2">
<LegacyButton color="default">Default LegacyButton</LegacyButton>
<LegacyButton color="primary">Primary LegacyButton</LegacyButton>
<LegacyButton color="secondary">Secondary LegacyButton</LegacyButton>
<LegacyButton color="white">White LegacyButton</LegacyButton>
<LegacyButton color="black">Black LegacyButton</LegacyButton>
<LegacyButton color="inherit">Inherit LegacyButton</LegacyButton>
<LegacyButton color="light">Light LegacyButton</LegacyButton>
</div>
</Story>
</Canvas>
### Mixing props
You can mix different props together to create a legacy button.
<Canvas>
<Story name="Custom">
<LegacyButton color="secondary" variant="outlined">
Custom LegacyButton
</LegacyButton>
</Story>
</Canvas>
### Disabled
You can disable the legacy button by setting the variant to `disabled`.
<Canvas>
<Story name="Disabled">
<LegacyButton variant="disabled">Disabled LegacyButton</LegacyButton>
</Story>
</Canvas>
### Start/End Icons
You can add an icon to the start of the legacy button. It accepts an icon component.
<Canvas>
<Story name="Start Icon">
{() => {
// svg icon for github
const Github = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="feather feather-github"
>
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg>
);
};
return <LegacyButton startIcon={<Github />}>Start Icon LegacyButton</LegacyButton>;
}}
</Story>
</Canvas>
End Icon is the same as start icon, but for the end of the legacy button.
<Canvas>
<Story name="End Icon">
{() => {
// svg icon for github
const Github = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="feather feather-github"
>
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg>
);
};
return (
<LegacyButton startIcon={<Github />} endIcon={<Github />}>
Start and End Icon LegacyButton
</LegacyButton>
);
}}
</Story>
</Canvas>
### Full width
You can make the legacy button full width by setting the `fullWidth` prop to `true`.
<Canvas>
<Story name="Full Width">
<LegacyButton fullWidth color="secondary">
Full Width LegacyButton
</LegacyButton>
</Story>
</Canvas>
## Contribute
<Footer componentRelativePath="LegacyButton/__stories__/legacyButton.stories.mdx" />

View File

@ -0,0 +1,2 @@
import LegacyButton from './LegacyButton';
export default LegacyButton;

View File

@ -6,7 +6,7 @@ import { StringNumber } from '../../types';
import LegacyPatientInfo from '../LegacyPatientInfo'; import LegacyPatientInfo from '../LegacyPatientInfo';
import Icon from '../Icon'; import Icon from '../Icon';
import ButtonGroup from '../ButtonGroup'; import ButtonGroup from '../ButtonGroup';
import Button from '../Button'; import LegacyButton from '../LegacyButton';
import LegacyCinePlayer from '../LegacyCinePlayer'; import LegacyCinePlayer from '../LegacyCinePlayer';
const LegacyViewportActionBar = ({ const LegacyViewportActionBar = ({
@ -104,23 +104,24 @@ const LegacyViewportActionBar = ({
</div> </div>
{showNavArrows && !showCine && ( {showNavArrows && !showCine && (
<div className="mt-2" style={{ pointerEvents: 'all' }}> <div className="mt-2" style={{ pointerEvents: 'all' }}>
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<ButtonGroup> <ButtonGroup>
<Button <LegacyButton
size="initial" size="initial"
className="px-2 py-1 bg-black" className="px-2 py-1 bg-black"
border="light" border="light"
onClick={() => onArrowsClick('left')} onClick={() => onArrowsClick('left')}
> >
<Icon name="chevron-left" className="w-4 text-white" /> <Icon name="chevron-left" className="w-4 text-white" />
</Button> </LegacyButton>
<Button <LegacyButton
size="initial" size="initial"
border="light" border="light"
className="px-2 py-1 bg-black" className="px-2 py-1 bg-black"
onClick={() => onArrowsClick('right')} onClick={() => onArrowsClick('right')}
> >
<Icon name="chevron-right" className="w-4 text-white" /> <Icon name="chevron-right" className="w-4 text-white" />
</Button> </LegacyButton>
</ButtonGroup> </ButtonGroup>
</div> </div>
)} )}

View File

@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Button from '../Button'; import Button, { ButtonEnums } from '../Button';
import Icon from '../Icon'; import Icon from '../Icon';
const Notification = ({ const Notification = ({
@ -42,7 +42,7 @@ const Notification = ({
color: 'text-yellow-500', color: 'text-yellow-500',
}, },
info: { info: {
icon: 'info', icon: 'notifications-info',
color: 'text-primary-main', color: 'text-primary-main',
}, },
success: { success: {
@ -65,24 +65,23 @@ const Notification = ({
return ( return (
<div <div
ref={notificationRef} ref={notificationRef}
className="flex flex-col p-2 mx-2 mt-2 rounded bg-common-bright" className="flex flex-col p-2 mx-2 mt-2 border-2 rounded-md border-customblue-10 bg-customblue-400"
data-cy={id} data-cy={id}
> >
<div className="flex grow"> <div className="flex items-center grow">
<Icon name={icon} className={classnames('w-5', color)} /> <Icon name={icon} className={classnames('w-6 h-6', color)} />
<span className="ml-2 text-base text-black">{message}</span> <span className="ml-2 text-[13px] text-black">{message}</span>
</div> </div>
<div className="flex justify-end mt-2"> <div className="flex flex-wrap gap-2 justify-end mt-2">
{actions.map((action, index) => { {actions.map((action, index) => {
const isFirst = index === 0; const isFirst = index === 0;
const isPrimary = action.type === 'primary';
return ( return (
<Button <Button
data-cy={action.id} name={action.id}
key={index} key={index}
className={classnames({ 'ml-2': !isFirst })} type={action.type}
color={isPrimary ? 'primary' : undefined} size={action.size || ButtonEnums.size.small}
onClick={() => { onClick={() => {
onSubmit(action.value); onSubmit(action.value);
}} }}
@ -108,7 +107,11 @@ Notification.propTypes = {
PropTypes.shape({ PropTypes.shape({
text: PropTypes.string.isRequired, text: PropTypes.string.isRequired,
value: PropTypes.any.isRequired, value: PropTypes.any.isRequired,
type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired, type: PropTypes.oneOf([
ButtonEnums.type.primary,
ButtonEnums.type.secondary,
]).isRequired,
size: PropTypes.oneOf([ButtonEnums.size.small, ButtonEnums.size.medium]),
}) })
).isRequired, ).isRequired,
onSubmit: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,

View File

@ -13,7 +13,7 @@ import { Swiper, SwiperSlide } from 'swiper/react';
import { PanelService, ServicesManager, Types } from '@ohif/core'; import { PanelService, ServicesManager, Types } from '@ohif/core';
import Button from '../Button'; import LegacyButton from '../LegacyButton';
import Icon from '../Icon'; import Icon from '../Icon';
import IconButton from '../IconButton'; import IconButton from '../IconButton';
import Tooltip from '../Tooltip'; import Tooltip from '../Tooltip';
@ -234,7 +234,8 @@ const SidePanel = ({
}} }}
data-cy={`side-panel-header-${side}`} data-cy={`side-panel-header-${side}`}
> >
<Button {/* TODO This should be redesigned to not be a button. */}
<LegacyButton
variant="text" variant="text"
color="inherit" color="inherit"
border="none" border="none"
@ -254,7 +255,7 @@ const SidePanel = ({
<span className="text-primary-active"> <span className="text-primary-active">
{tabs.length === 1 && (t(tabs[activeTabIndex].label) as string)} {tabs.length === 1 && (t(tabs[activeTabIndex].label) as string)}
</span> </span>
</Button> </LegacyButton>
</div> </div>
{tabs.length > 1 && {tabs.length > 1 &&
_getMoreThanOneTabLayout( _getMoreThanOneTabLayout(

View File

@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
import StudyItem from '../StudyItem'; import StudyItem from '../StudyItem';
import ButtonGroup from '../ButtonGroup'; import ButtonGroup from '../ButtonGroup';
import Button from '../Button'; import LegacyButton from '../LegacyButton';
import ThumbnailList from '../ThumbnailList'; import ThumbnailList from '../ThumbnailList';
import { StringNumber } from '../../types'; import { StringNumber } from '../../types';
@ -81,6 +81,7 @@ const StudyBrowser = ({
className="flex flex-row items-center justify-center h-16 p-4 border-b w-100 border-secondary-light bg-primary-dark" className="flex flex-row items-center justify-center h-16 p-4 border-b w-100 border-secondary-light bg-primary-dark"
data-cy={'studyBrowser-panel'} data-cy={'studyBrowser-panel'}
> >
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<ButtonGroup variant="outlined" color="secondary" splitBorder={false}> <ButtonGroup variant="outlined" color="secondary" splitBorder={false}>
{tabs.map(tab => { {tabs.map(tab => {
const { name, label, studies } = tab; const { name, label, studies } = tab;
@ -95,7 +96,7 @@ const StudyBrowser = ({
}; };
const color = classStudyBrowser[`${isActive}`]; const color = classStudyBrowser[`${isActive}`];
return ( return (
<Button <LegacyButton
key={name} key={name}
className={'text-white text-base p-2 min-w-18'} className={'text-white text-base p-2 min-w-18'}
size="initial" size="initial"
@ -107,7 +108,7 @@ const StudyBrowser = ({
disabled={isDisabled} disabled={isDisabled}
> >
{t(label)} {t(label)}
</Button> </LegacyButton>
); );
})} })}
</ButtonGroup> </ButtonGroup>

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Button from '../Button'; import LegacyButton from '../LegacyButton';
import Icon from '../Icon'; import Icon from '../Icon';
import Typography from '../Typography'; import Typography from '../Typography';
import InputGroup from '../InputGroup'; import InputGroup from '../InputGroup';
@ -48,8 +48,9 @@ const StudyListFilter = ({
)} )}
</div> </div>
<div className="flex flex-row"> <div className="flex flex-row">
{/* TODO revisit the completely rounded style of button used for clearing the study list filter - for now use LegacyButton*/}
{isFiltering && ( {isFiltering && (
<Button <LegacyButton
rounded="full" rounded="full"
variant="outlined" variant="outlined"
color="primaryActive" color="primaryActive"
@ -59,7 +60,7 @@ const StudyListFilter = ({
onClick={clearFilters} onClick={clearFilters}
> >
{t('ClearFilters')} {t('ClearFilters')}
</Button> </LegacyButton>
)} )}
<Typography <Typography
variant="h4" variant="h4"

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Button from '../Button'; import LegacyButton from '../LegacyButton';
import ButtonGroup from '../ButtonGroup'; import ButtonGroup from '../ButtonGroup';
import Typography from '../Typography'; import Typography from '../Typography';
import Select from '../Select'; import Select from '../Select';
@ -59,8 +59,9 @@ const StudyListPagination = ({
<Typography className="opacity-60 mr-4 text-base"> <Typography className="opacity-60 mr-4 text-base">
{t('Page')} {currentPage} {t('Page')} {currentPage}
</Typography> </Typography>
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
<ButtonGroup> <ButtonGroup>
<Button <LegacyButton
size="initial" size="initial"
className="px-4 py-2 text-base" className="px-4 py-2 text-base"
color="translucent" color="translucent"
@ -69,8 +70,8 @@ const StudyListPagination = ({
onClick={() => navigateToPage(1)} onClick={() => navigateToPage(1)}
> >
{`<<`} {`<<`}
</Button> </LegacyButton>
<Button <LegacyButton
size="initial" size="initial"
className="py-2 px-2 text-base" className="py-2 px-2 text-base"
color="translucent" color="translucent"
@ -79,8 +80,8 @@ const StudyListPagination = ({
onClick={() => navigateToPage(currentPage - 1)} onClick={() => navigateToPage(currentPage - 1)}
> >
{t('Previous')} {t('Previous')}
</Button> </LegacyButton>
<Button <LegacyButton
size="initial" size="initial"
className="py-2 px-4 text-base" className="py-2 px-4 text-base"
color="translucent" color="translucent"
@ -89,7 +90,7 @@ const StudyListPagination = ({
onClick={() => navigateToPage(currentPage + 1)} onClick={() => navigateToPage(currentPage + 1)}
> >
{t('Next')} {t('Next')}
</Button> </LegacyButton>
</ButtonGroup> </ButtonGroup>
</div> </div>
</div> </div>

View File

@ -6,6 +6,7 @@ import Select from '../Select';
import Typography from '../Typography'; import Typography from '../Typography';
import Button from '../Button'; import Button from '../Button';
import HotkeysPreferences from '../HotkeysPreferences'; import HotkeysPreferences from '../HotkeysPreferences';
import { ButtonEnums } from '../Button';
const UserPreferences = ({ const UserPreferences = ({
availableLanguages, availableLanguages,
@ -104,22 +105,18 @@ const UserPreferences = ({
</Section> </Section>
<div className="flex flex-row justify-between"> <div className="flex flex-row justify-between">
<Button <Button
variant="outlined" type={ButtonEnums.type.secondary}
border="light"
onClick={onResetHandler} onClick={onResetHandler}
disabled={disabled} disabled={disabled}
> >
{t('Reset to Defaults')} {t('Reset to Defaults')}
</Button> </Button>
<div className="flex flex-row"> <div className="flex flex-row">
<Button variant="outlined" border="light" onClick={onCancelHandler}> <Button type={ButtonEnums.type.secondary} onClick={onCancelHandler}>
{t('Cancel')} {t('Cancel')}
</Button> </Button>
<Button <Button
variant="contained"
disabled={state.isDisabled} disabled={state.isDisabled}
color="light"
border="light"
className="ml-2" className="ml-2"
onClick={onSubmitHandler} onClick={onSubmitHandler}
> >

View File

@ -14,7 +14,7 @@ import IconButton from '../IconButton';
import Icon from '../Icon'; import Icon from '../Icon';
import Select from '../Select'; import Select from '../Select';
import InputLabelWrapper from '../InputLabelWrapper'; import InputLabelWrapper from '../InputLabelWrapper';
import Button from '../Button'; import Button, { ButtonEnums } from '../Button';
const FILE_TYPE_OPTIONS = [ const FILE_TYPE_OPTIONS = [
{ {
@ -401,13 +401,9 @@ const ViewportDownloadForm = ({
<div className="flex justify-end mt-4"> <div className="flex justify-end mt-4">
<Button <Button
data-cy="cancel-btn" name="cancel"
variant="outlined" type={ButtonEnums.type.secondary}
size="initial"
color="black"
border="secondary"
onClick={onClose} onClick={onClose}
className="p-2"
> >
{t('Cancel')} {t('Cancel')}
</Button> </Button>
@ -415,8 +411,8 @@ const ViewportDownloadForm = ({
className="ml-2" className="ml-2"
disabled={hasError} disabled={hasError}
onClick={downloadImage} onClick={downloadImage}
color="primary" type={ButtonEnums.type.primary}
data-cy="download-btn" name={'download'}
> >
{t('Download')} {t('Download')}
</Button> </Button>

View File

@ -1,6 +1,7 @@
import AboutModal from './AboutModal'; import AboutModal from './AboutModal';
import Button from './Button'; import Button from './Button';
import ButtonGroup from './ButtonGroup'; import ButtonGroup from './ButtonGroup';
import { ButtonEnums } from './Button';
import ContextMenu from './ContextMenu'; import ContextMenu from './ContextMenu';
import CinePlayer from './CinePlayer'; import CinePlayer from './CinePlayer';
import DateRange from './DateRange'; import DateRange from './DateRange';
@ -18,6 +19,7 @@ import InputMultiSelect from './InputMultiSelect';
import InputText from './InputText'; import InputText from './InputText';
import Label from './Label'; import Label from './Label';
import LayoutSelector from './LayoutSelector'; import LayoutSelector from './LayoutSelector';
import LegacyButton from './LegacyButton';
import LegacyCinePlayer from './LegacyCinePlayer'; import LegacyCinePlayer from './LegacyCinePlayer';
import LegacyViewportActionBar from './LegacyViewportActionBar'; import LegacyViewportActionBar from './LegacyViewportActionBar';
import MeasurementTable from './MeasurementTable'; import MeasurementTable from './MeasurementTable';
@ -80,6 +82,7 @@ export {
HotkeysPreferences, HotkeysPreferences,
Button, Button,
ButtonGroup, ButtonGroup,
ButtonEnums,
CheckBox, CheckBox,
CinePlayer, CinePlayer,
ContextMenu, ContextMenu,
@ -103,6 +106,7 @@ export {
ImageScrollbar, ImageScrollbar,
Label, Label,
LayoutSelector, LayoutSelector,
LegacyButton,
LegacyCinePlayer, LegacyCinePlayer,
LegacyViewportActionBar, LegacyViewportActionBar,
LoadingIndicatorProgress, LoadingIndicatorProgress,

View File

@ -42,6 +42,7 @@ export {
HotkeysPreferences, HotkeysPreferences,
Button, Button,
ButtonGroup, ButtonGroup,
ButtonEnums,
ContextMenu, ContextMenu,
CinePlayer, CinePlayer,
DateRange, DateRange,
@ -62,6 +63,7 @@ export {
InputText, InputText,
Label, Label,
LayoutSelector, LayoutSelector,
LegacyButton,
LegacyCinePlayer, LegacyCinePlayer,
LegacyViewportActionBar, LegacyViewportActionBar,
LoadingIndicatorProgress, LoadingIndicatorProgress,

View File

@ -63,9 +63,16 @@ module.exports = {
}, },
customblue: { customblue: {
10: '#0A163F',
20: '#0B1F54',
30: '#09286e',
40: '#0E307F',
50: '#0F3A94',
80: '#1454D4',
100: '#c4fdff', 100: '#c4fdff',
200: '#38daff', 200: '#38daff',
300: '#1D204D', 300: '#1D204D',
400: '#90A0C1',
}, },
customgray: { customgray: {