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';
|
import { CommentChip, CommentChipProps } from './CommentChip';
|
||||||
|
|
||||||
// TODO: tie those fixed values to the other components in the cell
|
// TODO: tie those fixed values to the other components in the cell
|
||||||
const StyledCellWrapper = styled.div`
|
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;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export function CellCommentChip(props: CommentChipProps) {
|
export function CellCommentChip(props: CommentChipProps) {
|
||||||
|
if (props.count === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledCellWrapper>
|
<StyledCellWrapper>
|
||||||
<StyledCommentChipContainer>
|
<CommentChip {...props} />
|
||||||
<CommentChip {...props} />
|
|
||||||
</StyledCommentChipContainer>
|
|
||||||
</StyledCellWrapper>
|
</StyledCellWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,19 +20,20 @@ const TestCellContainer = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
justify-content: flex-start;
|
justify-content: space-between;
|
||||||
|
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
|
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
text-wrap: nowrap;
|
text-wrap: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledFakeCellText = styled.div`
|
const StyledFakeCellText = styled.div`
|
||||||
display: flex;
|
overflow: hidden;
|
||||||
width: 100%;
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const OneComment: Story = {
|
export const OneComment: Story = {
|
||||||
@ -60,7 +61,7 @@ export const InCellOverlappingBlur: Story = {
|
|||||||
render: getRenderWrapperForComponent(
|
render: getRenderWrapperForComponent(
|
||||||
<TestCellContainer>
|
<TestCellContainer>
|
||||||
<StyledFakeCellText>
|
<StyledFakeCellText>
|
||||||
Fake long text to demonstrate blur effect
|
Fake long text to demonstrate ellipsis
|
||||||
</StyledFakeCellText>
|
</StyledFakeCellText>
|
||||||
<CellCommentChip count={12} />
|
<CellCommentChip count={12} />
|
||||||
</TestCellContainer>,
|
</TestCellContainer>,
|
||||||
|
|||||||
@ -15,6 +15,7 @@ const StyledContainer = styled.span`
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: ${({ theme }) => theme.spacing(1)};
|
gap: ${({ theme }) => theme.spacing(1)};
|
||||||
height: calc(20px - 2 * ${({ theme }) => theme.spacing(1)});
|
height: calc(20px - 2 * ${({ theme }) => theme.spacing(1)});
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
padding: ${({ theme }) => theme.spacing(1)};
|
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) {
|
function CompanyChip({ name, picture }: CompanyChipPropsType) {
|
||||||
return (
|
return (
|
||||||
<StyledContainer data-testid="company-chip">
|
<StyledContainer data-testid="company-chip">
|
||||||
@ -42,7 +49,7 @@ function CompanyChip({ name, picture }: CompanyChipPropsType) {
|
|||||||
size={14}
|
size={14}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{name}
|
<StyledName>{name}</StyledName>
|
||||||
</StyledContainer>
|
</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;
|
onChange: (firstname: string, lastname: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledDiv = styled.div`
|
const NoEditModeContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const RightContainer = styled.div`
|
||||||
|
margin-left: ${(props) => props.theme.spacing(1)};
|
||||||
|
`;
|
||||||
|
|
||||||
export function EditablePeopleFullName({ person, onChange }: OwnProps) {
|
export function EditablePeopleFullName({ person, onChange }: OwnProps) {
|
||||||
const [firstnameValue, setFirstnameValue] = useState(person.firstname ?? '');
|
const [firstnameValue, setFirstnameValue] = useState(person.firstname ?? '');
|
||||||
const [lastnameValue, setLastnameValue] = useState(person.lastname ?? '');
|
const [lastnameValue, setLastnameValue] = useState(person.lastname ?? '');
|
||||||
@ -55,15 +59,15 @@ export function EditablePeopleFullName({ person, onChange }: OwnProps) {
|
|||||||
secondValuePlaceholder="Last name"
|
secondValuePlaceholder="Last name"
|
||||||
onChange={handleDoubleTextChange}
|
onChange={handleDoubleTextChange}
|
||||||
nonEditModeContent={
|
nonEditModeContent={
|
||||||
<>
|
<NoEditModeContainer>
|
||||||
<StyledDiv>
|
<PersonChip name={person.firstname + ' ' + person.lastname} />
|
||||||
<PersonChip name={person.firstname + ' ' + person.lastname} />
|
<RightContainer>
|
||||||
</StyledDiv>
|
<CellCommentChip
|
||||||
<CellCommentChip
|
count={person._commentCount ?? 0}
|
||||||
count={person._commentCount ?? 0}
|
onClick={handleCommentClick}
|
||||||
onClick={handleCommentClick}
|
/>
|
||||||
/>
|
</RightContainer>
|
||||||
</>
|
</NoEditModeContainer>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -34,6 +34,12 @@ const StyledContainer = styled.span`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledName = styled.span`
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
`;
|
||||||
|
|
||||||
export function PersonChip({ name, picture }: PersonChipPropsType) {
|
export function PersonChip({ name, picture }: PersonChipPropsType) {
|
||||||
return (
|
return (
|
||||||
<StyledContainer data-testid="person-chip">
|
<StyledContainer data-testid="person-chip">
|
||||||
@ -42,7 +48,7 @@ export function PersonChip({ name, picture }: PersonChipPropsType) {
|
|||||||
src={picture ? picture.toString() : PersonPlaceholder.toString()}
|
src={picture ? picture.toString() : PersonPlaceholder.toString()}
|
||||||
alt="person"
|
alt="person"
|
||||||
/>
|
/>
|
||||||
{name}
|
<StyledName>{name}</StyledName>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,8 @@ export const EditableCellNormalModeOuterContainer = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-left: ${({ theme }) => theme.spacing(2)};
|
|
||||||
|
|
||||||
|
padding-left: ${({ theme }) => theme.spacing(2)};
|
||||||
padding-right: ${({ theme }) => theme.spacing(1)};
|
padding-right: ${({ theme }) => theme.spacing(1)};
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,11 @@ export type EditableChipProps = {
|
|||||||
picture: string;
|
picture: string;
|
||||||
changeHandler: (updated: string) => void;
|
changeHandler: (updated: string) => void;
|
||||||
editModeHorizontalAlign?: 'left' | 'right';
|
editModeHorizontalAlign?: 'left' | 'right';
|
||||||
ChipComponent: ComponentType<{ name: string; picture: string }>;
|
ChipComponent: ComponentType<{
|
||||||
|
name: string;
|
||||||
|
picture: string;
|
||||||
|
isOverlapped?: boolean;
|
||||||
|
}>;
|
||||||
commentCount?: number;
|
commentCount?: number;
|
||||||
onCommentClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
|
onCommentClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
rightEndContents?: ReactNode[];
|
rightEndContents?: ReactNode[];
|
||||||
@ -24,11 +28,17 @@ const StyledInplaceInput = styled.input`
|
|||||||
${textInputStyle}
|
${textInputStyle}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledInplaceShow = styled.div`
|
const NoEditModeContainer = styled.div`
|
||||||
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const RightContainer = styled.div`
|
||||||
|
margin-left: ${(props) => props.theme.spacing(1)};
|
||||||
|
`;
|
||||||
|
|
||||||
function EditableChip({
|
function EditableChip({
|
||||||
value,
|
value,
|
||||||
placeholder,
|
placeholder,
|
||||||
@ -67,20 +77,20 @@ function EditableChip({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
nonEditModeContent={
|
nonEditModeContent={
|
||||||
<>
|
<NoEditModeContainer>
|
||||||
<StyledInplaceShow>
|
<ChipComponent name={inputValue} picture={picture} />
|
||||||
<ChipComponent name={inputValue} picture={picture} />
|
<RightContainer>
|
||||||
</StyledInplaceShow>
|
{rightEndContents &&
|
||||||
{rightEndContents &&
|
rightEndContents.length > 0 &&
|
||||||
rightEndContents.length > 0 &&
|
rightEndContents.map((content, index) => (
|
||||||
rightEndContents.map((content, index) => (
|
<div key={index} onClick={handleRightEndContentClick}>
|
||||||
<div key={index} onClick={handleRightEndContentClick}>
|
{content}
|
||||||
{content}
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</RightContainer>
|
||||||
</>
|
</NoEditModeContainer>
|
||||||
}
|
}
|
||||||
></EditableCell>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,16 @@ type StyledEditModeProps = {
|
|||||||
isEditMode: boolean;
|
isEditMode: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const StyledRawLink = styled(RawLink)`
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
a {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
// TODO: refactor
|
// TODO: refactor
|
||||||
const StyledEditInplaceInput = styled.input<StyledEditModeProps>`
|
const StyledEditInplaceInput = styled.input<StyledEditModeProps>`
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -48,9 +58,9 @@ export function EditablePhone({ value, placeholder, changeHandler }: OwnProps) {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
nonEditModeContent={
|
nonEditModeContent={
|
||||||
<div>
|
<>
|
||||||
{isValidPhoneNumber(inputValue) ? (
|
{isValidPhoneNumber(inputValue) ? (
|
||||||
<RawLink
|
<StyledRawLink
|
||||||
href={parsePhoneNumber(inputValue, 'FR')?.getURI()}
|
href={parsePhoneNumber(inputValue, 'FR')?.getURI()}
|
||||||
onClick={(event: MouseEvent<HTMLElement>) => {
|
onClick={(event: MouseEvent<HTMLElement>) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -58,11 +68,11 @@ export function EditablePhone({ value, placeholder, changeHandler }: OwnProps) {
|
|||||||
>
|
>
|
||||||
{parsePhoneNumber(inputValue, 'FR')?.formatInternational() ||
|
{parsePhoneNumber(inputValue, 'FR')?.formatInternational() ||
|
||||||
inputValue}
|
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`
|
const StyledNoEditText = styled.div`
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { Link as ReactLink } from 'react-router-dom';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
|
className?: string;
|
||||||
href: string;
|
href: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
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 (
|
return (
|
||||||
<StyledClickable>
|
<StyledClickable className={className}>
|
||||||
<ReactLink onClick={onClick} to={href}>
|
<ReactLink onClick={onClick} to={href}>
|
||||||
{children}
|
{children}
|
||||||
</ReactLink>
|
</ReactLink>
|
||||||
|
|||||||
@ -70,9 +70,10 @@ const StyledSoonPill = styled.div`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
background-color: ${({ theme }) => theme.background.transparent.light};
|
background-color: ${({ theme }) => theme.background.transparent.light};
|
||||||
font-size: ${({ theme }) => theme.font.size.xs};
|
font-size: ${({ theme }) => theme.font.size.xxs};
|
||||||
padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)}
|
height: 16px;
|
||||||
${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
|
padding-left: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding-right: ${({ theme }) => theme.spacing(2)};
|
||||||
margin-left: auto; // this aligns the pill to the right
|
margin-left: auto; // this aligns the pill to the right
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,6 @@ const StyledContainer = styled.div`
|
|||||||
|
|
||||||
const LogoAndNameContainer = styled.div`
|
const LogoAndNameContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { grayScale } from './colors';
|
|||||||
|
|
||||||
const common = {
|
const common = {
|
||||||
size: {
|
size: {
|
||||||
|
xxs: '0.625rem',
|
||||||
xs: '0.85rem',
|
xs: '0.85rem',
|
||||||
sm: '0.92rem',
|
sm: '0.92rem',
|
||||||
md: '1rem',
|
md: '1rem',
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export const StyledAvatar = styled.div<Omit<OwnProps, 'placeholder'>>`
|
|||||||
border-radius: ${(props) => (props.type === 'rounded' ? '50%' : '2px')};
|
border-radius: ${(props) => (props.type === 'rounded' ? '50%' : '2px')};
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
|
|||||||
Reference in New Issue
Block a user