Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📇 UI work on notifications #4434

Merged
12 changes: 12 additions & 0 deletions packages/atlas/src/components/Avatar/Avatar.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import styled from '@emotion/styled'
import { SvgActionAddImage, SvgActionEdit, SvgIllustrativeFileFailed } from '@/assets/icons'
import { SvgAvatarSilhouette } from '@/assets/illustrations'
import { AssetImage } from '@/components/AssetImage'
import { smallBadgeStyles } from '@/components/Badge'
import { SkeletonLoader } from '@/components/_loaders/SkeletonLoader'
import { cVar, square, zIndex } from '@/styles'

Expand Down Expand Up @@ -171,3 +172,14 @@ export const StyledSvgIllustrativeFileFailed = styled(SvgIllustrativeFileFailed)
fill: ${cVar('colorCoreNeutral100')};
}
`

export const BadgeContainer = styled.div`
position: relative;
${smallBadgeStyles}

&[data-badge]::after {
position: absolute;
right: -6px;
top: -6px;
}
`
95 changes: 50 additions & 45 deletions packages/atlas/src/components/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { validateImage } from '@/utils/image'

import {
AvatarSize,
BadgeContainer,
ChildrenWrapper,
Container,
IconAndOverlayWrapper,
Expand Down Expand Up @@ -33,6 +34,7 @@ export type AvatarProps = PropsWithChildren<{
editable?: boolean
clickable?: boolean
disableHoverDimm?: boolean
badge?: boolean | string | number
}>

export const Avatar: FC<AvatarProps> = ({
Expand All @@ -49,6 +51,7 @@ export const Avatar: FC<AvatarProps> = ({
onClick,
onImageValidation,
disableHoverDimm,
badge,
}) => {
const isEditable = !loading && editable && size !== 32 && size !== 24

Expand Down Expand Up @@ -82,51 +85,53 @@ export const Avatar: FC<AvatarProps> = ({
}, [size])

return (
<Container
as={onClick ? 'button' : 'div'}
type={onClick ? 'button' : undefined}
onClick={onClick}
size={size}
className={className}
isLoading={loading}
disableHoverDimm={disableHoverDimm}
isClickable={clickable || (clickable == null && !!onClick)} // default to true if onClick is provided
>
{(clickable || !!onClick) && (
<IconAndOverlayWrapper>
<Overlay isEdit={isEditable && !!assetUrls} />
{isEditable &&
(assetUrls ? (
<StyledSvgActionEdit width={getEditableIconSize()} height={getEditableIconSize()} />
) : (
<StyledSvgActionAddImage width={getEditableIconSize()} height={getEditableIconSize()} />
))}
</IconAndOverlayWrapper>
)}
{!children &&
(newChannel && !isEditable ? (
<NewChannelAvatar>
<SvgActionNewChannel />
</NewChannelAvatar>
) : hasAvatarUploadFailed ? (
<NewChannelAvatar>
<StyledSvgIllustrativeFileFailed />
{size === 136 && (
<Text variant="t100" as="span" margin={{ top: 2 }}>
Failed upload
</Text>
)}
</NewChannelAvatar>
) : (
<StyledImage
resolvedUrls={assetUrls}
onError={onError}
isLoading={loading}
imagePlaceholder={<SilhouetteAvatar />}
/>
))}
{children && (loading ? <StyledSkeletonLoader rounded /> : <ChildrenWrapper>{children}</ChildrenWrapper>)}
</Container>
<BadgeContainer data-badge={badge}>
<Container
as={onClick ? 'button' : 'div'}
type={onClick ? 'button' : undefined}
onClick={onClick}
size={size}
className={className}
isLoading={loading}
disableHoverDimm={disableHoverDimm}
isClickable={clickable || (clickable == null && !!onClick)} // default to true if onClick is provided
>
{(clickable || !!onClick) && (
<IconAndOverlayWrapper>
<Overlay isEdit={isEditable && !!assetUrls} />
{isEditable &&
(assetUrls ? (
<StyledSvgActionEdit width={getEditableIconSize()} height={getEditableIconSize()} />
) : (
<StyledSvgActionAddImage width={getEditableIconSize()} height={getEditableIconSize()} />
))}
</IconAndOverlayWrapper>
)}
{!children &&
(newChannel && !isEditable ? (
<NewChannelAvatar>
<SvgActionNewChannel />
</NewChannelAvatar>
) : hasAvatarUploadFailed ? (
<NewChannelAvatar>
<StyledSvgIllustrativeFileFailed />
{size === 136 && (
<Text variant="t100" as="span" margin={{ top: 2 }}>
Failed upload
</Text>
)}
</NewChannelAvatar>
) : (
<StyledImage
resolvedUrls={assetUrls}
onError={onError}
isLoading={loading}
imagePlaceholder={<SilhouetteAvatar />}
/>
))}
{children && (loading ? <StyledSkeletonLoader rounded /> : <ChildrenWrapper>{children}</ChildrenWrapper>)}
</Container>
</BadgeContainer>
)
}

Expand Down
2 changes: 1 addition & 1 deletion packages/atlas/src/components/ListItem/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export const ListItem = forwardRef<HTMLDivElement, ListItemProps>(
{label}
</LabelText>
</LabelContainer>
<Caption as="span" captionPosition={captionPosition} color="colorText" variant="t100">
<Caption as="span" captionPosition={captionPosition} color="colorTextMuted" variant="t100">
{caption}
</Caption>
</LabelCaptionContainer>
Expand Down
3 changes: 2 additions & 1 deletion packages/atlas/src/components/PageTabs/PageTabs.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ export const PageTabsWrapper = styled.div`
export const BackActionWrapper = styled.div`
display: flex;
align-items: center;
padding: ${sizes(2)} ${sizes(4)} ${sizes(2)} 0;
padding-right: ${sizes(4)};
position: relative;
border-right: 1px solid ${cVar('colorCoreNeutral600')};
margin-right: ${sizes(4)};
`
export const TailingContentWrapper = styled.div`
margin: ${sizes(2)} ${sizes(4)} ${sizes(2)} auto;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { BreakpointKey, Grid, media, sizes } from '@/styles'

export type GridWrapperProps = {
grid?: Grid
gap?: number
}

const createGridBreakpoints = ({ grid = { xxs: { columns: 'auto', minItemWidth: 300 } } }: GridWrapperProps) => {
const createGridBreakpoints = ({ grid = { xxs: { columns: 'auto', minItemWidth: 300 } }, gap }: GridWrapperProps) => {
const gridKeys = Object.keys(grid) as Array<BreakpointKey>

const styles = gridKeys.map((key) => {
Expand All @@ -20,6 +21,13 @@ const createGridBreakpoints = ({ grid = { xxs: { columns: 'auto', minItemWidth:
}
`
})

