diff --git a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.js b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.js index 2f8f50b16a..c6b1fe0a49 100644 --- a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.js +++ b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.js @@ -6,14 +6,14 @@ import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogTitle from '@material-ui/core/DialogTitle'; import { withStyles } from '@material-ui/core/styles'; -import IconButton from '@material-ui/core/IconButton'; +import { IconButton } from 'capture-ui'; import { IconCross24, Button } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; import isDefined from 'd2-utilizr/lib/isDefined'; -const styles = theme => ({ +const styles = () => ({ closeButton: { - height: theme.spacing.unit * 4, + marginTop: '5px', }, actionContainer: { paddingRight: 2, @@ -58,7 +58,7 @@ class Index extends React.Component { const { feedback, classes } = this.props; return ( - + <> { (() => { if (!feedback.action) { @@ -75,15 +75,12 @@ class Index extends React.Component { })() } - + ); } diff --git a/src/core_modules/capture-core/components/ListView/ColumnSelector/ColumnSelector.component.js b/src/core_modules/capture-core/components/ListView/ColumnSelector/ColumnSelector.component.js index 44ae08d186..6974ef1048 100644 --- a/src/core_modules/capture-core/components/ListView/ColumnSelector/ColumnSelector.component.js +++ b/src/core_modules/capture-core/components/ListView/ColumnSelector/ColumnSelector.component.js @@ -1,6 +1,6 @@ // @flow import * as React from 'react'; -import { IconButton } from '@material-ui/core'; +import { IconButton } from 'capture-ui'; import { IconSettings24, Tooltip } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; import { ColumnSelectorDialog } from './ColumnSelectorDialog.component'; diff --git a/src/core_modules/capture-core/components/ListView/Main/ListViewMain.component.js b/src/core_modules/capture-core/components/ListView/Main/ListViewMain.component.js index 313059ade4..87c71afbee 100644 --- a/src/core_modules/capture-core/components/ListView/Main/ListViewMain.component.js +++ b/src/core_modules/capture-core/components/ListView/Main/ListViewMain.component.js @@ -25,6 +25,7 @@ const getStyles = (theme: Theme) => ({ }, topBarButtonContainer: { display: 'flex', + gap: '6px', alignItems: 'center', }, paginationContainer: { diff --git a/src/core_modules/capture-core/components/ListView/Menu/ListViewMenu.component.js b/src/core_modules/capture-core/components/ListView/Menu/ListViewMenu.component.js index 78a455f997..dd8d628a4d 100644 --- a/src/core_modules/capture-core/components/ListView/Menu/ListViewMenu.component.js +++ b/src/core_modules/capture-core/components/ListView/Menu/ListViewMenu.component.js @@ -1,8 +1,9 @@ // @flow import React, { useCallback, memo, type ComponentType } from 'react'; +import { IconButton } from 'capture-ui'; import { withStyles } from '@material-ui/core/styles'; import { Divider, IconMore24 } from '@dhis2/ui'; -import { IconButton, Paper, MenuList, MenuItem } from '@material-ui/core'; +import { Paper, MenuList, MenuItem } from '@material-ui/core'; import { MenuPopper } from '../../Popper/Popper.component'; import type { Props } from './listViewMenu.types'; @@ -32,7 +33,7 @@ const getStyles = () => ({ const ListViewMenuPlain = ({ customMenuContents = [], classes }: Props) => { const renderPopperAction = useCallback((togglePopper: Function) => ( diff --git a/src/core_modules/capture-core/components/Pagination/withDefaultNavigation.js b/src/core_modules/capture-core/components/Pagination/withDefaultNavigation.js index 335cc9f43e..77fe10dafa 100644 --- a/src/core_modules/capture-core/components/Pagination/withDefaultNavigation.js +++ b/src/core_modules/capture-core/components/Pagination/withDefaultNavigation.js @@ -4,13 +4,13 @@ */ import * as React from 'react'; import { withStyles } from '@material-ui/core/styles'; - -import IconButton from '@material-ui/core/IconButton'; +import { IconButton } from 'capture-ui'; import { IconChevronLeft24, IconChevronRight24 } from '@dhis2/ui'; const styles = (theme: Theme) => ({ root: { flexShrink: 0, + display: 'flex', color: theme.palette.text.secondary, }, }); @@ -81,7 +81,7 @@ const getNavigation = (InnerComponent: React.ComponentType) => className={classes.root} > ) => {theme.direction === 'rtl' ? : } ) => {theme.direction === 'rtl' ? : } ({ container: { @@ -87,14 +87,13 @@ class SectionHeaderSimplePlain extends Component { (() => { if (onChangeCollapseState) { return ( - - {this.props.isCollapsed ? : } - + dataTest={'collapsible-button'} + /> ); } return null; diff --git a/src/core_modules/capture-ui/AgeField/AgeField.component.js b/src/core_modules/capture-ui/AgeField/AgeField.component.js index b48763e956..ccf1bbaad9 100644 --- a/src/core_modules/capture-ui/AgeField/AgeField.component.js +++ b/src/core_modules/capture-ui/AgeField/AgeField.component.js @@ -3,7 +3,7 @@ import React, { Component } from 'react'; import { isValidPositiveInteger } from 'capture-core-utils/validators/form'; import i18n from '@dhis2/d2-i18n'; import classNames from 'classnames'; -import IconButton from '@material-ui/core/IconButton'; +import { IconButton } from 'capture-ui'; import { IconCross24 } from '@dhis2/ui'; import { AgeNumberInput } from '../internal/AgeInput/AgeNumberInput.component'; import { AgeDateInput } from '../internal/AgeInput/AgeDateInput.component'; @@ -249,7 +249,7 @@ class D2AgeFieldPlain extends Component { {this.renderNumberInput(currentValues, 'months', 'Months')} {this.renderNumberInput(currentValues, 'days', 'Days')}
- + diff --git a/src/core_modules/capture-ui/AgeField/ageField.module.css b/src/core_modules/capture-ui/AgeField/ageField.module.css index 753c527700..ffd6907cf9 100644 --- a/src/core_modules/capture-ui/AgeField/ageField.module.css +++ b/src/core_modules/capture-ui/AgeField/ageField.module.css @@ -10,6 +10,7 @@ .containerHorizontal { display: flex; flex-wrap: wrap; + align-items: center; } .ageNumberInputContainer { diff --git a/src/core_modules/capture-ui/CoordinateField/CoordinateField.component.js b/src/core_modules/capture-ui/CoordinateField/CoordinateField.component.js index 31ef11095f..48eecdaca7 100644 --- a/src/core_modules/capture-ui/CoordinateField/CoordinateField.component.js +++ b/src/core_modules/capture-ui/CoordinateField/CoordinateField.component.js @@ -5,7 +5,7 @@ import i18n from '@dhis2/d2-i18n'; import { Map, TileLayer, Marker, withLeaflet } from 'react-leaflet'; import { ReactLeafletSearch } from 'react-leaflet-search-unpolyfilled'; import { IconCross24, Button } from '@dhis2/ui'; -import IconButton from '@material-ui/core/IconButton'; +import { IconButton } from 'capture-ui'; import { AddLocationIcon } from '../Icons'; import { CoordinateInput } from '../internal/CoordinateInput/CoordinateInput.component'; import defaultClasses from './coordinateField.module.css'; @@ -125,12 +125,10 @@ export class CoordinateField extends React.Component { - +
diff --git a/src/core_modules/capture-ui/CoordinateField/coordinateField.module.css b/src/core_modules/capture-ui/CoordinateField/coordinateField.module.css index e5aa4a8f4e..d73c64bcf2 100644 --- a/src/core_modules/capture-ui/CoordinateField/coordinateField.module.css +++ b/src/core_modules/capture-ui/CoordinateField/coordinateField.module.css @@ -27,10 +27,11 @@ .mapIconContainerWithMargin { position: relative; display: flex; + overflow: hidden; align-items: center; justify-content: center; - height: 41px; - width: 41px; + height: 40.5px; + width: 40.5px; border: 1px solid #a0adba; border-radius: 4px 0px 0px 4px; color: #212934; diff --git a/src/core_modules/capture-ui/IconButton/IconButton.component.js b/src/core_modules/capture-ui/IconButton/IconButton.component.js index cdaa3014ab..758cdc1e85 100644 --- a/src/core_modules/capture-ui/IconButton/IconButton.component.js +++ b/src/core_modules/capture-ui/IconButton/IconButton.component.js @@ -1,33 +1,49 @@ // @flow -import React, { useCallback } from 'react'; +import React from 'react'; import cx from 'classnames'; -import classes from './iconButton.module.css'; +import { withStyles } from '@material-ui/core/styles'; +import { colors } from '@dhis2/ui'; import type { Props } from './iconButton.types'; -export const IconButton = ({ children, className, dataTest, onClick, ...passOnProps }: Props) => { - const handleKeyDown = useCallback((event: SyntheticKeyboardEvent) => { - if ([' ', 'Enter', 'Spacebar'].includes(event.key)) { - onClick(event); - } - }, [onClick]); +const styles = { + button: { + cursor: 'pointer', + borderRadius: '3px', + border: 'none', + background: 'transparent', + display: 'flex', + alignItems: 'center', + padding: '2px', + justifyContent: 'center', + color: colors.grey700, + '&:hover': { + background: colors.grey200, + color: colors.grey800, + }, + '&:focus': { + outline: 'solid', + background: colors.grey200, + color: colors.grey800, + }, + '&.disabled': { + color: colors.grey500, + cursor: 'not-allowed', + }, + }, +}; - const handleMouseDown = useCallback((event: SyntheticMouseEvent) => { - event.preventDefault(); - }, []); +const IconButtonPlain = ({ children, className, dataTest, onClick, disabled, classes, ...passOnProps }: Props) => ( + +); - return ( - - {children} - - ); -}; +export const IconButton = withStyles(styles)(IconButtonPlain); diff --git a/src/core_modules/capture-ui/IconButton/iconButton.module.css b/src/core_modules/capture-ui/IconButton/iconButton.module.css index 7e68f83f0e..b6cb38532f 100644 --- a/src/core_modules/capture-ui/IconButton/iconButton.module.css +++ b/src/core_modules/capture-ui/IconButton/iconButton.module.css @@ -8,3 +8,4 @@ outline-width: 1px; outline-offset: 0px; } + diff --git a/src/core_modules/capture-ui/IconButton/iconButton.types.js b/src/core_modules/capture-ui/IconButton/iconButton.types.js index 29eb9cc901..910ed37bc3 100644 --- a/src/core_modules/capture-ui/IconButton/iconButton.types.js +++ b/src/core_modules/capture-ui/IconButton/iconButton.types.js @@ -4,5 +4,7 @@ export type Props = { children: React$Node, className?: string, dataTest?: string, - onClick: (event: SyntheticKeyboardEvent | SyntheticMouseEvent | SyntheticTouchEvent) => void, + disabled?: boolean, + onClick: (event: SyntheticKeyboardEvent | SyntheticMouseEvent | SyntheticTouchEvent) => void, + ...CssClasses, }; diff --git a/src/core_modules/capture-ui/Icons/ChevronIcon.component.js b/src/core_modules/capture-ui/Icons/ChevronIcon.component.js new file mode 100644 index 0000000000..491b1cb452 --- /dev/null +++ b/src/core_modules/capture-ui/Icons/ChevronIcon.component.js @@ -0,0 +1,88 @@ +// @flow +import React, { useState, useEffect } from 'react'; +import { IconButton } from 'capture-ui'; +import cx from 'classnames'; +import { withStyles } from '@material-ui/core/styles'; +import { colors, spacersNum, IconChevronUp24 } from '@dhis2/ui'; + +type ChevronIconProps = { + open: boolean, + dataTest?: string, + onOpen: () => void, + onClose: () => void, + disabled?: boolean, + ...CssClasses, +}; + +const styles = { + toggleButton: { + margin: `0 0 0 ${spacersNum.dp4}px`, + height: '24px', + borderRadius: '3px', + color: colors.grey600, + '&:hover': { + background: colors.grey200, + color: colors.grey800, + }, + '&.open': { + animation: 'flipOpen 200ms normal forwards linear', + }, + '&.close': { + animation: 'flipClose 200ms normal forwards linear', + }, + '&.closeinit': { + transform: 'rotateX(180deg)', + }, + '&.disabled': { + color: colors.grey400, + cursor: 'not-allowed', + }, + }, + '@keyframes flipOpen': { + from: { transform: 'rotateX(180deg)' }, + to: { transform: 'rotateX(0)' }, + }, + '@keyframes flipClose': { + from: { transform: 'rotateX(0)' }, + to: { transform: 'rotateX(180deg)' }, + }, +}; + +const ChevronIconPlain = ({ open, onOpen, onClose, dataTest, disabled, classes }: ChevronIconProps) => { + const [postEffectOpen, setPostEffectOpenStatus] = useState(open); + const [animationsReady, setAnimationsReadyStatus] = useState(false); + + const handleClick = () => { + if (disabled) { + return null; + } + return open ? onClose() : onOpen(); + }; + + useEffect(() => { + if (!animationsReady) { + setAnimationsReadyStatus(true); + } + + setPostEffectOpenStatus(open); + }, [open, animationsReady]); + + return ( + + + + ); +}; + +export const ChevronIcon = withStyles(styles)(ChevronIconPlain); + diff --git a/src/core_modules/capture-ui/Icons/index.js b/src/core_modules/capture-ui/Icons/index.js index 70e0b1b0a9..1f4dfc1f82 100644 --- a/src/core_modules/capture-ui/Icons/index.js +++ b/src/core_modules/capture-ui/Icons/index.js @@ -6,4 +6,5 @@ export { MultiSelectionUncheckedIcon } from './MultiSelectionUncheckedIcon.compo export { SingleSelectionCheckedIcon } from './SingleSelectionCheckedIcon.component'; export { SingleSelectionUncheckedIcon } from './SingleSelectionUncheckedIcon.component'; export { BookmarkAddIcon } from './BookmarkAddIcon.component'; +export { ChevronIcon } from './ChevronIcon.component'; diff --git a/src/core_modules/capture-ui/index.js b/src/core_modules/capture-ui/index.js index c0a8aa0ac1..4ef8f7033a 100644 --- a/src/core_modules/capture-ui/index.js +++ b/src/core_modules/capture-ui/index.js @@ -29,5 +29,6 @@ export { Pagination } from './Pagination/Pagination.component'; // UI-Elements export { DividerHorizontal } from './Divider/DividerHorizontal.component'; export { IconButton } from './IconButton'; +export { ChevronIcon } from './Icons'; export { NonBundledIcon } from './NonBundledIcon'; export { FlatList } from './FlatList';