UX: topic cards v3 (#182)

* Bringing back the OP
* Removed reason why topic appears (again) in topic list (="activity")
* Removed likes
* New layout with indention + moved all elements left (on desktop)

| Mobile | Desktop |
|--------|--------|
| ![CleanShot 2025-06-13 at 11 00
19@2x](https://github.com/user-attachments/assets/f43a773d-c8ba-4573-b16a-940e9fc3d901)
| ![CleanShot 2025-06-13 at 11 05
10@2x](https://github.com/user-attachments/assets/6bb152df-9ed3-4866-8c0a-95ddf94cd773)
|
| ![CleanShot 2025-06-13 at 11 02
25@2x](https://github.com/user-attachments/assets/3d9fb41c-a894-4b07-8737-6bd03e513f2f)
| ![CleanShot 2025-06-13 at 11 06
59@2x](https://github.com/user-attachments/assets/c54b9efe-fd1d-40aa-b8ad-2e4eab54eb90)
|
| ![CleanShot 2025-06-13 at 11 03
28@2x](https://github.com/user-attachments/assets/cdad49e8-ae6d-4f2c-9ef5-f6fa42705764)
| ![CleanShot 2025-06-13 at 11 07
10@2x](https://github.com/user-attachments/assets/91fee5ad-71b7-400c-a2c7-80339438b8de)
|
| ![CleanShot 2025-06-13 at 11 04
09@2x](https://github.com/user-attachments/assets/85296a16-f052-4787-a260-81fa54cd6191)
| ![CleanShot 2025-06-13 at 11 07
24@2x](https://github.com/user-attachments/assets/ffcaecb0-767a-4a72-8244-a3baa56d3cc2)
|
| ![CleanShot 2025-06-13 at 11 04
26@2x](https://github.com/user-attachments/assets/48a05ef5-366f-4543-bf0e-441ecae39877)
| ![CleanShot 2025-06-13 at 11 04
48@2x](https://github.com/user-attachments/assets/50499b4d-60bf-4b41-8a42-6fba8e0a41d8)
|

---------

Co-authored-by: Jordan Vidrine <jordan@jordanvidrine.com>
This commit is contained in:
chapoi
2025-06-13 11:08:57 +02:00
committed by GitHub
parent 05416abe70
commit 2bcd04d4f4
4 changed files with 278 additions and 235 deletions
@@ -36,21 +36,12 @@ export default class TopicActivityColumn extends Component {
<template> <template>
<span class={{concatClass "topic-activity" this.topicUser.class}}> <span class={{concatClass "topic-activity" this.topicUser.class}}>
<div class="topic-activity__type">
{{#if this.topicUser.user}}
{{icon "reply"}}
{{else}}
{{icon "pencil"}}
{{/if}}
</div>
{{#if this.topicUser.username}} {{#if this.topicUser.username}}
<span <span
class="topic-activity__username" class="topic-activity__username"
>{{this.topicUser.username}}</span> >{{this.topicUser.username}}</span>
<span class="dot-separator"></span> <span class="dot-separator"></span>
{{/if}} {{/if}}
<div class="topic-activity__time"> <div class="topic-activity__time">
{{formatDate @topic.bumpedAt leaveAgo="true" format="tiny"}} {{formatDate @topic.bumpedAt leaveAgo="true" format="tiny"}}
</div> </div>
@@ -30,7 +30,7 @@ export default class TopicStatusColumn extends Component {
{{#if this.badge}} {{#if this.badge}}
<span class="topic-status-card {{this.badge.className}}">{{icon <span class="topic-status-card {{this.badge.className}}">{{icon
this.badge.icon this.badge.icon
}}{{i18n (themePrefix this.badge.text)}}</span> }}<p class="topic-status-card__name">{{i18n (themePrefix this.badge.text)}}</p></span>
{{/if}} {{/if}}
</template> </template>
} }
@@ -2,7 +2,6 @@ import { withPluginApi } from "discourse/lib/plugin-api";
import TopicActivityColumn from "../components/card/topic-activity-column"; import TopicActivityColumn from "../components/card/topic-activity-column";
import TopicCategoryColumn from "../components/card/topic-category-column"; import TopicCategoryColumn from "../components/card/topic-category-column";
import TopicCreatorColumn from "../components/card/topic-creator-column"; import TopicCreatorColumn from "../components/card/topic-creator-column";
import TopicLikesColumn from "../components/card/topic-likes-column";
import TopicRepliesColumn from "../components/card/topic-replies-column"; import TopicRepliesColumn from "../components/card/topic-replies-column";
import TopicStatusColumn from "../components/card/topic-status-column"; import TopicStatusColumn from "../components/card/topic-status-column";
@@ -24,9 +23,8 @@ const TopicCategory = <template>
</td> </td>
</template>; </template>;
const TopicLikesReplies = <template> const TopicReplies = <template>
<td class="topic-likes-replies-data"> <td class="topic-likes-replies-data">
<TopicLikesColumn @topic={{@topic}} />
<TopicRepliesColumn @topic={{@topic}} /> <TopicRepliesColumn @topic={{@topic}} />
</td> </td>
</template>; </template>;
@@ -56,7 +54,7 @@ export default {
}); });
columns.add("topic-likes-replies", { columns.add("topic-likes-replies", {
item: TopicLikesReplies, item: TopicReplies,
after: "topic-author-avatar", after: "topic-author-avatar",
}); });
columns.add("topic-creator", { columns.add("topic-creator", {
@@ -87,6 +85,9 @@ export default {
) { ) {
classes.push("--has-status-card"); classes.push("--has-status-card");
} }
if (context.topic.replyCount > 1) {
classes.push("has-replies");
}
return classes; return classes;
} }
); );
+272 -221
View File
@@ -1,5 +1,9 @@
@use "lib/viewport"; @use "lib/viewport";
:root {
--d-border-radius-small: calc(var(--d-border-radius) * 0.5);
}
.topic-list .topic-list-item-separator { .topic-list .topic-list-item-separator {
display: none; display: none;
} }
@@ -18,12 +22,12 @@
flex-direction: column; flex-direction: column;
gap: 1.25em; gap: 1.25em;
@include viewport.until(lg) { @include breakpoint(medium) {
gap: 0.5em; gap: 0.5em;
padding: 0 0.5em; padding: 0 0.5em;
} }
@include viewport.until(sm) { @include breakpoint(mobile-extra-large) {
gap: 0; gap: 0;
padding: 0; padding: 0;
} }
@@ -34,35 +38,74 @@
background: var(--d-content-background); background: var(--d-content-background);
box-shadow: 0 0 12px 1px var(--topic-card-shadow); box-shadow: 0 0 12px 1px var(--topic-card-shadow);
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 0.75em 1rem; padding: var(--space-3);
border: 1px solid var(--primary-300); border: 1px solid var(--primary-300);
display: grid; display: grid;
grid-template-columns: min-content min-content auto min-content; grid-template-columns: min-content min-content min-content auto min-content;
grid-template-areas: grid-template-areas:
"creator title title status" "creator title title title status"
"creator category activity likes-replies"; ". category activity activity .";
grid-column-gap: 0.75rem; grid-gap: var(--space-3);
grid-row-gap: 0.5rem;
border-radius: var(--d-border-radius); border-radius: var(--d-border-radius);
cursor: pointer; cursor: pointer;
.bulk-select-enabled & { &.has-replies {
grid-template-columns: min-content min-content min-content auto min-content;
grid-template-areas: grid-template-areas:
"bulk-select creator title title status" "creator title title title status"
"bulk-select creator category activity likes-replies"; ". category likes-replies activity .";
}
&:not(.has-replies) {
.topic-likes-replies-data {
display: none;
}
} }
@include viewport.until(sm) { @include viewport.until(sm) {
max-width: 100vw;
box-sizing: border-box;
grid-template-areas: grid-template-areas:
"category category category status" "creator title title title status"
"creator title title title" ". category activity activity . ";
"activity activity activity likes-replies";
row-gap: 0.75em;
border: none; border: none;
border-bottom: 1px solid var(--primary-200); border-bottom: 1px solid var(--primary-200);
box-shadow: none; box-shadow: none;
border-radius: 0; border-radius: 0;
padding: var(--space-4) var(--space-3);
&.has-replies {
grid-template-areas:
"creator title title title status"
". category likes-replies activity . ";
}
}
.bulk-select-enabled & {
grid-template-columns: min-content min-content min-content auto min-content min-content;
grid-template-areas:
"bulk-select creator title title title status"
"bulk-select category category activity activity .";
&.has-replies {
grid-template-areas:
"bulk-select creator title title title status"
"bulk-select category category activity likes-replies likes-replies";
}
@include viewport.until(sm) {
grid-template-columns: min-content min-content min-content min-content auto min-content;
grid-template-areas:
"bulk-select creator title title title status"
"bulk-select . category activity activity . ";
}
&.has-replies {
@include viewport.until(sm) {
grid-template-areas:
"bulk-select creator title title title status"
"bulk-select . category likes-replies activity . ";
}
}
} }
&:hover { &:hover {
@@ -88,32 +131,34 @@
@include viewport.from(sm) { @include viewport.from(sm) {
grid-template-areas: grid-template-areas:
"creator title title status" "creator title title title status"
"creator category activity likes-replies " ". category activity activity . "
"creator excerpt excerpt excerpt"; ". excerpt excerpt excerpt excerpt";
&.has-replies {
grid-template-areas:
"creator title title title status"
". category likes-replies activity ."
". excerpt excerpt excerpt excerpt";
}
.bulk-select-enabled & { .bulk-select-enabled & {
grid-template-areas: grid-template-areas:
"bulk-select creator title title status" "bulk-select creator title title title status"
"bulk-select creator category activity likes-replies " "bulk-select category category activity likes-replies likes-replies "
" bulk-select creator excerpt excerpt excerpt"; " bulk-select excerpt excerpt excerpt excerpt excerpt";
} }
} }
// when there is enough space, excerpt can be next to likes-replies
@include viewport.from(lg) {
grid-template-areas:
"creator title title status"
"creator category activity ."
"creator excerpt excerpt likes-replies";
}
} }
.link-top-line { .link-top-line {
grid-area: title; grid-area: title;
font-weight: 500; font-weight: 500;
display: flex; line-height: calc(var(--space-3) * 2); // avatar sizing
align-items: center;
@include viewport.until(sm) {
line-height: normal;
}
.title { .title {
padding: 0; padding: 0;
@@ -148,22 +193,41 @@
.badge-category__wrapper { .badge-category__wrapper {
border-radius: var(--d-border-radius); border-radius: var(--d-border-radius);
@include viewport.until(sm) {
border-radius: var(--d-border-radius-small);
max-width: 125px;
}
padding: 0.25em 0.5rem; padding: 0.25em 0.5rem;
background-color: light-dark( background-color: light-dark(
oklch(from var(--category-badge-color) 97% calc(c * 0.3) h), oklch(from var(--category-badge-color) 97% calc(c * 0.3) h),
oklch(from var(--category-badge-color) 45% calc(c * 0.5) h) oklch(from var(--category-badge-color) 45% calc(c * 0.5) h)
); );
@include viewport.until(md) { @include breakpoint(tablet) {
padding: 0.25em 0.5rem; padding: 0.25em 0.5rem;
font-size: var(--font-down-2); font-size: var(--font-down-2);
} }
.badge-category {
align-items: center;
}
.badge-category__name { .badge-category__name {
font-size: var(--font-down-1);
color: light-dark( color: light-dark(
oklch(from var(--category-badge-color) 20% calc(c * 1) h), oklch(from var(--category-badge-color) 20% calc(c * 1) h),
oklch(from var(--category-badge-color) 100% calc(c * 0.9) h) oklch(from var(--category-badge-color) 100% calc(c * 0.9) h)
); );
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.d-icon {
width: var(--font-down-1);
height: var(--font-down-1);
} }
} }
@@ -172,14 +236,12 @@
grid-area: creator; grid-area: creator;
.avatar { .avatar {
height: 50px; height: calc(var(--space-3) * 2);
width: 50px; width: calc(var(--space-3) * 2);
border-radius: var(--d-border-radius); border-radius: var(--d-border-radius);
@include viewport.until(sm) { @include viewport.until(sm) {
height: 30px; border-radius: var(--d-border-radius-small);
width: 30px;
border-radius: 0.25rem;
} }
} }
} }
@@ -229,6 +291,11 @@
// status // status
.topic-status-data { .topic-status-data {
display: none;
}
&.--has-status-card .topic-status-data {
display: block;
grid-area: status; grid-area: status;
} }
@@ -240,13 +307,21 @@
gap: 0.25em; gap: 0.25em;
align-items: center; align-items: center;
padding: 0.2em 0.5rem; padding: 0.2em 0.5rem;
font-size: var(--font-down-3); font-size: var(--font-down-2);
@include viewport.from(lg) {
font-size: var(--font-down-3);
}
font-weight: 600; font-weight: 600;
border-radius: var(--d-border-radius); border-radius: var(--d-border-radius);
border: 1px solid var(--status-color); border: 1px solid var(--status-color);
color: var(--status-color); color: var(--status-color);
width: min-content; width: min-content;
@include viewport.until(sm) {
border-radius: var(--d-border-radius-small);
padding: 0.35em;
}
&.--pinned { &.--pinned {
--status-color: var(--primary-500); --status-color: var(--primary-500);
} }
@@ -264,14 +339,30 @@
} }
svg { svg {
font-size: var(--font-down-1);
color: var(--status-color); color: var(--status-color);
@include viewport.from(lg) {
font-size: var(--font-down-1);
}
}
&__name {
margin: 0;
@include viewport.until(sm) {
display: none;
}
} }
} }
.link-top-line .event-date { .link-top-line .event-date {
margin-left: 0.5em; margin-left: 0.5em;
font-size: var(--font-down-3); font-size: var(--font-down-3);
white-space: nowrap;
}
.link-top-line .event-date-container {
top: -0.25rem;
line-height: normal;
} }
.topic-list-data { .topic-list-data {
@@ -323,13 +414,15 @@
grid-area: likes-replies; grid-area: likes-replies;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 0.5em; gap: var(--space-3);
justify-content: flex-end;
height: min-content; height: min-content;
align-self: center; align-self: center;
.topic-likes {
display: none;
}
} }
.topic-likes-replies-data .topic-likes,
.topic-likes-replies-data .topic-replies { .topic-likes-replies-data .topic-replies {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -362,220 +455,179 @@
display: none; display: none;
} }
} }
}
// Bookmarks // Assigned List
.topic-list-item.bookmark-list-item { &.assigned-list-item {
.link-bottom-line { .topic-status-data {
font-size: unset;
}
// regular card without excerpt class
grid-template-columns: 20px min-content min-content auto min-content min-content min-content;
grid-template-areas:
". . . . . . dropdown"
"avatar update metadata metadata metadata . category";
@include viewport.until(sm) {
grid-template-columns: min-content min-content auto min-content min-content min-content min-content;
grid-template-areas:
" . . . . . . dropdown"
"update metadata metadata metadata metadata category category";
.avatar {
display: none; display: none;
} }
grid-template-areas:
"creator title title title dropdown"
". category activity activity .";
&.has-replies {
grid-template-areas:
"creator title title title dropdown"
"category category likes-replies activity .";
}
.assign-topic-buttons {
display: contents;
.assign-actions-dropdown {
grid-area: dropdown;
justify-content: flex-end;
height: 1em;
.select-kit-header {
padding-top: 0;
margin-left: auto;
align-items: center;
background: transparent;
}
.select-kit-header-wrapper {
height: 1em;
width: 1em;
}
}
}
} }
&.has-metadata { // Bookmarks
grid-template-columns: 20px min-content min-content auto min-content min-content min-content; &.bookmark-list-item {
grid-template-areas:
"creator title title title dropdown"
"category category activity . . ";
@include viewport.until(sm) { @include viewport.until(sm) {
grid-template-areas: grid-template-areas:
". . . . . . . dropdown" "title title title title dropdown"
"update update metadata metadata metadata metadata category category"; "category category activity activity . ";
.avatar { .avatar {
display: none; display: none;
} }
} }
}
// card with excerpt (all in horizon since the toggle is gone) &.excerpt-expanded {
&.excerpt-expanded {
grid-template-columns: 20px min-content auto minmax(0, 100px);
grid-template-areas:
". . . dropdown"
"avatar update metadata metadata"
"excerpt excerpt excerpt ."
"excerpt excerpt excerpt category";
@include viewport.from(xl) {
grid-template-columns: 20px min-content auto min-content;
}
@include viewport.until(sm) {
grid-template-columns: auto min-content;
grid-template-areas: grid-template-areas:
". dropdown" "creator title title title dropdown"
"category category"; "category category activity . . "
"excerpt excerpt excerpt excerpt excerpt";
.post-excerpt, @include viewport.until(sm) {
.avatar { grid-template-areas:
display: none; "title title title title dropdown"
"category category activity activity . "
"excerpt excerpt excerpt excerpt excerpt";
} }
} }
&.has-metadata { &.has-metadata {
grid-template-columns: 20px min-content auto min-content;
grid-template-areas: grid-template-areas:
". . . dropdown" "creator title title title dropdown"
"avatar update metadata metadata" "category category activity metadata . ";
"excerpt excerpt excerpt . "
"excerpt excerpt excerpt category";
@include viewport.until(sm) { @include viewport.until(sm) {
grid-template-columns: auto min-content;
grid-template-areas: grid-template-areas:
" . dropdown" "metadata metadata metadata metadata dropdown"
"metadata category"; "title title title title ."
"category category activity activity . ";
}
.bookmark-metadata { &.excerpt-expanded {
flex-wrap: wrap; grid-template-areas:
"creator title title title dropdown"
"category category activity metadata . "
"excerpt excerpt excerpt excerpt excerpt";
@include viewport.until(sm) {
grid-template-areas:
"metadata metadata metadata metadata dropdown"
"title title title title ."
"category category activity activity . "
"excerpt excerpt excerpt excerpt excerpt";
} }
} }
} }
.badge-category__wrapper { td.author-avatar {
align-self: flex-end; grid-area: creator;
height: min-content;
max-width: 100%;
} }
}
td.author-avatar { td.main-link .link-bottom-line {
grid-area: avatar; display: contents;
}
td.main-link .link-bottom-line { .badge-category__wrapper {
display: contents; grid-area: category;
display: flex;
align-items: center;
width: min-content;
justify-self: flex-end;
}
}
.badge-category__wrapper { td.main-link .link-top-line {
grid-area: category; display: contents;
.bookmark-metadata {
grid-area: metadata;
margin: 0;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--spacing-inline-s);
white-space: nowrap;
}
.bookmark-metadata-item {
margin: 0;
vertical-align: middle;
}
.bookmark-status-with-link {
grid-area: title;
}
}
.post-excerpt {
grid-area: excerpt;
margin: 0;
}
.topic-list-data:last-of-type {
display: contents;
.bookmark-actions-dropdown {
grid-area: dropdown;
align-self: flex-start;
height: 1em;
.select-kit-header {
padding-top: 0;
margin-left: auto;
align-items: center;
background: transparent;
}
.select-kit-header-wrapper {
height: 1em;
width: 1em;
}
}
}
.post-metadata.topic-list-data.updated-at {
grid-area: activity;
display: flex; display: flex;
align-items: center; align-items: center;
width: min-content; font-size: var(--font-down-1-rem);
justify-self: flex-end;
}
}
td.main-link .link-top-line {
display: contents;
.bookmark-metadata {
grid-area: metadata;
margin: 0;
display: flex;
align-items: center;
gap: var(--spacing-inline-xs);
} }
.bookmark-metadata-item { td.activity .post-activity {
margin: 0; display: none;
vertical-align: middle;
} }
.bookmark-status-with-link {
grid-column: 1/-2;
grid-row: 1/2;
}
}
.post-excerpt {
grid-area: excerpt;
margin: 0;
}
.topic-list-data:last-of-type {
display: contents;
.bookmark-actions-dropdown {
grid-area: dropdown;
align-self: flex-start;
height: 1em;
.select-kit-header {
padding-top: 0;
margin-left: auto;
align-items: center;
background: transparent;
}
.select-kit-header-wrapper {
height: 1em;
width: 1em;
}
}
}
.post-metadata.topic-list-data.updated-at {
grid-area: update;
}
td.activity .post-activity {
display: none;
}
}
// Assigned List
.topic-list-item.assigned-list-item {
.topic-status-card {
display: none;
position: relative;
top: unset;
right: unset;
}
td.main-link .link-top-line {
grid-column: 1/-3;
}
grid-template-columns: 20px min-content min-content auto min-content min-content min-content;
grid-template-areas:
". . . . . status dropdown"
"activity . . . . likes-replies category";
@include viewport.until(sm) {
grid-template-columns: 20px min-content min-content auto min-content min-content min-content 36px;
grid-template-areas:
"category category . . . . status dropdown"
". . . . . . . . "
"activity . . . . . . likes-replies";
}
.assign-topic-buttons {
display: contents;
.assign-actions-dropdown {
grid-area: dropdown;
justify-content: flex-end;
height: 1em;
.select-kit-header {
padding-top: 0;
margin-left: auto;
align-items: center;
background: transparent;
}
.select-kit-header-wrapper {
height: 1em;
width: 1em;
}
}
}
td.topic-category-status-data {
display: contents;
} }
} }
@@ -650,5 +702,4 @@ body.user-messages-page {
.event-date-container { .event-date-container {
display: inline-flex; display: inline-flex;
position: relative; position: relative;
top: -0.25em; // optical alignment
} }