From 5fb7d753ef9e7b4341279c24c824d21c25f8e9df Mon Sep 17 00:00:00 2001 From: Emilien Chauvet Date: Wed, 19 Jul 2023 15:31:53 -0700 Subject: [PATCH] Various styling improvements (#766) * Various styling improvements * Add card styling * Fix select when editing fields * Add colors * Refactor prevent click --- .../companies/components/CompanyBoardCard.tsx | 139 ++++++++++++------ .../pipeline/components/EntityBoardColumn.tsx | 3 +- .../src/modules/ui/board/components/Board.tsx | 2 +- .../ui/board/components/BoardColumn.tsx | 23 ++- .../ui/board/components/BoardHeader.tsx | 7 +- .../modules/ui/board/components/NewButton.tsx | 2 +- front/src/modules/ui/icon/index.ts | 1 + front/src/modules/ui/themes/accent.ts | 15 ++ front/src/modules/ui/themes/colors.ts | 8 + front/src/modules/ui/themes/themes.ts | 7 +- 10 files changed, 142 insertions(+), 65 deletions(-) create mode 100644 front/src/modules/ui/themes/accent.ts diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx index cc1002849..130ce1ad8 100644 --- a/front/src/modules/companies/components/CompanyBoardCard.tsx +++ b/front/src/modules/companies/components/CompanyBoardCard.tsx @@ -1,4 +1,4 @@ -import { useCallback } from 'react'; +import { ReactNode, useCallback, useState } from 'react'; import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; import { useRecoilState } from 'recoil'; @@ -13,28 +13,32 @@ import { selectedBoardCardsState } from '@/pipeline/states/selectedBoardCardsSta import { ChipVariant } from '@/ui/chip/components/EntityChip'; import { DateEditableField } from '@/ui/editable-field/variants/components/DateEditableField'; import { NumberEditableField } from '@/ui/editable-field/variants/components/NumberEditableField'; -import { IconCheck, IconCurrencyDollar } from '@/ui/icon'; +import { IconCurrencyDollar, IconProgressCheck } from '@/ui/icon'; import { IconCalendarEvent } from '@/ui/icon'; import { Checkbox } from '@/ui/input/components/Checkbox'; import { useRecoilScopedState } from '@/ui/recoil-scope/hooks/useRecoilScopedState'; import { useUpdateOnePipelineProgressMutation } from '~/generated/graphql'; import { getLogoUrlFromDomainName } from '~/utils'; -import { CompanyAccountOwnerEditableField } from '../editable-field/components/CompanyAccountOwnerEditableField'; import { PipelineProgressForBoard } from '../types/CompanyProgress'; import { CompanyChip } from './CompanyChip'; const StyledBoardCard = styled.div<{ selected: boolean }>` background-color: ${({ theme, selected }) => - selected ? theme.selectedCard : theme.background.secondary}; - border: 1px solid ${({ theme }) => theme.border.color.medium}; + selected ? theme.accent.quaternary : theme.background.secondary}; + border: 1px solid + ${({ theme, selected }) => + selected ? theme.accent.secondary : theme.border.color.medium}; border-radius: ${({ theme }) => theme.border.radius.sm}; box-shadow: ${({ theme }) => theme.boxShadow.light}; color: ${({ theme }) => theme.font.color.primary}; &:hover { background-color: ${({ theme, selected }) => - selected ? theme.selectedCardHover : theme.background.tertiary}; + selected && theme.accent.tertiary}; + border: 1px solid + ${({ theme, selected }) => + selected ? theme.accent.primary : theme.border.color.medium}; } cursor: pointer; `; @@ -49,6 +53,7 @@ const StyledBoardCardHeader = styled.div` flex-direction: row; font-weight: ${({ theme }) => theme.font.weight.semiBold}; height: 24px; + padding-bottom: ${({ theme }) => theme.spacing(1)}; padding-left: ${({ theme }) => theme.spacing(2)}; padding-right: ${({ theme }) => theme.spacing(2)}; padding-top: ${({ theme }) => theme.spacing(2)}; @@ -62,7 +67,10 @@ const StyledBoardCardHeader = styled.div` const StyledBoardCardBody = styled.div` display: flex; flex-direction: column; - padding: ${({ theme }) => theme.spacing(2)}; + gap: ${({ theme }) => theme.spacing(0.5)}; + padding-bottom: ${({ theme }) => theme.spacing(2)}; + padding-left: ${({ theme }) => theme.spacing(2.5)}; + padding-right: ${({ theme }) => theme.spacing(2)}; span { align-items: center; display: flex; @@ -74,7 +82,12 @@ const StyledBoardCardBody = styled.div` } `; +const StyledFieldContainer = styled.div` + width: max-content; +`; + export function CompanyBoardCard() { + const [isHovered, setIsHovered] = useState(false); const [updatePipelineProgress] = useUpdateOnePipelineProgressMutation(); const [pipelineProgressId] = useRecoilScopedState( @@ -119,17 +132,34 @@ export function CompanyBoardCard() { [updatePipelineProgress], ); - const handleCheckboxChange = (checked: boolean) => { - setSelected(checked); - }; - if (!company || !pipelineProgress) { return null; } + function PreventSelectOnClickContainer({ + children, + }: { + children: ReactNode; + }) { + return ( + { + e.stopPropagation(); + }} + > + {children} + + ); + } + return ( - + setSelected(!selected)} + onMouseEnter={() => setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + >
- + {(isHovered || selected) && ( + setSelected(!selected)} + /> + )} - } - placeholder="Opportunity amount" - value={pipelineProgress.amount} - onSubmit={(value) => - handleCardUpdate({ - ...pipelineProgress, - amount: value, - }) - } - /> - - } - value={pipelineProgress.closeDate || new Date().toISOString()} - onSubmit={(value) => - handleCardUpdate({ - ...pipelineProgress, - closeDate: value, - }) - } - /> - - } - value={pipelineProgress.probability} - onSubmit={(value) => { - handleCardUpdate({ - ...pipelineProgress, - probability: value, - }); - }} - /> - + + } + value={pipelineProgress.closeDate || new Date().toISOString()} + onSubmit={(value) => + handleCardUpdate({ + ...pipelineProgress, + closeDate: value, + }) + } + /> + + + } + placeholder="Opportunity amount" + value={pipelineProgress.amount} + onSubmit={(value) => + handleCardUpdate({ + ...pipelineProgress, + amount: value, + }) + } + /> + + + } + value={pipelineProgress.probability} + onSubmit={(value) => { + handleCardUpdate({ + ...pipelineProgress, + probability: value, + }); + }} + /> + + + + diff --git a/front/src/modules/pipeline/components/EntityBoardColumn.tsx b/front/src/modules/pipeline/components/EntityBoardColumn.tsx index a29eb9fec..28ec78907 100644 --- a/front/src/modules/pipeline/components/EntityBoardColumn.tsx +++ b/front/src/modules/pipeline/components/EntityBoardColumn.tsx @@ -24,7 +24,7 @@ const StyledPlaceholder = styled.div` `; const StyledNewCardButtonContainer = styled.div` - padding-bottom: ${({ theme }) => theme.spacing(40)}; + padding-bottom: ${({ theme }) => theme.spacing(4)}; `; const BoardColumnCardsContainer = ({ @@ -86,6 +86,7 @@ export function EntityBoardColumn({ colorCode={column.colorCode} pipelineStageId={column.pipelineStageId} totalAmount={boardColumnTotal} + isFirstColumn={column.index === 0} > {column.pipelineProgressIds.map((pipelineProgressId, index) => ( diff --git a/front/src/modules/ui/board/components/Board.tsx b/front/src/modules/ui/board/components/Board.tsx index 93ad98ac3..37d233d11 100644 --- a/front/src/modules/ui/board/components/Board.tsx +++ b/front/src/modules/ui/board/components/Board.tsx @@ -4,10 +4,10 @@ import { DropResult } from '@hello-pangea/dnd'; // Atlassian dnd does not suppor export const StyledBoard = styled.div` border-radius: ${({ theme }) => theme.spacing(2)}; display: flex; + flex: 1; flex-direction: row; overflow-x: auto; padding-left: ${({ theme }) => theme.spacing(2)}; - width: 100%; `; export type BoardPipelineStageColumn = { diff --git a/front/src/modules/ui/board/components/BoardColumn.tsx b/front/src/modules/ui/board/components/BoardColumn.tsx index 096845cff..34b5777eb 100644 --- a/front/src/modules/ui/board/components/BoardColumn.tsx +++ b/front/src/modules/ui/board/components/BoardColumn.tsx @@ -5,8 +5,11 @@ import { debounce } from '~/utils/debounce'; import { EditColumnTitleInput } from './EditColumnTitleInput'; -export const StyledColumn = styled.div` +export const StyledColumn = styled.div<{ isFirstColumn: boolean }>` background-color: ${({ theme }) => theme.background.primary}; + border-left: 1px solid + ${({ theme, isFirstColumn }) => + isFirstColumn ? 'none' : theme.border.color.light}; display: flex; flex-direction: column; min-width: 200px; @@ -14,15 +17,19 @@ export const StyledColumn = styled.div` `; const StyledHeader = styled.div` + align-items: center; cursor: pointer; display: flex; flex-direction: row; - justify-content: space-between; + height: 24px; + justify-content: left; + margin-bottom: ${({ theme }) => theme.spacing(2)}; width: 100%; `; export const StyledColumnTitle = styled.h3` align-items: center; + border-radius: ${({ theme }) => theme.border.radius.sm}; color: ${({ color }) => color}; display: flex; flex-direction: row; @@ -30,13 +37,16 @@ export const StyledColumnTitle = styled.h3` font-style: normal; font-weight: ${({ theme }) => theme.font.weight.medium}; gap: ${({ theme }) => theme.spacing(2)}; - height: 24px; margin: 0; - margin-bottom: ${({ theme }) => theme.spacing(1)}; + padding-bottom: ${({ theme }) => theme.spacing(1)}; + padding-left: ${({ theme }) => theme.spacing(2)}; + padding-right: ${({ theme }) => theme.spacing(2)}; + padding-top: ${({ theme }) => theme.spacing(1)}; `; const StyledAmount = styled.div` color: ${({ theme }) => theme.font.color.tertiary}; + margin-left: ${({ theme }) => theme.spacing(2)}; `; type OwnProps = { @@ -46,6 +56,7 @@ type OwnProps = { onTitleEdit: (title: string) => void; totalAmount?: number; children: React.ReactNode; + isFirstColumn: boolean; }; export function BoardColumn({ @@ -54,6 +65,7 @@ export function BoardColumn({ onTitleEdit, totalAmount, children, + isFirstColumn, }: OwnProps) { const [isEditing, setIsEditing] = React.useState(false); const [internalValue, setInternalValue] = React.useState(title); @@ -65,10 +77,9 @@ export function BoardColumn({ }; return ( - + setIsEditing(true)}> - • {isEditing ? ( = { }; const StyledContainer = styled.div` + border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; display: flex; flex-direction: column; `; -const StyledTableHeader = styled.div` +const StyledBoardHeader = styled.div` align-items: center; color: ${({ theme }) => theme.font.color.secondary}; display: flex; @@ -83,7 +84,7 @@ export function BoardHeader({ return ( - + {viewIcon} {viewName} @@ -100,7 +101,7 @@ export function BoardHeader({ HotkeyScope={FiltersHotkeyScope.FilterDropdownButton} /> - + theme.spacing(1)}; &:hover { - background-color: ${({ theme }) => theme.background.secondary}; + background-color: ${({ theme }) => theme.background.tertiary}; } `; diff --git a/front/src/modules/ui/icon/index.ts b/front/src/modules/ui/icon/index.ts index 05f637569..b9bf68033 100644 --- a/front/src/modules/ui/icon/index.ts +++ b/front/src/modules/ui/icon/index.ts @@ -12,6 +12,7 @@ export { IconSearch } from '@tabler/icons-react'; export { IconSettings } from '@tabler/icons-react'; export { IconLogout } from '@tabler/icons-react'; export { IconColorSwatch } from '@tabler/icons-react'; +export { IconProgressCheck } from '@tabler/icons-react'; export { IconX } from '@tabler/icons-react'; export { IconChevronLeft } from '@tabler/icons-react'; export { IconPlus } from '@tabler/icons-react'; diff --git a/front/src/modules/ui/themes/accent.ts b/front/src/modules/ui/themes/accent.ts new file mode 100644 index 000000000..7f0250e69 --- /dev/null +++ b/front/src/modules/ui/themes/accent.ts @@ -0,0 +1,15 @@ +import { color } from './colors'; + +export const accentLight = { + primary: color.blueAccent25, + secondary: color.blueAccent20, + tertiary: color.blueAccent15, + quaternary: color.blueAccent10, +}; + +export const accentDark = { + primary: color.blueAccent75, + secondary: color.blueAccent80, + tertiary: color.blueAccent85, + quaternary: color.blueAccent90, +}; diff --git a/front/src/modules/ui/themes/colors.ts b/front/src/modules/ui/themes/colors.ts index b07b1af92..4ee84e8a3 100644 --- a/front/src/modules/ui/themes/colors.ts +++ b/front/src/modules/ui/themes/colors.ts @@ -116,6 +116,14 @@ export const color = { gray20: grayScale.gray15, gray10: grayScale.gray10, gray0: grayScale.gray0, + blueAccent90: '#141a25', + blueAccent85: '#151D2E', + blueAccent80: '#152037', + blueAccent75: '#16233F', + blueAccent25: '#dae6fc', + blueAccent20: '#e2ecfd', + blueAccent15: '#edf2fe', + blueAccent10: '#f5f9fd', }; export function rgba(hex: string, alpha: number) { diff --git a/front/src/modules/ui/themes/themes.ts b/front/src/modules/ui/themes/themes.ts index 3e3b46067..caaed3d70 100644 --- a/front/src/modules/ui/themes/themes.ts +++ b/front/src/modules/ui/themes/themes.ts @@ -1,3 +1,4 @@ +import { accentDark, accentLight } from './accent'; import { animation } from './animation'; import { backgroundDark, backgroundLight } from './background'; import { blur } from './blur'; @@ -43,11 +44,10 @@ const common = { export const lightTheme = { ...common, ...{ + accent: accentLight, background: backgroundLight, border: borderLight, boxShadow: boxShadowLight, - selectedCardHover: color.blue20, - selectedCard: color.blue10, font: fontLight, name: 'light', }, @@ -57,11 +57,10 @@ export type ThemeType = typeof lightTheme; export const darkTheme: ThemeType = { ...common, ...{ + accent: accentDark, background: backgroundDark, border: borderDark, boxShadow: boxShadowDark, - selectedCardHover: color.blue70, - selectedCard: color.blue80, font: fontDark, name: 'dark', },