✨ Features added: - 🔍 Implement functional search in header navigation - ⚙️ Add basic user settings page - 📱 Make dashboard fully responsive 🔧 Enhancements: - 🎭 Standardize CSS with consistent theming across components - 🧹 Remove unused CSS for better performance - 📊 Improve dashboard layout and visual hierarchy - 📦 Redesign last block widget for better usability 💅 This commit introduces a cohesive design system with functional design-token components for a more ✨ polished user experience.
215 lines
5.9 KiB
TypeScript
215 lines
5.9 KiB
TypeScript
import { LitElement, css, html } from 'lit';
|
|
import { customElement, property } from 'lit/decorators.js';
|
|
|
|
import '@components/EveLink';
|
|
import formatDateTime from '@/utils/formatDateTime';
|
|
|
|
@customElement('arx-arbor-forum-topic')
|
|
export class ArborForumTopic extends LitElement {
|
|
static override styles = [
|
|
css`
|
|
.topic {
|
|
display: grid;
|
|
grid-template-columns: 3fr 1fr;
|
|
padding: 1.75rem;
|
|
border-radius: var(--radius-box);
|
|
margin-bottom: 1rem;
|
|
border: var(--border) solid var(--color-base-300);
|
|
background-color: var(--color-base-200);
|
|
box-shadow: calc(var(--depth) * 2px) calc(var(--depth) * 2px)
|
|
calc(var(--depth) * 4px)
|
|
oklch(from var(--color-base-content) l c h / 0.1),
|
|
calc(var(--depth) * -1px) calc(var(--depth) * -1px)
|
|
calc(var(--depth) * 3px)
|
|
oklch(from var(--color-base-100) l c h / 0.4);
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.topic:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: calc(var(--depth) * 4px) calc(var(--depth) * 4px)
|
|
calc(var(--depth) * 8px)
|
|
oklch(from var(--color-base-content) l c h / 0.15),
|
|
calc(var(--depth) * -2px) calc(var(--depth) * -2px)
|
|
calc(var(--depth) * 5px)
|
|
oklch(from var(--color-base-100) l c h / 0.5);
|
|
}
|
|
|
|
.topic-icon {
|
|
inline-size: 40px;
|
|
block-size: 40px;
|
|
background: var(--color-accent);
|
|
border-radius: calc(var(--radius-selector) * 1.5);
|
|
flex-shrink: 0;
|
|
position: relative;
|
|
overflow: hidden;
|
|
box-shadow: calc(var(--depth) * 1px) calc(var(--depth) * 1px)
|
|
calc(var(--depth) * 2px)
|
|
oklch(from var(--color-base-content) l c h / 0.15);
|
|
}
|
|
|
|
.topic-icon::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(
|
|
45deg,
|
|
transparent,
|
|
oklch(from var(--color-accent) l c h / 0.2)
|
|
);
|
|
}
|
|
|
|
.topic-info {
|
|
display: flex;
|
|
gap: 1.5rem;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.topic-details {
|
|
flex: 1;
|
|
}
|
|
|
|
arx-eve-link::part(link) {
|
|
display: inline-block;
|
|
margin-bottom: 0.875rem;
|
|
font-size: 1.2rem;
|
|
font-weight: 600;
|
|
letter-spacing: -0.01em;
|
|
text-decoration: none;
|
|
color: var(--color-base-content);
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
arx-eve-link:hover::part(link) {
|
|
color: var(--color-accent);
|
|
transform: translateX(4px);
|
|
}
|
|
|
|
.topic-details p {
|
|
margin: 0;
|
|
font-size: 0.975rem;
|
|
line-height: 1.6;
|
|
color: var(--color-secondary);
|
|
}
|
|
|
|
.new-status {
|
|
position: relative;
|
|
color: var(--color-accent);
|
|
}
|
|
|
|
.new-status::after {
|
|
content: "New";
|
|
position: absolute;
|
|
top: -8px;
|
|
right: -40px;
|
|
font-size: 0.75rem;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
background: var(--color-accent);
|
|
color: var(--color-accent-content);
|
|
padding: 2px 8px;
|
|
border-radius: 12px;
|
|
box-shadow: calc(var(--depth) * 1px) calc(var(--depth) * 1px)
|
|
calc(var(--depth) * 2px)
|
|
oklch(from var(--color-base-content) l c h / 0.15);
|
|
}
|
|
|
|
.hot-status {
|
|
color: var(--color-error);
|
|
}
|
|
|
|
.hot-status::before {
|
|
content: "🔥";
|
|
margin-right: 0.5rem;
|
|
}
|
|
|
|
.stats-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
padding-left: 1.5rem;
|
|
border-left: var(--border) solid var(--color-base-300);
|
|
}
|
|
|
|
.last-post-section {
|
|
background: oklch(from var(--color-base-200) l c h);
|
|
padding: 0.875rem;
|
|
border-radius: var(--radius-field);
|
|
box-shadow: calc(var(--depth) * 1px) calc(var(--depth) * 1px)
|
|
calc(var(--depth) * 2px)
|
|
oklch(from var(--color-base-content) l c h / 0.1);
|
|
}
|
|
|
|
.last-post-section > div:first-of-type {
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
color: var(--color-secondary);
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.last-post-info {
|
|
color: var(--color-secondary);
|
|
font-size: 0.875rem;
|
|
margin-top: 0.625rem;
|
|
padding-top: 0.625rem;
|
|
border-top: var(--border) solid var(--color-base-300);
|
|
}
|
|
|
|
@media (max-width: 968px) {
|
|
.topic {
|
|
grid-template-columns: 1fr;
|
|
gap: 1.5rem;
|
|
padding: 1.25rem;
|
|
}
|
|
|
|
.stats-container {
|
|
padding-left: 0;
|
|
border-left: none;
|
|
padding-top: 1rem;
|
|
border-top: var(--border) solid var(--color-base-300);
|
|
}
|
|
}
|
|
`,
|
|
];
|
|
|
|
@property({ type: String }) override id = '';
|
|
@property({ type: String }) override title = '';
|
|
@property({ type: String }) description = '';
|
|
@property({ type: String }) lastPostBy = '';
|
|
@property({ type: String }) lastPostTime = '';
|
|
@property({ type: Boolean }) isNew = false;
|
|
@property({ type: Boolean }) isHot = false;
|
|
|
|
get status() {
|
|
if (this.isNew) return 'new-status';
|
|
if (this.isHot) return 'hot-status';
|
|
return '';
|
|
}
|
|
|
|
override render() {
|
|
return html`
|
|
<div class="topic">
|
|
<div class="topic-info">
|
|
<div class="topic-icon"></div>
|
|
<div class="topic-details">
|
|
<arx-eve-link
|
|
class="${this.status}"
|
|
href="/arbor/topics/${this.id}"
|
|
>
|
|
${this.title}
|
|
</arx-eve-link>
|
|
<p>${this.description}</p>
|
|
</div>
|
|
</div>
|
|
<div class="stats-container">
|
|
<div class="last-post-section">
|
|
<arx-nostr-profile npub="${this.lastPostBy}"></arx-nostr-profile>
|
|
<div class="last-post-info">
|
|
${formatDateTime(this.lastPostTime)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|