Skip to content

Commit

Permalink
refactor(ui): adjust article card layout and structure
Browse files Browse the repository at this point in the history
  • Loading branch information
NekoAria committed Nov 1, 2024
1 parent 7432c1a commit 9905b96
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 49 deletions.
43 changes: 38 additions & 5 deletions src/components/Article/ArticleCard.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@

.article-card-mini-content {
display: flex;
padding-left: 0;
gap: 10px;
flex-direction: column;
gap: 8px;
}

.article-card-mini-content-padding {
padding-left: 22px;
}

.article-card-mini-content-text {
margin-top: -2px;
flex: 1;
width: 100%;
}

.article-card-title {
color: var(--color-text-2);
font-weight: 500;
margin-top: 8px;
}

.article-card-title.arco-typography {
Expand Down Expand Up @@ -64,7 +64,7 @@

.card-custom-style .arco-card-body {
box-sizing: border-box;
padding: 10px;
padding: 8px;
width: 100%;
}

Expand All @@ -88,6 +88,9 @@
overflow: hidden;
height: 80px;
width: 80px;
order: 2;
flex-shrink: 0;
margin: 0;
}

.cover-image {
Expand Down Expand Up @@ -126,3 +129,33 @@
height: 80px;
overflow: hidden;
}

.article-card-preview {
margin-top: 0;
margin-bottom: 8px;
color: var(--color-text-3);
font-size: 13px;
line-height: 1.5;
}

.article-card-header {
margin-bottom: 8px;
}

.article-card-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 4px;
}

.article-card-body {
display: flex;
gap: 12px;
align-items: flex-start;
}

.article-card-content {
flex: 1;
min-width: 0;
}
130 changes: 86 additions & 44 deletions src/components/Article/ArticleCard.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Card, Typography } from "@arco-design/web-react";
import { IconStarFill } from "@arco-design/web-react/icon";
import { IconClockCircle, IconStarFill } from "@arco-design/web-react/icon";
import classNames from "classnames";
import { useState } from "react";
import { useInView } from "react-intersection-observer";
Expand All @@ -9,6 +9,7 @@ import useEntryActions from "../../hooks/useEntryActions";
import { contentState } from "../../store/contentState";
import { settingsState } from "../../store/settingsState";
import { generateReadingTime, generateRelativeTime } from "../../utils/date";
import sanitizeHtml from "../../utils/sanitizeHtml";
import FeedIcon from "../ui/FeedIcon";
import ImageWithLazyLoading from "./ImageWithLazyLoading";
import "./ArticleCard.css";
Expand All @@ -33,6 +34,12 @@ const ArticleCardImage = ({ entry, isThumbnail, setHasError }) => {
);
};

const extractTextFromHtml = (html) => {
const div = document.createElement("div");
div.innerHTML = html;
return div.textContent || div.innerText || "";
};

const ArticleCardContent = ({ entry, showFeedIcon, mini, children }) => {
const { showDetailedRelativeTime, showEstimatedReadingTime } =
useStore(settingsState);
Expand All @@ -53,51 +60,86 @@ const ArticleCardContent = ({ entry, showFeedIcon, mini, children }) => {
opacity: entry.status === "unread" ? 1 : 0.5,
}}
>
{entry.imgSrc && !hasError && (
<div
className={
mini
? "article-card-image-container-mini"
: "article-card-image-container"
}
style={{ margin: mini ? "0" : "0 0 10px 0" }}
>
<ArticleCardImage
entry={entry}
isThumbnail={mini}
setHasError={setHasError}
/>
</div>
)}
<div className={mini ? "article-card-mini-content-text" : ""}>
<Typography.Ellipsis
className="article-card-title"
rows={2}
expandable={false}
>
{entry.title}
</Typography.Ellipsis>
<Typography.Text
className="article-card-info"
style={{ lineHeight: "1em" }}
>
{showFeedIcon && (
<FeedIcon
feed={entry.feed}
className={mini ? "feed-icon-mini" : "feed-icon"}
/>
)}
{entry.feed.title}
<br />
{generateRelativeTime(entry.published_at, showDetailedRelativeTime)}
{showEstimatedReadingTime && (
<>
<br />
{generateReadingTime(entry.reading_time)}
</>
<div className="article-card-header">
<div className="article-card-meta">
<Typography.Text
className="article-card-info"
style={{ lineHeight: "1em" }}
>
{showFeedIcon && (
<FeedIcon
feed={entry.feed}
className={mini ? "feed-icon-mini" : "feed-icon"}
/>
)}
{entry.feed.title}
</Typography.Text>
<Typography.Text
className="article-card-info"
style={{ lineHeight: "1em" }}
>
{generateRelativeTime(
entry.published_at,
showDetailedRelativeTime,
)}
</Typography.Text>
</div>
<Typography.Ellipsis
className="article-card-info"
style={{ lineHeight: "1em" }}
rows={1}
expandable={false}
>
{entry.author}
</Typography.Ellipsis>
<Typography.Ellipsis
className="article-card-title"
rows={2}
expandable={false}
>
{entry.title}
</Typography.Ellipsis>
</div>
<div className="article-card-body">
<div className="article-card-content">
<Typography.Text
className="article-card-info"
style={{ lineHeight: "1em" }}
>
<div style={{ marginBottom: 8 }}>
{showEstimatedReadingTime && (
<>
<IconClockCircle />{" "}
{generateReadingTime(entry.reading_time)}
</>
)}
</div>
</Typography.Text>
<Typography.Ellipsis
className="article-card-preview"
rows={3}
expandable={false}
>
{extractTextFromHtml(sanitizeHtml(entry.content))}
</Typography.Ellipsis>
<Typography.Text
className="article-card-info"
style={{ lineHeight: "1em" }}
>
{entry.starred && <IconStarFill className="icon-starred" />}
</Typography.Text>
</div>
{entry.imgSrc && !hasError && (
<div className="article-card-image-container-mini">
<ArticleCardImage
entry={entry}
isThumbnail={mini}
setHasError={setHasError}
/>
</div>
)}
</Typography.Text>
{entry.starred && <IconStarFill className="icon-starred" />}
</div>
</div>
<div>{children}</div>
</div>
Expand Down

0 comments on commit 9905b96

Please sign in to comment.