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:
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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>,
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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>,
|
||||
),
|
||||
};
|
||||
@ -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>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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%;
|
||||
|
||||
|
||||
@ -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>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -24,6 +24,9 @@ const StyledInplaceInput = styled.input<StyledEditModeProps>`
|
||||
`;
|
||||
|
||||
const StyledNoEditText = styled.div`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
`;
|
||||
|
||||
|
||||
@ -22,7 +22,6 @@ const StyledContainer = styled.div`
|
||||
|
||||
const LogoAndNameContainer = styled.div`
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { grayScale } from './colors';
|
||||
|
||||
const common = {
|
||||
size: {
|
||||
xxs: '0.625rem',
|
||||
xs: '0.85rem',
|
||||
sm: '0.92rem',
|
||||
md: '1rem',
|
||||
|
||||
@ -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};
|
||||
|
||||
Reference in New Issue
Block a user