diff --git a/frontends/main/src/app-pages/HomePage/NewsEventsSection.tsx b/frontends/main/src/app-pages/HomePage/NewsEventsSection.tsx
index 2b9b37abbb..a29ae1e828 100644
--- a/frontends/main/src/app-pages/HomePage/NewsEventsSection.tsx
+++ b/frontends/main/src/app-pages/HomePage/NewsEventsSection.tsx
@@ -192,7 +192,7 @@ const Story: React.FC<{ item: NewsFeedItem; mobile: boolean }> = ({
{item.image.url ? (
) : null}
-
+
{item.title}
diff --git a/frontends/ol-components/src/components/Card/Card.tsx b/frontends/ol-components/src/components/Card/Card.tsx
index c2b6876f83..e3b276a3ea 100644
--- a/frontends/ol-components/src/components/Card/Card.tsx
+++ b/frontends/ol-components/src/components/Card/Card.tsx
@@ -103,14 +103,13 @@ const Info = styled.div<{ size?: Size }>`
`
const titleOpts = {
- shouldForwardProp: (prop: string) => prop !== "lines" && prop !== "size",
+ shouldForwardProp: (prop: string) => prop !== "size",
}
-const Title = styled(Linkable, titleOpts)<{ lines?: number; size?: Size }>`
+const Title = styled(Linkable, titleOpts)<{ size?: Size }>`
text-overflow: ellipsis;
- height: ${({ lines, size }) => {
+ height: ${({ size }) => {
const lineHeightPx = size === "small" ? 18 : 20
- lines = lines ?? (size === "small" ? 2 : 3)
- return theme.typography.pxToRem(lines * lineHeightPx)
+ return theme.typography.pxToRem(3 * lineHeightPx)
}};
overflow: hidden;
margin: 0;
@@ -120,16 +119,16 @@ const Title = styled(Linkable, titleOpts)<{ lines?: number; size?: Size }>`
? { ...theme.typography.subtitle2 }
: { ...theme.typography.subtitle1 }}
- ${({ lines, size }) => {
- lines = lines ?? (size === "small" ? 2 : 3)
- return `
- @supports (-webkit-line-clamp: ${lines}) {
- white-space: initial;
- display: -webkit-box;
- -webkit-line-clamp: ${lines};
- -webkit-box-orient: vertical;
- }`
- }}
+ @supports (-webkit-line-clamp: 3) {
+ white-space: initial;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 3;
+
+ > * {
+ -webkit-line-clamp: 3;
+ }
+ }
`
const Footer = styled.span`
@@ -225,7 +224,6 @@ export type ImageProps = NextImageProps & {
type TitleProps = {
children?: ReactNode
href?: string
- lines?: number
style?: CSSProperties
}
diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/DifferingRunsTable.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/DifferingRunsTable.tsx
index ea1663f41c..9d132a9c2e 100644
--- a/frontends/ol-components/src/components/LearningResourceExpanded/DifferingRunsTable.tsx
+++ b/frontends/ol-components/src/components/LearningResourceExpanded/DifferingRunsTable.tsx
@@ -25,7 +25,7 @@ const DifferingRun = styled.div({
display: "flex",
flexWrap: "wrap",
alignItems: "center",
- gap: "16px",
+ gap: "8px",
padding: "12px",
alignSelf: "stretch",
borderBottom: `1px solid ${theme.custom.colors.lightGray2}`,
@@ -35,7 +35,7 @@ const DifferingRunHeader = styled.div({
display: "flex",
alignSelf: "stretch",
alignItems: "center",
- gap: "16px",
+ gap: "8px",
padding: "12px",
color: theme.custom.colors.darkGray2,
backgroundColor: theme.custom.colors.lightGray1,
@@ -120,7 +120,7 @@ const DifferingRunsTable: React.FC<{ resource: LearningResource }> = ({
{run.delivery.filter((d) => d.code === "in_person").length > 0 &&
run.location && (
- Location
+ Location:
{run.location}
)}
diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV2.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV2.tsx
index e51548cb45..9f580e9aaf 100644
--- a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV2.tsx
+++ b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV2.tsx
@@ -1,4 +1,4 @@
-import React from "react"
+import React, { useCallback, useRef, useState } from "react"
import styled from "@emotion/styled"
import Skeleton from "@mui/material/Skeleton"
import Typography from "@mui/material/Typography"
@@ -21,6 +21,7 @@ import type { User } from "api/hooks/user"
import { LearningResourceCardProps } from "../LearningResourceCard/LearningResourceCard"
import { CardActionButton } from "../LearningResourceCard/LearningResourceListCard"
import VideoFrame from "./VideoFrame"
+import { Link } from "../Link/Link"
const DRAWER_WIDTH = "900px"
@@ -148,12 +149,39 @@ const Platform = styled.div({
gap: "16px",
})
+const DescriptionContainer = styled.div({
+ display: "flex",
+ flexDirection: "column",
+ gap: "4px",
+ width: "100%",
+})
+
const Description = styled.p({
...theme.typography.body2,
color: theme.custom.colors.black,
margin: 0,
whiteSpace: "pre-wrap",
wordBreak: "break-word",
+ "p:first-child": {
+ marginTop: 0,
+ },
+ "p:last-child": {
+ marginBottom: 0,
+ },
+})
+
+const DescriptionCollapsed = styled(Description)({
+ display: "-webkit-box",
+ overflow: "hidden",
+ height: `calc(${theme.typography.body2.lineHeight} * 5)`,
+ "@supports (-webkit-line-clamp: 5)": {
+ WebkitLineClamp: 5,
+ WebkitBoxOrient: "vertical",
+ },
+})
+
+const DescriptionExpanded = styled(Description)({
+ display: "block",
})
const StyledPlatformLogo = styled(PlatformLogo)({
@@ -439,6 +467,24 @@ const CallToActionSection = ({
}
const ResourceDescription = ({ resource }: { resource?: LearningResource }) => {
+ const firstRender = useRef(true)
+ const clampedOnFirstRender = useRef(false)
+ const [isClamped, setClamped] = useState(false)
+ const [isExpanded, setExpanded] = useState(false)
+ const descriptionRendered = useCallback((node: HTMLDivElement) => {
+ if (node !== null) {
+ const clamped = node.scrollHeight > node.clientHeight
+ setClamped(clamped)
+ if (firstRender.current) {
+ firstRender.current = false
+ clampedOnFirstRender.current = clamped
+ return
+ }
+ }
+ }, [])
+ const DescriptionText = isExpanded
+ ? DescriptionExpanded
+ : DescriptionCollapsed
if (!resource) {
return (
<>
@@ -452,13 +498,22 @@ const ResourceDescription = ({ resource }: { resource?: LearningResource }) => {
)
}
return (
-
+
+
+ {(isClamped || clampedOnFirstRender.current) && (
+ setExpanded(!isExpanded)}>
+ {isExpanded ? "Show less" : "Show more"}
+
+ )}
+
)
}