Front small ui fixes (#428)

* fix: add ellipsis in all table cells

* fix: workspace click redirect to home

* fix: add company chip story and edit comment cell story

* fix: remove cursor pointer on workspace name

* fix: snoop pill height

* fix: rebase
This commit is contained in:
Jérémy M
2023-06-27 17:56:48 +02:00
committed by GitHub
parent edee69bc07
commit c9038bb93a
15 changed files with 144 additions and 61 deletions

View File

@ -3,27 +3,14 @@ import styled from '@emotion/styled';
import { CommentChip, CommentChipProps } from './CommentChip';
// TODO: tie those fixed values to the other components in the cell
const StyledCellWrapper = styled.div`
position: absolute;
right: -46px;
top: 3px;
`;
const StyledCommentChipContainer = styled.div`
display: flex;
justify-content: flex-end;
position: relative;
right: 50px;
width: 50px;
`;
const StyledCellWrapper = styled.div``;
export function CellCommentChip(props: CommentChipProps) {
if (props.count === 0) return null;
return (
<StyledCellWrapper>
<StyledCommentChipContainer>
<CommentChip {...props} />
</StyledCommentChipContainer>
<CommentChip {...props} />
</StyledCellWrapper>
);
}

View File

@ -20,19 +20,20 @@ const TestCellContainer = styled.div`
display: flex;
height: fit-content;
justify-content: flex-start;
justify-content: space-between;
max-width: 250px;
min-width: 250px;
overflow: hidden;
text-wrap: nowrap;
`;
const StyledFakeCellText = styled.div`
display: flex;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
export const OneComment: Story = {
@ -60,7 +61,7 @@ export const InCellOverlappingBlur: Story = {
render: getRenderWrapperForComponent(
<TestCellContainer>
<StyledFakeCellText>
Fake long text to demonstrate blur effect
Fake long text to demonstrate ellipsis
</StyledFakeCellText>
<CellCommentChip count={12} />
</TestCellContainer>,

View File

@ -15,6 +15,7 @@ const StyledContainer = styled.span`
display: inline-flex;
gap: ${({ theme }) => theme.spacing(1)};
height: calc(20px - 2 * ${({ theme }) => theme.spacing(1)});
overflow: hidden;
padding: ${({ theme }) => theme.spacing(1)};
@ -31,6 +32,12 @@ const StyledContainer = styled.span`
}
`;
const StyledName = styled.span`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
function CompanyChip({ name, picture }: CompanyChipPropsType) {
return (
<StyledContainer data-testid="company-chip">
@ -42,7 +49,7 @@ function CompanyChip({ name, picture }: CompanyChipPropsType) {
size={14}
/>
)}
{name}
<StyledName>{name}</StyledName>
</StyledContainer>
);
}

View File

@ -0,0 +1,52 @@
import styled from '@emotion/styled';
import type { Meta, StoryObj } from '@storybook/react';
import { getRenderWrapperForComponent } from '~/testing/renderWrappers';
import CompanyChip from '../CompanyChip';
const meta: Meta<typeof CompanyChip> = {
title: 'Modules/Companies/CompanyChip',
component: CompanyChip,
};
export default meta;
type Story = StoryObj<typeof CompanyChip>;
const TestCellContainer = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.primary};
display: flex;
height: fit-content;
justify-content: space-between;
max-width: 250px;
min-width: 250px;
overflow: hidden;
text-wrap: nowrap;
`;
export const SmallName: Story = {
render: getRenderWrapperForComponent(
<TestCellContainer>
<CompanyChip
name="Instragram"
picture="https://api.faviconkit.com/instagram.com/144"
/>
</TestCellContainer>,
),
};
export const BigName: Story = {
render: getRenderWrapperForComponent(
<TestCellContainer>
<CompanyChip
name="Google with a real big name to overflow the cell"
picture="https://api.faviconkit.com/google.com/144"
/>
</TestCellContainer>,
),
};

View File

@ -13,13 +13,17 @@ type OwnProps = {
onChange: (firstname: string, lastname: string) => void;
};
const StyledDiv = styled.div`
const NoEditModeContainer = styled.div`
align-items: center;
display: flex;
justify-content: space-between;
width: 100%;
`;
const RightContainer = styled.div`
margin-left: ${(props) => props.theme.spacing(1)};
`;
export function EditablePeopleFullName({ person, onChange }: OwnProps) {
const [firstnameValue, setFirstnameValue] = useState(person.firstname ?? '');
const [lastnameValue, setLastnameValue] = useState(person.lastname ?? '');
@ -55,15 +59,15 @@ export function EditablePeopleFullName({ person, onChange }: OwnProps) {
secondValuePlaceholder="Last name"
onChange={handleDoubleTextChange}
nonEditModeContent={
<>
<StyledDiv>
<PersonChip name={person.firstname + ' ' + person.lastname} />
</StyledDiv>
<CellCommentChip
count={person._commentCount ?? 0}
onClick={handleCommentClick}
/>
</>
<NoEditModeContainer>
<PersonChip name={person.firstname + ' ' + person.lastname} />
<RightContainer>
<CellCommentChip
count={person._commentCount ?? 0}
onClick={handleCommentClick}
/>
</RightContainer>
</NoEditModeContainer>
}
/>
);

View File

@ -34,6 +34,12 @@ const StyledContainer = styled.span`
white-space: nowrap;
`;
const StyledName = styled.span`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
export function PersonChip({ name, picture }: PersonChipPropsType) {
return (
<StyledContainer data-testid="person-chip">
@ -42,7 +48,7 @@ export function PersonChip({ name, picture }: PersonChipPropsType) {
src={picture ? picture.toString() : PersonPlaceholder.toString()}
alt="person"
/>
{name}
<StyledName>{name}</StyledName>
</StyledContainer>
);
}

View File

@ -6,8 +6,8 @@ export const EditableCellNormalModeOuterContainer = styled.div`
display: flex;
height: 100%;
overflow: hidden;
padding-left: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(1)};
width: 100%;

View File

@ -11,7 +11,11 @@ export type EditableChipProps = {
picture: string;
changeHandler: (updated: string) => void;
editModeHorizontalAlign?: 'left' | 'right';
ChipComponent: ComponentType<{ name: string; picture: string }>;
ChipComponent: ComponentType<{
name: string;
picture: string;
isOverlapped?: boolean;
}>;
commentCount?: number;
onCommentClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
rightEndContents?: ReactNode[];
@ -24,11 +28,17 @@ const StyledInplaceInput = styled.input`
${textInputStyle}
`;
const StyledInplaceShow = styled.div`
const NoEditModeContainer = styled.div`
align-items: center;
display: flex;
justify-content: space-between;
width: 100%;
`;
const RightContainer = styled.div`
margin-left: ${(props) => props.theme.spacing(1)};
`;
function EditableChip({
value,
placeholder,
@ -67,20 +77,20 @@ function EditableChip({
/>
}
nonEditModeContent={
<>
<StyledInplaceShow>
<ChipComponent name={inputValue} picture={picture} />
</StyledInplaceShow>
{rightEndContents &&
rightEndContents.length > 0 &&
rightEndContents.map((content, index) => (
<div key={index} onClick={handleRightEndContentClick}>
{content}
</div>
))}
</>
<NoEditModeContainer>
<ChipComponent name={inputValue} picture={picture} />
<RightContainer>
{rightEndContents &&
rightEndContents.length > 0 &&
rightEndContents.map((content, index) => (
<div key={index} onClick={handleRightEndContentClick}>
{content}
</div>
))}
</RightContainer>
</NoEditModeContainer>
}
></EditableCell>
/>
);
}

View File

@ -17,6 +17,16 @@ type StyledEditModeProps = {
isEditMode: boolean;
};
const StyledRawLink = styled(RawLink)`
overflow: hidden;
a {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
`;
// TODO: refactor
const StyledEditInplaceInput = styled.input<StyledEditModeProps>`
margin: 0;
@ -48,9 +58,9 @@ export function EditablePhone({ value, placeholder, changeHandler }: OwnProps) {
/>
}
nonEditModeContent={
<div>
<>
{isValidPhoneNumber(inputValue) ? (
<RawLink
<StyledRawLink
href={parsePhoneNumber(inputValue, 'FR')?.getURI()}
onClick={(event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
@ -58,11 +68,11 @@ export function EditablePhone({ value, placeholder, changeHandler }: OwnProps) {
>
{parsePhoneNumber(inputValue, 'FR')?.formatInternational() ||
inputValue}
</RawLink>
</StyledRawLink>
) : (
<RawLink href="#">{inputValue}</RawLink>
<StyledRawLink href="#">{inputValue}</StyledRawLink>
)}
</div>
</>
}
/>
);

View File

@ -24,6 +24,9 @@ const StyledInplaceInput = styled.input<StyledEditModeProps>`
`;
const StyledNoEditText = styled.div`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;
`;

View File

@ -3,6 +3,7 @@ import { Link as ReactLink } from 'react-router-dom';
import styled from '@emotion/styled';
type OwnProps = {
className?: string;
href: string;
children?: React.ReactNode;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
@ -17,9 +18,9 @@ const StyledClickable = styled.div`
}
`;
export function RawLink({ href, children, onClick }: OwnProps) {
export function RawLink({ className, href, children, onClick }: OwnProps) {
return (
<StyledClickable>
<StyledClickable className={className}>
<ReactLink onClick={onClick} to={href}>
{children}
</ReactLink>

View File

@ -70,9 +70,10 @@ const StyledSoonPill = styled.div`
align-items: center;
border-radius: 50px;
background-color: ${({ theme }) => theme.background.transparent.light};
font-size: ${({ theme }) => theme.font.size.xs};
padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)}
${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
font-size: ${({ theme }) => theme.font.size.xxs};
height: 16px;
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(2)};
margin-left: auto; // this aligns the pill to the right
`;

View File

@ -22,7 +22,6 @@ const StyledContainer = styled.div`
const LogoAndNameContainer = styled.div`
align-items: center;
cursor: pointer;
display: flex;
`;

View File

@ -2,6 +2,7 @@ import { grayScale } from './colors';
const common = {
size: {
xxs: '0.625rem',
xs: '0.85rem',
sm: '0.92rem',
md: '1rem',

View File

@ -22,6 +22,7 @@ export const StyledAvatar = styled.div<Omit<OwnProps, 'placeholder'>>`
border-radius: ${(props) => (props.type === 'rounded' ? '50%' : '2px')};
color: ${({ theme }) => theme.font.color.primary};
display: flex;
flex-shrink: 0;
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};