if (gap) {
styles.push(css`
gap: ${sizes(gap)}!important;
`)
}

return styles
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ export type SectionContentProps = {

export const SectionContent: FC<SectionContentProps> = (props) => {
if (props.type === 'grid') {
return (
<GridWrapper grid={props.grid} className={props.className}>
{props.children}
</GridWrapper>
)
return <GridWrapper {...props}>{props.children}</GridWrapper>
}

return <Carousel {...props}>{props.children}</Carousel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ export const TopbarStudio: FC<StudioTopbarProps> = ({ hideChannelInfo, isMembers
setIsWorkspaceOpen(false)
}

// todo: add logic after orion is done
const unseedMemberNotifications = 1
WRadoslaw marked this conversation as resolved.
Show resolved Hide resolved

return (
<>
<StyledTopbarBase
Expand All @@ -75,8 +78,13 @@ export const TopbarStudio: FC<StudioTopbarProps> = ({ hideChannelInfo, isMembers
{mdMatch && 'Upload video'}
</Button>
</CSSTransition>
<NotificationsWidget trigger={<NotificationsButton />} />
<StyledAvatar size={40} assetUrls={memberAvatarUrls} onClick={handleDrawerToggle} />
<NotificationsWidget type="channel" trigger={<NotificationsButton />} />
<StyledAvatar
size={40}
assetUrls={memberAvatarUrls}
onClick={handleDrawerToggle}
badge={unseedMemberNotifications}
/>
</StudioTopbarContainer>
) : (
<Button size="medium" onClick={() => setAuthModalOpenName(getCorrectLoginModal())}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ export const TopbarViewer: FC = () => {
}

const topbarButtonLoading = isAuthenticating || membershipsLoading

// todo: add logic after orion is done
const unseedChannelNotifications = 2
WRadoslaw marked this conversation as resolved.
Show resolved Hide resolved
return (
<>
<StyledTopbarBase
Expand Down Expand Up @@ -132,13 +133,14 @@ export const TopbarViewer: FC = () => {
{!topbarButtonLoading ? (
isLoggedIn ? (
<SignedButtonsWrapper>
<NotificationsWidget trigger={<NotificationsButton />} />
<NotificationsWidget type="member" trigger={<NotificationsButton />} />
{!mdMatch && !searchOpen && (
<StyledAvatar
size={40}
assetUrls={memberAvatarUrls}
loading={memberAvatarLoading}
onClick={handleDrawerToggle}
badge={unseedChannelNotifications}
WRadoslaw marked this conversation as resolved.
Show resolved Hide resolved
/>
)}
{mdMatch && (
Expand All @@ -147,6 +149,7 @@ export const TopbarViewer: FC = () => {
assetUrls={memberAvatarUrls}
onClick={handleDrawerToggle}
loading={memberAvatarLoading}
badge={unseedChannelNotifications}
WRadoslaw marked this conversation as resolved.
Show resolved Hide resolved
/>
)}
</SignedButtonsWrapper>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Meta, StoryFn } from '@storybook/react'
import { useState } from 'react'
import { BrowserRouter } from 'react-router-dom'

import { NotificationRecord } from '@/providers/notifications/notifications.types'
Expand Down Expand Up @@ -39,7 +38,6 @@ export default {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const Template: StoryFn<any> = (args) => {
const [selected, setSelected] = useState(false)
const notification: NotificationRecord = {
id: 'id',
date: new Date(Date.now() - 10000000),
Expand All @@ -62,14 +60,7 @@ const Template: StoryFn<any> = (args) => {
title: args.videoTitle,
},
}
return (
<NotificationTile
{...args}
notification={notification}
selected={selected}
onSelect={() => setSelected(!selected)}
/>
)
return <NotificationTile {...args} notification={notification} />
}

export const Default = Template.bind({})
Loading