Files
discourse_theme_ran/javascripts/discourse/initializers/topic-list-columns.gjs
T
chapoi b72a3c1e95 UX: Topic cards v2 (#173)
This is the second iteration on the topic card design, in which we bring
back the OP and change the layout.

**Changes**:
* Show OP avatar
* Remove activity avatar and replace by reply icon
* Remove activity icon background
* Move category tag to top left
* Replace long activity copy ("…replied at…") with dot separator
* Change date formatting to `tiny`
* Adjust bulk select styling to new layout + align checkbox to top on
mobile VS keep centred on desktop

* Why: On desktop, the avatar is taking 2 lines (usually) and aligning
the checkbox vertically looks nice. Exception for excerpts, but since
that's only available for pinned topics atm that's a low occurrence. On
mobile, the topic card is 3 lines, with a smaller avatar, which makes
the checkbox "float" around a bit when centred. Hence aligning it to the
top, which for solid avatars aligns nicely too.

* CSS refactor: grid, breakpoints

Messages/bookmarks have not been changed.

| Description | Visual |
|--------|--------|
| Large topic list | ![CleanShot 2025-06-02 at 17 37
35@2x](https://github.com/user-attachments/assets/f232058e-dbf6-4689-abe3-65970464a3e3)|
| Large bulk edit | ![CleanShot 2025-06-02 at 17 37
17@2x](https://github.com/user-attachments/assets/03d86b5f-d62b-4449-9c0b-452ceb8be60c)
|
| Medium topic list | ![CleanShot 2025-06-02 at 17 39
01@2x](https://github.com/user-attachments/assets/80739641-cf8f-4095-938f-9781cac57a7d)
|
| Medium bulk edit | ![CleanShot 2025-06-02 at 17 39
24@2x](https://github.com/user-attachments/assets/6e9045af-734a-4f3f-830a-e03a2f06fdd8)
|
| Small topic list | ![CleanShot 2025-06-02 at 17 39
44@2x](https://github.com/user-attachments/assets/eeca80bc-6863-4026-8f19-b1b5cf6848f3)
|
| Small bulk edit | ![CleanShot 2025-06-02 at 17 40
00@2x](https://github.com/user-attachments/assets/cde7be08-cde2-4ff2-b81b-328d3d7be848)
|
| Messages page (remains unchanged) | ![CleanShot 2025-06-02 at 17 20
37@2x](https://github.com/user-attachments/assets/6512bfe9-a699-4c67-b709-166540ee6fde)
|
| Bookmark page (remains unchanged) | ![CleanShot 2025-06-02 at 17 21
01@2x](https://github.com/user-attachments/assets/f8f43638-e911-49cb-a0d5-ebcb51ccfba4)
|
2025-06-04 14:50:41 +02:00

128 lines
3.6 KiB
Plaintext

import { withPluginApi } from "discourse/lib/plugin-api";
import TopicActivityColumn from "../components/card/topic-activity-column";
import TopicCategoryColumn from "../components/card/topic-category-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 TopicStatusColumn from "../components/card/topic-status-column";
const TopicActivity = <template>
<td class="topic-activity-data">
<TopicActivityColumn @topic={{@topic}} />
</td>
</template>;
const TopicStatus = <template>
<td class="topic-status-data">
<TopicStatusColumn @topic={{@topic}} />
</td>
</template>;
const TopicCategory = <template>
<td class="topic-category-data">
<TopicCategoryColumn @topic={{@topic}} />
</td>
</template>;
const TopicLikesReplies = <template>
<td class="topic-likes-replies-data">
<TopicLikesColumn @topic={{@topic}} />
<TopicRepliesColumn @topic={{@topic}} />
</td>
</template>;
const TopicCreator = <template>
<td class="topic-creator-data">
<TopicCreatorColumn @topic={{@topic}} />
</td>
</template>;
export default {
name: "topic-list-customizations",
initialize(container) {
const router = container.lookup("service:router");
withPluginApi("1.39.0", (api) => {
api.registerValueTransformer(
"topic-list-columns",
({ value: columns }) => {
columns.add("topic-status", {
item: TopicStatus,
after: "topic-author",
});
columns.add("topic-category", {
item: TopicCategory,
after: "topic-status",
});
columns.add("topic-likes-replies", {
item: TopicLikesReplies,
after: "topic-author-avatar",
});
columns.add("topic-creator", {
item: TopicCreator,
after: "topic-author-avatar",
});
columns.delete("views");
columns.delete("replies");
if (!router.currentRouteName.includes("userPrivateMessages")) {
columns.add("topic-activity", {
item: TopicActivity,
after: "title",
});
columns.delete("posters");
columns.delete("activity");
}
return columns;
}
);
api.registerValueTransformer(
"topic-list-item-class",
({ value: classes, context }) => {
if (
context.topic.is_hot ||
context.topic.pinned ||
context.topic.pinned_globally
) {
classes.push("--has-status-card");
}
return classes;
}
);
api.registerValueTransformer("topic-list-item-mobile-layout", () => {
return false;
});
api.registerBehaviorTransformer(
"topic-list-item-click",
({ context: { event }, next }) => {
if (event.target.closest("a, button, input")) {
return next();
}
event.preventDefault();
event.stopPropagation();
const topicLink = event.target
.closest("tr")
.querySelector("a.raw-topic-link");
// Redespatch the click on the topic link, so that all key-handing is sorted
topicLink.dispatchEvent(
new MouseEvent("click", {
ctrlKey: event.ctrlKey,
metaKey: event.metaKey,
shiftKey: event.shiftKey,
button: event.button,
bubbles: true,
cancelable: true,
})
);
}
);
});
},
};