Redesign community section with social media feed UX; v1.2.6
- Twitter/X-style post cards: avatar thread line, author + relative timestamp - Heart like button with optimistic toggle and like count per post - Comment button with reply count; inline threaded replies always visible - Compose card with user avatar, borderless textarea, pill Post button - Horizontal scrollable lesson filter chips (All + per-lesson) - New POST /api/study-community/posts/:postId/like endpoint (toggle) - GET community posts now returns likedByMe + likeCount per post - sanitizeStudyCommunityPosts preserves likedBy array on disk - Relative timestamps (just now, Xm ago, Xh ago, Xd ago, then date) - UserAvatar helper renders img or initials fallback consistently Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
874dd0c89b
commit
49e3a80c2c
5 files changed
+261
-135
No files matched your search
+70
@@ -12550,3 +12550,73 @@
|
||||
.admin-save-ok { color: #6ebd7c; font-size: 0.85rem; margin: 0; }
|
||||
.admin-save-error { color: #e05c5c; font-size: 0.85rem; margin: 0; }
|
||||
.admin-field-hint { font-size: 0.78rem; color: var(--admin-muted, #a0957e); margin: 0; }
|
||||
|
||||
/* ── Community feed ──────────────────────────────────────────────────────── */
|
||||
.community-feed { display: flex; flex-direction: column; gap: 0; }
|
||||
|
||||
.community-filter-bar { display: flex; gap: 0.4rem; flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; margin-bottom: 1.25rem; scrollbar-width: none; }
|
||||
.community-filter-bar::-webkit-scrollbar { display: none; }
|
||||
.community-filter-chip { flex-shrink: 0; padding: 0.3rem 0.85rem; border-radius: 999px; border: 1px solid var(--brand-border, #2a2518); background: transparent; color: var(--brand-muted, #b0a48c); font-size: 0.82rem; font-weight: 500; cursor: pointer; white-space: nowrap; transition: background 0.15s, color 0.15s, border-color 0.15s; }
|
||||
.community-filter-chip:hover { background: rgba(201,168,76,0.08); color: var(--brand-gold, #c9a84c); border-color: var(--brand-gold, #c9a84c); }
|
||||
.community-filter-chip--active { background: rgba(201,168,76,0.12); color: var(--brand-gold, #c9a84c); border-color: var(--brand-gold, #c9a84c); font-weight: 600; }
|
||||
|
||||
/* Avatar */
|
||||
.community-avatar { border-radius: 50%; object-fit: cover; flex-shrink: 0; display: block; }
|
||||
.community-avatar--initials { background: #2a2518; display: grid; place-items: center; color: var(--brand-warm-white, #f0ead8); font-weight: 700; font-family: var(--brand-font-body, sans-serif); line-height: 1; }
|
||||
|
||||
/* Compose card */
|
||||
.community-compose-card { display: flex; gap: 0.85rem; padding: 1.1rem 1.25rem; background: var(--brand-card-bg, #11100d); border: 1px solid var(--brand-border, #2a2518); border-radius: 14px; margin-bottom: 1.25rem; }
|
||||
.community-compose-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.6rem; }
|
||||
.community-compose-tag { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: var(--brand-muted, #b0a48c); }
|
||||
.community-compose-tag strong { color: var(--brand-gold, #c9a84c); }
|
||||
.community-compose-tag-clear { background: none; border: none; color: var(--brand-muted, #b0a48c); cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 0.1rem; }
|
||||
.community-compose-textarea { width: 100%; padding: 0.7rem 0; background: transparent; border: none; border-bottom: 1px solid var(--brand-border, #2a2518); color: var(--brand-warm-white, #f0ead8); font-family: var(--brand-font-body, sans-serif); font-size: 0.975rem; resize: none; overflow: hidden; outline: none; box-sizing: border-box; transition: border-color 0.15s; }
|
||||
.community-compose-textarea:focus { border-bottom-color: var(--brand-gold, #c9a84c); }
|
||||
.community-compose-textarea::placeholder { color: var(--brand-muted, #b0a48c); }
|
||||
.community-compose-footer { display: flex; justify-content: flex-end; }
|
||||
.community-post-btn { font-size: 0.875rem; padding: 0.4rem 1.1rem; border-radius: 999px; }
|
||||
|
||||
/* Status */
|
||||
.community-status-msg { color: var(--brand-muted, #b0a48c); font-size: 0.9rem; padding: 0.75rem 0; margin: 0; }
|
||||
.community-status-msg--error { color: #e07060; }
|
||||
|
||||
/* Post list */
|
||||
.community-posts-list { display: flex; flex-direction: column; }
|
||||
|
||||
/* Post card */
|
||||
.community-post-card { display: flex; gap: 0.75rem; padding: 1rem 0; border-bottom: 1px solid var(--brand-border, #2a2518); opacity: 1; transition: opacity 300ms; }
|
||||
.community-post-card--pending { opacity: 0.55; }
|
||||
.community-post-card:last-child { border-bottom: none; }
|
||||
.community-post-left { display: flex; flex-direction: column; align-items: center; gap: 0; padding-top: 0.15rem; }
|
||||
.community-thread-line { flex: 1; width: 2px; background: var(--brand-border, #2a2518); margin-top: 0.35rem; border-radius: 1px; min-height: 1rem; }
|
||||
.community-post-body { flex: 1; min-width: 0; }
|
||||
.community-post-header { display: flex; align-items: baseline; gap: 0.55rem; flex-wrap: wrap; margin-bottom: 0.25rem; }
|
||||
.community-post-author { font-weight: 700; font-size: 0.925rem; color: var(--brand-warm-white, #f0ead8); }
|
||||
.community-post-time { font-size: 0.8rem; color: var(--brand-muted, #b0a48c); }
|
||||
.community-lesson-chip { font-size: 0.73rem; font-weight: 500; padding: 0.15rem 0.55rem; border-radius: 999px; border: 1px solid var(--brand-border, #2a2518); background: transparent; color: var(--brand-muted, #b0a48c); cursor: pointer; transition: color 0.15s, border-color 0.15s; white-space: nowrap; }
|
||||
.community-lesson-chip:hover { color: var(--brand-gold, #c9a84c); border-color: var(--brand-gold, #c9a84c); }
|
||||
.community-post-text { font-size: 0.95rem; line-height: 1.6; color: var(--brand-warm-white, #f0ead8); white-space: pre-wrap; margin: 0 0 0.6rem; }
|
||||
|
||||
/* Engagement bar */
|
||||
.community-engagement-bar { display: flex; align-items: center; gap: 0.15rem; margin-bottom: 0.25rem; }
|
||||
.community-action-btn { display: flex; align-items: center; gap: 0.3rem; background: none; border: none; color: var(--brand-muted, #b0a48c); cursor: pointer; padding: 0.3rem 0.6rem; border-radius: 999px; font-size: 0.82rem; font-weight: 500; transition: color 0.15s, background 0.15s; line-height: 1; }
|
||||
.community-action-btn:hover { color: var(--brand-gold, #c9a84c); background: rgba(201,168,76,0.08); }
|
||||
.community-action-btn--liked .community-action-icon { fill: #e05c5c; color: #e05c5c; }
|
||||
.community-action-btn--liked { color: #e05c5c; }
|
||||
.community-action-btn--liked:hover { background: rgba(224,92,92,0.08); color: #e05c5c; }
|
||||
.community-action-btn--active { color: var(--brand-gold, #c9a84c); }
|
||||
.community-action-icon { width: 17px; height: 17px; fill: currentColor; flex-shrink: 0; }
|
||||
|
||||
/* Reply compose */
|
||||
.community-reply-compose { display: flex; gap: 0.65rem; margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--brand-border, #2a2518); align-items: flex-start; }
|
||||
|
||||
/* Replies thread */
|
||||
.community-replies { display: flex; flex-direction: column; gap: 0; margin-top: 0.5rem; padding-top: 0.5rem; }
|
||||
.community-reply { display: flex; gap: 0.6rem; padding: 0.65rem 0; border-top: 1px solid color-mix(in srgb, var(--brand-border, #2a2518) 60%, transparent); }
|
||||
.community-reply:first-child { border-top: none; }
|
||||
.community-reply-body { flex: 1; min-width: 0; }
|
||||
|
||||
@media (max-width: 540px) {
|
||||
.community-compose-card { padding: 0.9rem 1rem; }
|
||||
.community-post-card { gap: 0.55rem; padding: 0.85rem 0; }
|
||||
}
|
||||
Reference in new issue
Block a user