Skip to content

Commit

Permalink
Condensed list card components. Apply to ItemsListing page
Browse files Browse the repository at this point in the history
  • Loading branch information
jonkafton committed Jul 10, 2024
1 parent b3ae824 commit 6f2a133
Show file tree
Hide file tree
Showing 9 changed files with 493 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import React, { useCallback, useMemo, useState } from "react"
import { LearningResourceCard, LearningResourceListCard } from "ol-components"
import {
LearningResourceCard,
LearningResourceListCard,
LearningResourceListCardCondensed,
} from "ol-components"
import * as NiceModal from "@ebay/nice-modal-react"
import type {
LearningResourceCardProps,
Expand Down Expand Up @@ -104,7 +108,9 @@ const ResourceCard: React.FC<ResourceCardProps> = ({ resource, ...others }) => {
type ResourceListCardProps = Omit<
LearningResourceListCardProps,
"href" | "onAddToLearningPathClick" | "onAddToUserListClick"
>
> & {
condensed?: boolean
}

/**
* Just like `ol-components/LearningResourceListCard`, but with builtin actions:
Expand All @@ -115,6 +121,7 @@ type ResourceListCardProps = Omit<
*/
const ResourceListCard: React.FC<ResourceListCardProps> = ({
resource,
condensed,
...others
}) => {
const {
Expand All @@ -126,9 +133,13 @@ const ResourceListCard: React.FC<ResourceListCardProps> = ({
inUserList,
inLearningPath,
} = useResourceCard(resource)

const ListCardComponent = condensed
? LearningResourceListCardCondensed
: LearningResourceListCard
return (
<>
<LearningResourceListCard
<ListCardComponent
resource={resource}
href={resource ? getDrawerHref(resource.id) : undefined}
onAddToLearningPathClick={handleAddToLearningPathClick}
Expand Down
8 changes: 3 additions & 5 deletions frontends/mit-open/src/pages/ListDetailsPage/ItemsListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
styled,
PlainList,
} from "ol-components"
import { ResourceListCard } from "@/page-components/ResourceCard/ResourceCard"
import { useListItemMove } from "api/hooks/learningResources"

const EmptyMessage = styled.p({
Expand Down Expand Up @@ -38,14 +39,11 @@ const ItemsListingViewOnly: React.FC<{
items: NonNullable<ItemsListingProps["items"]>
}> = ({ items }) => {
return (
<PlainList itemSpacing={3}>
<PlainList itemSpacing={1}>
{items.map((item) => {
return (
<li key={item.id}>
<LearningResourceCard
variant="row-reverse"
resource={item.resource}
/>
<ResourceListCard resource={item.resource} condensed />
</li>
)
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,24 +73,6 @@ const EditUserListMenu: React.FC<EditUserListMenuProps> = ({ userList }) => {
)
}

type ListCardProps = {
list: UserList
onActivate: (userList: UserList) => void
canEdit: boolean
}
const ListCard: React.FC<ListCardProps> = ({ list, onActivate }) => {
return (
<UserListCardTemplate
variant="row-reverse"
userList={list}
className="ic-resource-card"
imgConfig={imgConfigs["row-reverse-small"]}
onActivate={onActivate}
footerActionSlot={<EditUserListMenu userList={list} />}
/>
)
}

type UserListListingComponentProps = {
title?: string
onActivate: (userList: UserList) => void
Expand Down Expand Up @@ -132,10 +114,13 @@ const UserListListingComponent: React.FC<UserListListingComponentProps> = (
{listingQuery.data.results?.map((list) => {
return (
<li key={list.id}>
<ListCard
list={list}
<UserListCardTemplate
variant="row-reverse"
userList={list}
className="ic-resource-card"
imgConfig={imgConfigs["row-reverse-small"]}
onActivate={onActivate}
canEdit={true}
footerActionSlot={<EditUserListMenu userList={list} />}
/>
</li>
)
Expand Down
29 changes: 12 additions & 17 deletions frontends/ol-components/src/components/Card/ListCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Wrapper, containerStyles } from "./Card"
import { TruncateText } from "../TruncateText/TruncateText"
import { ActionButton, ActionButtonProps } from "../Button/Button"

const LinkContainer = styled(Link)`
export const LinkContainer = styled(Link)`
${containerStyles}
display: flex;
Expand All @@ -26,13 +26,13 @@ const LinkContainer = styled(Link)`
}
`

const Container = styled.div`
export const Container = styled.div`
${containerStyles}
`

const Content = () => <></>

const Body = styled.div`
export const Body = styled.div`
flex-grow: 1;
overflow: hidden;
margin: 24px;
Expand Down Expand Up @@ -63,7 +63,7 @@ const Image = styled.img`
flex-shrink: 0;
`

const Info = styled.div`
export const Info = styled.div`
${{ ...theme.typography.subtitle3 }}
margin-bottom: 16px;
${theme.breakpoints.down("md")} {
Expand All @@ -77,35 +77,30 @@ const Info = styled.div`
align-items: center;
`

const Title = styled.h3`
export const Title = styled.h3`
flex-grow: 1;
color: ${theme.custom.colors.darkGray2};
text-overflow: ellipsis;
${{ ...theme.typography.subtitle1 }}
height: ${theme.typography.pxToRem(40)};
${theme.breakpoints.down("md")} {
${{ ...theme.typography.subtitle3 }}
${{ ...theme.typography.subtitle2 }}
height: ${theme.typography.pxToRem(32)};
}
margin: 0;
`

const Footer = styled.span`
export const Footer = styled.span`
display: block;
${{
...theme.typography.body3,
color: theme.custom.colors.silverGrayDark,
}}
${{ ...theme.typography.body3 }}
span {
color: ${theme.custom.colors.black};
}
color: ${theme.custom.colors.darkGray2};
white-space: nowrap;
`

const Bottom = styled.div`
export const Bottom = styled.div`
display: flex;
justify-content: space-between;
align-items: flex-end;
Expand All @@ -118,7 +113,7 @@ const Bottom = styled.div`
/**
* Slot intended to contain ListCardAction buttons.
*/
const Actions = styled.div<{ hasImage?: boolean }>`
export const Actions = styled.div<{ hasImage?: boolean }>`
display: flex;
gap: 8px;
position: absolute;
Expand Down Expand Up @@ -152,7 +147,7 @@ type CardProps = {
className?: string
href?: string
}
type Card = FC<CardProps> & {
export type Card = FC<CardProps> & {
Content: FC<{ children: ReactNode }>
Image: FC<ImgHTMLAttributes<HTMLImageElement>>
Info: FC<{ children: ReactNode }>
Expand Down
113 changes: 113 additions & 0 deletions frontends/ol-components/src/components/Card/ListCardCondensed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React, { FC, ReactNode, Children, isValidElement } from "react"
import styled from "@emotion/styled"
import { theme } from "../ThemeProvider/ThemeProvider"
import { Wrapper } from "./Card"
import { TruncateText } from "../TruncateText/TruncateText"
import {
ListCard,
Body as BaseBody,
LinkContainer,
Container,
Info as BaseInfo,
Title as BaseTitle,
Footer,
Actions as BaseActions,
Bottom as BaseBottom,
} from "./ListCard"
import type { Card as BaseCard } from "./ListCard"

const Body = styled(BaseBody)`
margin: 16px;
${theme.breakpoints.down("md")} {
margin: 16px;
}
`

const Info = styled(BaseInfo)`
margin-bottom: 4px;
`

const Title = styled(BaseTitle)`
height: auto;
margin-bottom: 8px;
margin-right: 82px;
${theme.breakpoints.down("md")} {
height: auto;
${{ ...theme.typography.subtitle2 }}
}
`

const Bottom = styled(BaseBottom)`
height: auto;
${theme.breakpoints.down("md")} {
height: auto;
}
`
export const Actions = styled(BaseActions)`
bottom: 16px;
right: 16px;
gap: 16px;
${theme.breakpoints.down("md")} {
bottom: 16px;
right: 16px;
gap: 16px;
}
`
const Content = () => <></>

type CardProps = {
children: ReactNode[] | ReactNode
className?: string
href?: string
}

type Card = FC<CardProps> & Omit<BaseCard, "Image">

const ListCardCondensed: Card = ({ children, className, href }) => {
const _Container = href ? LinkContainer : Container

let content, info, title, footer, actions

Children.forEach(children, (child) => {
if (!isValidElement(child)) return
if (child.type === Content) content = child.props.children
else if (child.type === Info) info = child.props.children
else if (child.type === Title) title = child.props.children
else if (child.type === Footer) footer = child.props.children
else if (child.type === Actions) actions = child.props.children
})

if (content) {
return (
<_Container className={className} to={href!}>
{content}
</_Container>
)
}

return (
<Wrapper className={className}>
<_Container to={href!}>
<Body>
<Info>{info}</Info>
<Title>
<TruncateText lineClamp={4}>{title}</TruncateText>
</Title>
<Bottom>
<Footer>{footer}</Footer>
</Bottom>
</Body>
</_Container>
{actions && <Actions>{actions}</Actions>}
</Wrapper>
)
}

ListCardCondensed.Content = Content
ListCardCondensed.Info = Info
ListCardCondensed.Title = Title
ListCardCondensed.Footer = Footer
ListCardCondensed.Actions = Actions
ListCardCondensed.Action = ListCard.Action

export { ListCardCondensed }
Loading

0 comments on commit 6f2a133

Please sign in to comment.