feat: Revamp navigation bar (#6031)

closes: #4428

Testing for fetchMoreRecords is pending, along with component tests

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Aditya Pimpalkar
2024-07-16 13:38:17 +01:00
committed by GitHub
parent a8dfff3a6d
commit 4a67cfa1c3
66 changed files with 1056 additions and 365 deletions

View File

@ -1,6 +1,6 @@
import { useContext } from 'react';
import { styled } from '@linaria/react';
import { isNonEmptyString, isUndefined } from '@sniptt/guards';
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { invalidAvatarUrlsState } from '@ui/display/avatar/components/states/isInvalidAvatarUrlState';
@ -50,7 +50,7 @@ export type AvatarProps = {
className?: string;
size?: AvatarSize;
placeholder: string | undefined;
entityId?: string;
placeholderColorSeed?: string;
type?: Nullable<AvatarType>;
color?: string;
backgroundColor?: string;
@ -62,7 +62,7 @@ export const Avatar = ({
avatarUrl,
size = 'md',
placeholder,
entityId = placeholder,
placeholderColorSeed = placeholder,
onClick,
type = 'squared',
color,
@ -85,9 +85,10 @@ export const Avatar = ({
}
};
const fixedColor = color ?? stringToHslColor(entityId ?? '', 75, 25);
const fixedColor =
color ?? stringToHslColor(placeholderColorSeed ?? '', 75, 25);
const fixedBackgroundColor =
backgroundColor ?? stringToHslColor(entityId ?? '', 75, 85);
backgroundColor ?? stringToHslColor(placeholderColorSeed ?? '', 75, 85);
const showBackgroundColor = showPlaceholder;

View File

@ -13,7 +13,7 @@ import { AvatarGroup, AvatarGroupProps } from '../AvatarGroup';
const makeAvatar = (userName: string, props: Partial<AvatarProps> = {}) => (
// eslint-disable-next-line react/jsx-props-no-spreading
<Avatar placeholder={userName} entityId={userName} {...props} />
<Avatar placeholder={userName} placeholderColorSeed={userName} {...props} />
);
const getAvatars = (commonProps: Partial<AvatarProps> = {}) => [

View File

@ -1,56 +1,47 @@
import * as React from 'react';
import { useNavigate } from 'react-router-dom';
import { useTheme } from '@emotion/react';
import { isNonEmptyString } from '@sniptt/guards';
import { Avatar } from '@ui/display/avatar/components/Avatar';
import { AvatarType } from '@ui/display/avatar/types/AvatarType';
import { Chip, ChipVariant } from '@ui/display/chip/components/Chip';
import { IconComponent } from '@ui/display/icon/types/IconComponent';
import { isDefined } from '@ui/utilities/isDefined';
import { Nullable } from '@ui/utilities/types/Nullable';
import { MouseEvent } from 'react';
export type EntityChipProps = {
linkToEntity?: string;
entityId: string;
export type AvatarChipProps = {
name: string;
avatarUrl?: string;
avatarType?: Nullable<AvatarType>;
variant?: EntityChipVariant;
variant?: AvatarChipVariant;
LeftIcon?: IconComponent;
className?: string;
placeholderColorSeed?: string;
onClick?: (event: MouseEvent) => void;
};
export enum EntityChipVariant {
export enum AvatarChipVariant {
Regular = 'regular',
Transparent = 'transparent',
}
export const EntityChip = ({
linkToEntity,
entityId,
export const AvatarChip = ({
name,
avatarUrl,
avatarType = 'rounded',
variant = EntityChipVariant.Regular,
variant = AvatarChipVariant.Regular,
LeftIcon,
className,
}: EntityChipProps) => {
const navigate = useNavigate();
placeholderColorSeed,
onClick,
}: AvatarChipProps) => {
const theme = useTheme();
const handleLinkClick = (event: React.MouseEvent<HTMLDivElement>) => {
if (isNonEmptyString(linkToEntity)) {
event.stopPropagation();
navigate(linkToEntity);
}
};
return (
<Chip
label={name}
variant={
linkToEntity
? variant === EntityChipVariant.Regular
isDefined(onClick)
? variant === AvatarChipVariant.Regular
? ChipVariant.Highlighted
: ChipVariant.Regular
: ChipVariant.Transparent
@ -61,15 +52,15 @@ export const EntityChip = ({
) : (
<Avatar
avatarUrl={avatarUrl}
entityId={entityId}
placeholderColorSeed={placeholderColorSeed}
placeholder={name}
size="sm"
type={avatarType}
/>
)
}
clickable={!!linkToEntity}
onClick={handleLinkClick}
clickable={isDefined(onClick)}
onClick={onClick}
className={className}
/>
);

View File

@ -1,21 +1,19 @@
import { Meta, StoryObj } from '@storybook/react';
import { AvatarChip } from '@ui/display/chip/components/AvatarChip';
import { ComponentDecorator, RouterDecorator } from '@ui/testing';
import { EntityChip } from '../EntityChip';
const meta: Meta<typeof EntityChip> = {
title: 'UI/Display/Chip/EntityChip',
component: EntityChip,
const meta: Meta<typeof AvatarChip> = {
title: 'UI/Display/Chip/AvatarChip',
component: AvatarChip,
decorators: [RouterDecorator, ComponentDecorator],
args: {
name: 'Entity name',
linkToEntity: '/entity-link',
avatarType: 'squared',
},
};
export default meta;
type Story = StoryObj<typeof EntityChip>;
type Story = StoryObj<typeof AvatarChip>;
export const Default: Story = {};

View File

@ -6,8 +6,8 @@ export * from './avatar/types/AvatarSize';
export * from './avatar/types/AvatarType';
export * from './checkmark/components/AnimatedCheckmark';
export * from './checkmark/components/Checkmark';
export * from './chip/components/AvatarChip';
export * from './chip/components/Chip';
export * from './chip/components/EntityChip';
export * from './color/components/ColorSample';
export * from './icon/components/IconAddressBook';
export * from './icon/components/IconGmail';

View File

@ -1,3 +1,4 @@
export * from './color/utils/stringToHslColor';
export * from './isDefined';
export * from './state/utils/createState';
export * from './types/Nullable';

View File

@ -0,0 +1,4 @@
import { isNull, isUndefined } from '@sniptt/guards';
export const isDefined = <T>(value: T | null | undefined): value is T =>
!isUndefined(value) && !isNull(value);