Skip to content

Commit

Permalink
UI/improvements (#4036)
Browse files Browse the repository at this point in the history
* Removed repeated styles and improved padding

* Updated input to match styled mocups and icons

* Updated Styling for multiselect and contact input

* linting

* Regenerated snaps

* Updated remove button alignment on project subform
  • Loading branch information
FuriousLlama authored May 27, 2024
1 parent 5383cbf commit f5cefdd
Show file tree
Hide file tree
Showing 149 changed files with 1,495 additions and 2,246 deletions.
4 changes: 2 additions & 2 deletions source/frontend/src/components/common/Section/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ export const StyledSectionHeader = styled.h2<{ isStyledHeader?: boolean }>`
`;

const StyledFormSection = styled.div<{ noPadding?: boolean }>`
margin: ${props => (props.noPadding === true ? '' : '1.5rem')};
padding: ${props => (props.noPadding === true ? '' : '1.5rem')};
margin: ${props => (props.noPadding === true ? '' : '1.6rem')};
padding: ${props => (props.noPadding === true ? '' : '1.6rem')};
background-color: white;
text-align: left;
border-radius: 0.5rem;
Expand Down
32 changes: 29 additions & 3 deletions source/frontend/src/components/common/TabView.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { TabsProps } from 'react-bootstrap';
import { Tabs as BsTabs } from 'react-bootstrap';
import styled from 'styled-components';

import * as Styled from '@/components/common/styles';

const TabView: React.FunctionComponent<
React.PropsWithChildren<TabsProps & { className?: string }>
> = ({ children, className, ...props }) => {
return (
<StyledTabWrapper className={className}>
<Styled.Tabs {...props}>{children}</Styled.Tabs>
<StyledTabs {...props}>{children}</StyledTabs>
</StyledTabWrapper>
);
};
Expand All @@ -26,4 +25,31 @@ const StyledTabWrapper = styled.div`
height: 100%;
`;

const StyledTabs = styled(BsTabs)`
background-color: white;
color: ${props => props.theme.css.linkColor};
font-size: 1.4rem;
border-color: transparent;
.nav-tabs {
height: auto;
}
.nav-item {
color: ${props => props.theme.css.linkColor};
min-width: 5rem;
padding: 0.1rem 1.2rem;
&:hover {
color: ${props => props.theme.css.linkHoverColor};
border-color: transparent;
text-decoration: underline;
}
&.active {
background-color: ${props => props.theme.css.highlightBackgroundColor};
font-family: 'BCSans-Bold';
color: ${props => props.theme.css.linkHoverColor};
border-color: transparent;
}
}
`;

export default TabView;
4 changes: 2 additions & 2 deletions source/frontend/src/components/common/form/AsyncTypeahead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ function AsyncTypeaheadInner<T extends TypeaheadModel>(
{/* hide the search icon when user is interacting with typeahead control */}
{({ selected, isMenuShown }: TypeaheadManagerChildProps) =>
isLoading || isMenuShown || selected.length > 0 ? null : (
<div className="rbt-aux">
<FaSearch size="2.5rem" color="#bcbec5" />
<div className="rbt-aux pr-3">
<FaSearch size="1.6rem" color="#bcbec5" />
</div>
)
}
Expand Down
58 changes: 40 additions & 18 deletions source/frontend/src/components/common/form/ContactInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import styled from 'styled-components';
import { Button } from '@/components/common/buttons/Button';
import { Input } from '@/components/common/form';
import { IContactSearchResult } from '@/interfaces';
import { isValidId } from '@/utils';
import { exists, isValidId } from '@/utils';
import { formatNames } from '@/utils/personUtils';

import { LinkButton } from '../buttons';
Expand Down Expand Up @@ -66,17 +66,26 @@ export const ContactInput: React.FC<React.PropsWithChildren<ContactInputProps>>
<TooltipWrapper tooltipId={`${field}-error-tooltip}`} tooltip={errorTooltip}>
<Row>
<Col>
<StyledDiv className={error ? 'is-invalid' : ''}>
<StyledInputLikeDiv
className={error ? 'is-invalid' : ''}
$hasContact={exists(contactInfo)}
onClick={() => {
if (!exists(contactInfo)) {
setShowContactManager(true);
}
}}
>
{text}
<StyledRemoveLinkButton
onClick={() => {
onClear();
}}
disabled={contactInfo === undefined}
>
<MdClose size="2rem" title="remove" />
</StyledRemoveLinkButton>
</StyledDiv>
{exists(contactInfo) && (
<StyledRemoveLinkButton
onClick={() => {
onClear();
}}
>
<MdClose size="2rem" title="remove" />
</StyledRemoveLinkButton>
)}
</StyledInputLikeDiv>
<Input
field={field + '.id'}
placeholder="Select from Contacts"
Expand All @@ -100,31 +109,44 @@ export const ContactInput: React.FC<React.PropsWithChildren<ContactInputProps>>
);
};

const StyledDiv = styled.div`
const StyledInputLikeDiv = styled.div<{ $hasContact: boolean }>`
position: relative;
border-radius: 0.3rem;
padding: 0.6rem;
padding-right: 2.1rem;
min-height: 2.5em;
border-radius: 0.4rem;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
padding-left: 1.2rem;
padding-right: 2.8rem;
background-image: none;
color: ${props => props.theme.bcTokens.typographyColorSecondary};
color: ${props =>
props.$hasContact
? props.theme.bcTokens.typographyColorSecondary
: props.theme.bcTokens.typographyColorPlaceholder};
border: ${props => props.theme.css.borderOutlineColor} solid 0.1rem;
&.is-invalid {
border: ${props => props.theme.bcTokens.surfaceColorPrimaryDangerButtonDefault} solid 0.1rem;
}
cursor: ${props => (props.$hasContact ? 'default' : 'pointer')};
`;

