feat: implement PostCard component design adjustments

This commit is contained in:
Hossein Mehrabi 2023-12-22 22:13:18 +03:30
parent e0ff5b837e
commit 4211a8894a
No known key found for this signature in database
GPG Key ID: 45C04964191AFAA1
7 changed files with 144 additions and 357 deletions

View File

@ -3,7 +3,6 @@ import styled from '@emotion/styled'
import Link from 'next/link'
import { LPE } from '../../types/lpe.types'
import { Authors } from '../Authors'
import { AuthorsDirection } from '../Authors/Authors'
type Props = {
data: LPE.Article.Metadata
@ -29,12 +28,7 @@ export default function ArticleReference({
</Typography>
</ArticleLink>
<Info>
<Authors
flexDirection={AuthorsDirection.ROW}
gap={4}
email={false}
authors={authors}
/>
<Authors authors={authors} />
<Typography variant="body3"></Typography>
<Typography variant="body3" genericFontFamily="sans-serif">
{localDate}

View File

@ -1,42 +1,48 @@
import { Typography } from '@acid-info/lsd-react'
import styled from '@emotion/styled'
import { AuthorsConfig } from '../../configs/data.configs'
import { LPE } from '../../types/lpe.types'
const Author = ({
author,
email,
}: {
export type AuthorProps = React.ComponentProps<typeof AuthorInfo> & {
author: LPE.Author.Document
email: boolean
gap?: number
}) => (
<AuthorInfo key={author.name}>
}
const Author: React.FC<AuthorProps> = ({ author, ...props }) => (
<AuthorInfo {...props}>
<AuthorInitials>
<span>{author.name.slice(0, 1)}</span>
</AuthorInitials>
<CustomTypography
variant="body3"
variant="subtitle4"
component="p"
genericFontFamily="sans-serif"
>
{author.name}
</CustomTypography>
{email &&
author.emailAddress &&
!AuthorsConfig.hiddenEmailAddresses.includes(author.emailAddress) && (
<Typography
href={`mailto:${author.emailAddress}`}
variant="label2"
component="a"
genericFontFamily="sans-serif"
>
{author.emailAddress}
</Typography>
)}
</AuthorInfo>
)
const AuthorInfo = styled.div`
display: flex;
flex-direction: column;
flex-direction: row;
align-items: center;
gap: 0 var(--lsd-spacing-8);
`
const AuthorInitials = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 1rem;
height: 1rem;
border-radius: 50%;
box-sizing: border-box;
border: 1px solid rgb(var(--lsd-border-primary));
span {
font-size: 0.6875rem !important;
font-weight: 400 !important;
line-height: 1rem !important;
}
`
const CustomTypography = styled(Typography)`

View File

@ -1,59 +1,45 @@
import { Typography } from '@acid-info/lsd-react'
import styled from '@emotion/styled'
import { LPE } from '../../types/lpe.types'
import { DotIcon } from '../Icons/DotIcon'
import Author from './Author'
export enum AuthorsDirection {
COLUMN = 'column',
ROW = 'row',
}
export type AuthorsProps = Partial<
React.ComponentProps<typeof AuthorsContainer>
> & {
authors: LPE.Author.Document[]
email: boolean
separator?: boolean
}
const Authors: React.FC<AuthorsProps> = ({
authors,
email,
gap = 12,
flexDirection = AuthorsDirection.ROW,
separator = true,
...props
}) => {
return authors?.length > 0 ? (
<AuthorsContainer gap={gap} flexDirection={flexDirection} {...props}>
<Typography variant="label2" style={{ marginRight: `${3 - gap}px` }}>
by
</Typography>
<AuthorsContainer {...props}>
{authors.map((author, index) => (
<AuthorContainer gap={gap} key={author.name}>
<Author author={author} email={email} />
{index < authors.length - 1 && <DotIcon color="primary" />}
<AuthorContainer key={author.name}>
<Author author={author} />
{separator && index < authors.length - 1 && (
<DotIcon color="primary" />
)}
</AuthorContainer>
))}
</AuthorsContainer>
) : null
}
const AuthorsContainer = styled.div<{
gap?: number
flexDirection?: AuthorsDirection
}>`
const AuthorsContainer = styled.div`
gap: 12px;
display: flex;
flex-direction: ${({ flexDirection }) => flexDirection};
gap: ${({ gap }) => gap}px;
flex-direction: row;
align-items: center;
`
const AuthorContainer = styled.div<{
gap: number
}>`
const AuthorContainer = styled.div`
gap: 12px;
display: flex;
align-items: center;
gap: ${({ gap }) => gap}px;
`
export default Authors

View File

@ -9,6 +9,7 @@ export type Props = React.ComponentProps<typeof Container> & {
contentType: PostType
date: Date | null
displayYear?: boolean
size?: 'small' | 'medium' | 'large'
}
export const PostCardLabel: FC<Props> = ({
@ -19,13 +20,13 @@ export const PostCardLabel: FC<Props> = ({
}) => {
return (
<Container {...props} className={`post-card__label ${props.className}`}>
<Typography variant="body3" genericFontFamily="sans-serif">
<Typography variant="subtitle2" genericFontFamily="sans-serif">
{contentType.toUpperCase()}
</Typography>
{date && (
<>
<DotIcon color="primary" />
<Date variant="body3" genericFontFamily="sans-serif">
<Date variant="subtitle2" genericFontFamily="sans-serif">
{date.toLocaleString('en-GB', {
day: 'numeric',
month: 'short',
@ -38,6 +39,12 @@ export const PostCardLabel: FC<Props> = ({
</Date>
</>
)}
{props.children && (
<>
<DotIcon color="primary" />
{props.children}
</>
)}
</Container>
)
}

View File

@ -45,14 +45,9 @@ export const PostCardShowDetails = ({
alt={podcast.logo.alt}
className="show-details__logo"
/>
<div className="show-details__info">
<Typography variant="subtitle2" className="show-details__title">
{podcast.title}
</Typography>
<Typography variant="body3" className="show-details__episodes">
{episodeNumber} EP
</Typography>
</div>
<Typography variant="label1" className="show-details__title">
{podcast.title}
</Typography>
</>
)}
</div>
@ -63,13 +58,7 @@ export const PostCardShowDetails = ({
PostCardShowDetails.styles = {
small: (theme: Theme) => css`
.show-details__title {
font-size: 12px !important;
font-weight: 400 !important;
line-height: 16px !important;
}
.show-details__episodes {
display: none !important;
${lsdUtils.typography('label2')}
}
.show-details__logo {
@ -78,9 +67,9 @@ PostCardShowDetails.styles = {
}
`,
medium: (theme: Theme) => css`
.show-details__episodes {
display: none;
large: (theme: Theme) => css`
.show-details__title {
${lsdUtils.typography('label1')}
}
.show-details__logo {
@ -88,43 +77,21 @@ PostCardShowDetails.styles = {
height: 28px;
}
`,
large: (theme: Theme) => css`
.show-details__episodes {
display: block !important;
}
.show-details__logo {
width: 38px;
height: 38px;
}
`,
}
type CustomLinkProps = {
size?: Size
xsSize?: Size
smSize?: Size
mdSize?: Size
lgSize?: Size
applySizeStyles?: boolean
}
const CustomLink = styled(Link)<CustomLinkProps>`
text-decoration: none;
.show-details {
&__container {
display: flex;
gap: 8px;
gap: 12px;
align-items: center;
}
&__info {
display: flex;
flex-direction: column;
gap: 2px;
}
&__logo {
border-radius: 100%;
}
@ -135,17 +102,14 @@ const CustomLink = styled(Link)<CustomLinkProps>`
props.applySizeStyles && PostCardShowDetails.styles.small(props.theme)}
}
&.show-details--medium {
${(props) =>
props.applySizeStyles && PostCardShowDetails.styles.medium(props.theme)}
}
&.show-details--large {
${(props) =>
props.applySizeStyles && PostCardShowDetails.styles.large(props.theme)}
}
`
&.show-details {
/**
* &.show-details {
${(props) => lsdUtils.breakpoint(props.theme, 'xs', 'down')} {
${(props) =>
props.xsSize &&
@ -174,4 +138,5 @@ const CustomLink = styled(Link)<CustomLinkProps>`
PostCardShowDetails.styles[props.lgSize](props.theme)}
}
}
`
*
*/

View File

@ -4,7 +4,7 @@ import { PropsWithChildren } from 'react'
export const PostCardSubTitle = ({ children }: PropsWithChildren) => (
<Typography
className="post-card__subtitle"
variant={'body1'}
variant={'body2'}
genericFontFamily="sans-serif"
>
{children}

View File

@ -16,7 +16,6 @@ import { LPE } from '../../types/lpe.types'
import { lsdUtils } from '../../utils/lsd.utils'
import { getPostLink } from '../../utils/route.utils'
import { Authors } from '../Authors'
import { AuthorsDirection } from '../Authors/Authors'
import { ResponsiveImageProps } from '../ResponsiveImage/ResponsiveImage'
import { PostCardLabel } from './PostCard.Label'
@ -81,12 +80,20 @@ export const PostCard = (_props: PostCardProps) => {
/>
)
const authorsElement = authors && authors.length > 0 && (
<div className="post-card__authors">
<Authors authors={authors} separator={false} />
</div>
)
const labelElement = (
<PostCardLabel
contentType={contentType}
displayYear={displayYear}
date={date}
/>
>
{contentType === 'article' && authorsElement}
</PostCardLabel>
)
const titleElement = <PostCardTitle href={link}>{title}</PostCardTitle>
@ -95,17 +102,6 @@ export const PostCard = (_props: PostCardProps) => {
<PostCardSubTitle>{subtitle}</PostCardSubTitle>
)
const authorsElement = authors && authors.length > 0 && (
<div className="post-card__authors">
<Authors
authors={authors}
email={false}
flexDirection={AuthorsDirection.ROW}
gap={8}
/>
</div>
)
const showElement = displayPodcastShow && podcastShowDetails && (
<PostCardShowDetails
{...podcastShowDetails}
@ -126,16 +122,14 @@ export const PostCard = (_props: PostCardProps) => {
applySizeStyles && applySizeStyles && `post-card--${size}`,
coverImageElement && 'post-card--with-image',
props.className,
`post-card__${contentType}`,
`post-card--${contentType}`,
)}
>
{coverImageElement}
{labelElement}
{titleElement}
{labelElement}
{subtitleElement}
{showElement}
{authorsElement}
{tagsElement}
</Container>
)
}
@ -175,125 +169,71 @@ PostCard.toData = (post: LPE.Post.Document, shows: LPE.Podcast.Show[] = []) => {
}
PostCard.styles = {
xxsmall: (theme: Theme) => css`
height: 100%;
.post-card__title-text {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
max-height: calc(2 * var(--lsd-h5-lineHeight));
${lsdUtils.typography('h5')}
}
.post-card__subtitle {
display: none;
}
.post-card__cover-image {
display: none;
}
.post-card__tags {
display: none;
}
.post-card__authors,
.post-card__show-details {
flex-grow: 1;
display: flex;
align-items: flex-end;
}
.post-card__show-details {
${PostCardShowDetails.styles.small(theme)}
}
${lsdUtils.breakpoint(theme, 'sm', 'exact')} {
.post-card__authors {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 6px 0;
> div {
> span {
display: none;
}
}
}
}
${lsdUtils.breakpoint(theme, 'md', 'down')} {
.post-card__title-text {
${lsdUtils.typography('subtitle1', true)}
max-height: calc(2 * var(--lsd-subtitle1-lineHeight));
}
}
`,
xsmall: (theme: Theme) => css`
.post-card__title-text {
${lsdUtils.typography('h5')}
}
${lsdUtils.breakpoint(theme, 'md', 'down')} {
.post-card__title-text {
${lsdUtils.typography('h5')}
}
}
`,
xxsmall: (theme: Theme) => css``,
xsmall: (theme: Theme) => css``,
small: (theme: Theme) => css`
.post-card__title {
margin-top: var(--lsd-spacing-16);
}
.post-card__title-text {
${lsdUtils.typography('h4')}
${lsdUtils.typography('h5')}
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: calc(3 * var(--lsd-h5-lineHeight));
}
.post-card__subtitle {
${lsdUtils.typography('subtitle2')}
${lsdUtils.typography('subtitle4')}
margin-top: var(--lsd-spacing-16);
}
.post-card__show-details {
${PostCardShowDetails.styles.large(theme)}
.post-card__label {
margin-top: var(--lsd-spacing-8);
* {
${lsdUtils.typography('subtitle4')}
}
}
&.post-card__search-explore {
.post-card__title h3 {
${lsdUtils.typography('h6')}
}
}
.post-card__show-details {
${PostCardShowDetails.styles.small(theme)}
}
${lsdUtils.breakpoint(theme, 'md', 'down')} {
.post-card__title-text {
${lsdUtils.typography('h5')}
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: calc(3 * var(--lsd-h5-lineHeight));
}
}
${lsdUtils.breakpoint(theme, 'xs', 'exact')} {
.post-card__show-details {
${PostCardShowDetails.styles.small(theme)}
}
margin-top: var(--lsd-spacing-16);
}
`,
medium: (theme: Theme) => css`
.post-card__title-text {
${lsdUtils.typography('h2')}
.post-card__title {
margin-top: var(--lsd-spacing-24);
}
.post-card__subtitle {
${lsdUtils.typography('subtitle2')}
.post-card__title-text {
${lsdUtils.typography('h2')}
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: calc(3 * var(--lsd-h2-lineHeight));
}
.post-card__label {
margin-top: var(--lsd-spacing-16);
* {
${lsdUtils.typography('subtitle2')}
}
}
.post-card__show-details {
${PostCardShowDetails.styles.large(theme)}
margin-top: var(--lsd-spacing-24);
}
.post-card__cover-image {
@ -313,37 +253,28 @@ PostCard.styles = {
}
}
}
${lsdUtils.breakpoint(theme, 'md', 'down')} {
.post-card__title-text {
${lsdUtils.typography('h3')}
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: calc(3 * var(--lsd-h3-lineHeight));
}
}
`,
large: (theme: Theme) => css`
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-areas:
'info image'
'info image'
'info image'
'info image'
'info image'
'info image'
'. image';
gap: 16px 105px;
gap: 0 var(--lsd-spacing-64);
.post-card__title-text {
${lsdUtils.typography('h2')}
${lsdUtils.typography('h1')}
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: calc(3 * var(--lsd-h1-lineHeight));
}
.postcard__subtitle {
${lsdUtils.typography('subtitle2')}
.post-card__subtitle {
margin-top: var(--lsd-spacing-32);
}
.post-card__cover-image {
@ -369,6 +300,9 @@ PostCard.styles = {
.post-card__label {
grid-area: info;
grid-row: auto;
* {
${lsdUtils.typography('subtitle2')}
}
}
.post-card__title {
@ -391,124 +325,10 @@ PostCard.styles = {
${PostCardShowDetails.styles.large(theme)}
}
${lsdUtils.breakpoint(theme, 'sm', 'exact')} {
gap: 16px 16px;
}
${lsdUtils.breakpoint(theme, 'md', 'exact')} {
gap: 16px 100px;
}
${lsdUtils.breakpoint(theme, 'md', 'down')} {
.post-card__title-text {
${lsdUtils.typography('h3')}
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: calc(3 * var(--lsd-h3-lineHeight));
}
}
${lsdUtils.breakpoint(theme, 'xs', 'exact')} {
.post-card__title-text {
${lsdUtils.typography('h5')}
}
}
&.post-card__search-explore {
opacity: 0.5;
}
&.post-card__search-result {
padding: 24px 0;
gap: 0 16px;
display: grid;
.post-card__title {
margin-top: 8px;
}
.post-card__title-text {
${lsdUtils.typography('h4')}
}
.post-card__subtitle {
margin-top: 8px;
grid-area: info;
grid-row: auto;
${lsdUtils.typography('subtitle2')}
}
.post-card__authors {
display: none;
}
.post-card__label {
margin-bottom: 0;
}
.show-details__title {
${lsdUtils.typography('subtitle3')}
}
.post-card__show-details {
margin-top: 12px;
${PostCardShowDetails.styles.small(theme)}
}
.post-card__tags {
margin-top: 16px;
align-self: end;
}
&.top-post {
.post-card__title-text {
${lsdUtils.typography('h4')}
}
}
&:not(.post-card--with-image) {
grid-template-areas:
'info info info info info info info info'
'info info info info info info info info'
'info info info info info info info info'
'info info info info info info info info' !important;
}
${lsdUtils.breakpoint(theme, 'md', 'down')} {
grid-template-columns: repeat(8, 1fr);
grid-template-areas:
'info info info info info image image image'
'info info info info info image image image'
'info info info info info image image image'
'info info info info info image image image'
'. . . . . image image image';
}
${lsdUtils.breakpoint(theme, 'sm', 'down')} {
&.post-card__article {
.post-card__subtitle {
display: none;
}
}
.post-card__title-text {
${lsdUtils.typography('h6')}
}
}
${lsdUtils.breakpoint(theme, 'lg', 'up')} {
grid-template-columns: repeat(11, 1fr);
grid-template-areas:
'info info info info info info info info image image image'
'info info info info info info info info image image image'
'info info info info info info info info image image image'
'info info info info info info info info image image image'
'. . . . . . . . image image image';
}
}
`,
}
@ -517,11 +337,6 @@ const Container = styled.div<Pick<PostCardProps, 'size'>>`
display: flex;
flex-direction: column;
position: 'relative';
gap: 16px 0;
.post-card__label {
margin-bottom: -8px;
}
.post-card__title {
text-decoration: none;
@ -535,6 +350,20 @@ const Container = styled.div<Pick<PostCardProps, 'size'>>`
word-break: break-word;
}
.post-card__label {
margin-top: var(--lsd-spacing-16);
}
.post-card__show-details {
margin-top: var(--lsd-spacing-16);
}
${(props) => lsdUtils.breakpoint(props.theme, 'md', 'down')} {
.post-card__label {
margin-top: var(--lsd-spacing-8);
}
}
&.post-card--xxsmall {
${({ theme }) => PostCard.styles.xxsmall(theme)}
}