export const StyledRemoveLinkButton = styled(LinkButton)`
&&.btn {
position: absolute;
top: calc(50% - 1.4rem);
right: 0.4rem;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
padding-right: 1.2rem;
height: 1.6rem;
right: 0rem;
color: ${props => props.theme.bcTokens.iconsColorDisabled};
text-decoration: none;
line-height: unset;
.text {
display: none;
}
&:hover,
&:active,
&:focus {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('ContactInputView component', () => {
<Formik
onSubmit={noop}
initialValues={
props.initialValues ?? ({ test: { firstName: 'blah', surname: 'blah' } } as any)
props.initialValues ?? ({ test: { id:'234', firstName: 'blah', surname: 'blah' } } as any)
}
>
<ContactInputView {...{ ...props }} />
Expand Down Expand Up @@ -102,25 +102,25 @@ describe('ContactInputView component', () => {
});

it('calls onClear when cancel clicked', async () => {
const { getByTitle } = setup({
const { queryByTitle } = setup({
contactManagerProps: { display: false, setSelectedRows: setSelectedRows, selectedRows: [] },
field: 'test',
setShowContactManager: setShowContactManager,
onClear: clear,
});
const icon = getByTitle('remove');
const icon = queryByTitle('remove');
await act(async () => userEvent.click(icon));
expect(clear).toHaveBeenCalled();
});

it('remove button disabled when no contact selected', async () => {
const { getByTitle } = setup({
it('remove button not present when no contact selected', async () => {
const { queryByTitle } = setup({
contactManagerProps: { display: false, setSelectedRows: setSelectedRows, selectedRows: [] },
field: 'invalid',
setShowContactManager: setShowContactManager,
onClear: clear,
});
const icon = getByTitle('remove');
expect(icon).toBeDisabled();
const icon = queryByTitle('remove');
expect(icon).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '@/components/contact/ContactManagerModal';
import { formatContactSearchResult } from '@/features/contacts/contactUtils';
import { IContactSearchResult } from '@/interfaces';
import { isValidString } from '@/utils';

import { DisplayError } from '../DisplayError';
import { Input } from '../Input';
Expand Down Expand Up @@ -59,18 +60,27 @@ const ContactInputView: React.FunctionComponent<IContactInputViewProps> = ({
<TooltipWrapper tooltipId={`${field}-error-tooltip}`} tooltip={errorTooltip}>
<Row>
<Col>
<StyledDiv className={!!error && !!touch ? 'is-invalid' : ''}>
<StyledInputLikeDiv
className={!!error && !!touch ? 'is-invalid' : ''}
$hasContact={isValidString(contactInfo?.id)}
onClick={() => {
if (!isValidString(contactInfo?.id)) {
setShowContactManager(true);
}
}}
>
{text}
<StyledRemoveLinkButton
onClick={() => {
onClear();
}}
disabled={contactInfo === undefined}
title="remove"
>
<MdClose size="2rem" />
</StyledRemoveLinkButton>
</StyledDiv>
{isValidString(contactInfo?.id) && (
<StyledRemoveLinkButton
onClick={() => {
onClear();
}}
title="remove"
>
<MdClose size="2rem" />
</StyledRemoveLinkButton>
)}
</StyledInputLikeDiv>
<Input
field={field + '.id'}
placeholder="Select from Contacts"
Expand Down Expand Up @@ -109,30 +119,44 @@ const ContactInputView: React.FunctionComponent<IContactInputViewProps> = ({

export default ContactInputView;

const StyledDiv = styled.div`
background: none;
const StyledInputLikeDiv = styled.div<{ $hasContact: boolean }>`
position: relative;
border-radius: 0.3rem;
padding: 0.6rem;
padding-right: 2.1rem;
color: ${props => props.theme.bcTokens.typographyColorSecondary};
border-radius: 0.4rem;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
padding-left: 1.2rem;
padding-right: 2.8rem;
background-image: none;
color: ${props =>
props.$hasContact
? props.theme.bcTokens.typographyColorSecondary
: props.theme.bcTokens.typographyColorPlaceholder};
border: ${props => props.theme.css.borderOutlineColor} solid 0.1rem;
&.is-invalid {
border: ${props => props.theme.bcTokens.surfaceColorPrimaryDangerButtonDefault} solid 0.1rem;
}
cursor: ${props => (props.$hasContact ? 'default' : 'pointer')};
`;

const StyledRemoveLinkButton = styled(LinkButton)`
&&.btn {
position: absolute;
top: calc(50% - 1.4rem);
right: 0.4rem;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
padding-right: 1.2rem;
height: 1.6rem;
right: 0rem;
color: ${props => props.theme.bcTokens.iconsColorDisabled};
text-decoration: none;
line-height: unset;
.text {
display: none;
}
&:hover,
&:active,
&:focus {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,15 @@ exports[`ContactInputView component > renders as expected 1`] = `
}
.c0 {
background: none;
position: relative;
border-radius: 0.3rem;
padding: 0.6rem;
padding-right: 2.1rem;
border-radius: 0.4rem;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
padding-left: 1.2rem;
padding-right: 2.8rem;
background-image: none;
border: solid 0.1rem;
cursor: default;
}
.c0.is-invalid {
Expand All @@ -157,7 +160,11 @@ exports[`ContactInputView component > renders as expected 1`] = `
.c2.c2.btn {
position: absolute;
top: calc(50% - 1.4rem);
right: 0.4rem;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
padding-right: 1.2rem;
height: 1.6rem;
right: 0rem;
-webkit-text-decoration: none;
text-decoration: none;
line-height: unset;
Expand Down Expand Up @@ -224,7 +231,8 @@ exports[`ContactInputView component > renders as expected 1`] = `
id="input-test.id"
name="test.id"
placeholder="Select from Contacts"
value=""
title="234"
value="234"
/>
</div>
</div>
Expand Down
7 changes: 4 additions & 3 deletions source/frontend/src/components/common/form/FastDatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,19 @@ const FormikDatePicker: FunctionComponent<React.PropsWithChildren<FastDatePicker

const StyledGroup = styled(Form.Group)`
.react-datepicker__calendar-icon {
width: 3rem;
width: 2.4rem;
height: 3rem;
margin-top: 0.5rem;
margin-right: 1.2rem;
right: 0;
fill: ${props => props.theme.css.linkColor};
pointer-events: none;
}
.react-datepicker__view-calendar-icon input {
padding: 0.6rem 1rem 0.5rem 0.6rem;
padding: 0.8rem 1.2rem 0.8rem 1.2rem;
}
.react-datepicker-wrapper {
max-width: 16rem;
max-width: 17rem;
}
`;

Expand Down
Loading

0 comments on commit f5cefdd

Please sign in to comment.