Skip to content

Commit 46f3217

Browse files
committed
improve design of discover
1 parent 4f430fe commit 46f3217

File tree

2 files changed

+183
-50
lines changed

2 files changed

+183
-50
lines changed

src/lib/types/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ export interface DiscoverUser {
185185
displayName?: string;
186186
avatarUrl?: string;
187187
shareCount: number;
188+
recentShares?: Array<{
189+
itemUrl: string;
190+
itemTitle?: string;
191+
createdAt: string;
192+
}>;
188193
}
189194

190195
export interface InappFollow {

src/routes/discover/+page.svelte

Lines changed: 178 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88
import UserCard from '$lib/components/common/UserCard.svelte';
99
1010
let followingDids = $state<Set<string>>(new Set());
11+
let expandedUsers = $state<Set<string>>(new Set());
12+
13+
function toggleExpanded(did: string) {
14+
if (expandedUsers.has(did)) {
15+
expandedUsers.delete(did);
16+
} else {
17+
expandedUsers.add(did);
18+
}
19+
expandedUsers = new Set(expandedUsers);
20+
}
1121
1222
onMount(async () => {
1323
if (!auth.isAuthenticated) {
@@ -54,44 +64,73 @@
5464
emptyTitle="No users to discover"
5565
emptyDescription="Check back later when more users have shared articles"
5666
>
57-
<div class="users-grid">
67+
<div class="users-list">
5868
{#each socialStore.discoverUsers as user (user.did)}
59-
<div class="user-card card">
60-
<UserCard
61-
avatarUrl={user.avatarUrl}
62-
displayName={user.displayName}
63-
handle={user.handle}
64-
size="large"
65-
/>
66-
<div class="user-stats">
67-
{user.shareCount}
68-
{user.shareCount === 1 ? 'share' : 'shares'} in last 30 days
69+
{@const isExpanded = expandedUsers.has(user.did)}
70+
{@const hasShares = user.recentShares && user.recentShares.length > 0}
71+
<div class="user-row card">
72+
<div class="user-main">
73+
<div class="user-info">
74+
<UserCard
75+
avatarUrl={user.avatarUrl}
76+
displayName={user.displayName}
77+
handle={user.handle}
78+
size="large"
79+
/>
80+
<div class="user-stats">
81+
<span class="share-count">
82+
{user.shareCount}
83+
{user.shareCount === 1 ? 'share' : 'shares'}
84+
</span>
85+
<span class="time-period">in last 30 days</span>
86+
</div>
87+
</div>
88+
89+
<div class="user-actions">
90+
<button
91+
class="btn follow-btn"
92+
class:btn-primary={!isFollowing(user.did)}
93+
class:btn-secondary={isFollowing(user.did)}
94+
disabled={isFollowing(user.did) || followingDids.has(user.did)}
95+
onclick={() => handleFollow(user.did)}
96+
>
97+
{#if isFollowing(user.did)}
98+
Following
99+
{:else if followingDids.has(user.did)}
100+
Following...
101+
{:else}
102+
Follow on Skyreader
103+
{/if}
104+
</button>
105+
<a
106+
href="https://bsky.app/profile/{user.handle}"
107+
target="_blank"
108+
rel="noopener"
109+
class="btn btn-outline bluesky-link"
110+
>
111+
Bluesky Profile
112+
</a>
113+
</div>
69114
</div>
70-
<div class="follow-buttons">
71-
<button
72-
class="btn follow-btn"
73-
class:btn-primary={!isFollowing(user.did)}
74-
class:btn-secondary={isFollowing(user.did)}
75-
disabled={isFollowing(user.did) || followingDids.has(user.did)}
76-
onclick={() => handleFollow(user.did)}
77-
>
78-
{#if isFollowing(user.did)}
79-
Following on Skyreader
80-
{:else if followingDids.has(user.did)}
81-
Following...
82-
{:else}
83-
Follow on Skyreader
84-
{/if}
115+
116+
{#if hasShares}
117+
<button class="disclosure-toggle" onclick={() => toggleExpanded(user.did)}>
118+
<span class="disclosure-icon">{isExpanded ? '' : ''}</span>
119+
<span>Recent shares</span>
85120
</button>
86-
<a
87-
href="https://bsky.app/profile/{user.handle}"
88-
target="_blank"
89-
rel="noopener"
90-
class="btn btn-outline bluesky-btn"
91-
>
92-
Follow on Bluesky ↗
93-
</a>
94-
</div>
121+
122+
{#if isExpanded}
123+
<ul class="recent-shares">
124+
{#each user.recentShares! as share}
125+
<li>
126+
<a href={share.itemUrl} target="_blank" rel="noopener">
127+
{share.itemTitle || share.itemUrl}
128+
</a>
129+
</li>
130+
{/each}
131+
</ul>
132+
{/if}
133+
{/if}
95134
</div>
96135
{/each}
97136
</div>
@@ -105,46 +144,113 @@
105144
padding: 0 1rem;
106145
}
107146
108-
.users-grid {
109-
display: grid;
110-
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
111-
gap: 1rem;
147+
.users-list {
148+
display: flex;
149+
flex-direction: column;
150+
gap: 0.75rem;
151+
margin-top: 1rem;
112152
}
113153
114-
.user-card {
115-
padding: 1rem;
154+
.user-row {
116155
display: flex;
117156
flex-direction: column;
157+
padding: 1rem;
118158
gap: 0.75rem;
119159
}
120160
161+
.user-main {
162+
display: flex;
163+
justify-content: space-between;
164+
align-items: center;
165+
gap: 1rem;
166+
width: 100%;
167+
}
168+
169+
.user-info {
170+
display: flex;
171+
flex-direction: column;
172+
gap: 0.5rem;
173+
min-width: 0;
174+
flex: 1;
175+
}
176+
121177
.user-stats {
178+
display: flex;
179+
gap: 0.5rem;
122180
font-size: 0.875rem;
123181
color: var(--color-text-secondary);
182+
padding-left: 3.5rem;
183+
}
184+
185+
.share-count {
186+
font-weight: 500;
124187
}
125188
126-
.follow-buttons {
189+
.user-actions {
127190
display: flex;
128191
flex-direction: column;
129192
gap: 0.5rem;
130-
margin-top: 0.25rem;
193+
flex-shrink: 0;
131194
}
132195
133196
.follow-btn {
134-
width: 100%;
197+
min-width: 150px;
135198
}
136199
137-
.bluesky-btn {
138-
width: 100%;
200+
.bluesky-link {
139201
text-align: center;
140202
text-decoration: none;
141-
background: transparent;
203+
font-size: 0.875rem;
204+
}
205+
206+
.disclosure-toggle {
207+
display: flex;
208+
align-items: center;
209+
gap: 0.5rem;
210+
background: none;
211+
border: none;
212+
padding: 0.5rem 0;
213+
font: inherit;
214+
font-size: 0.875rem;
215+
color: var(--color-text-secondary);
216+
cursor: pointer;
217+
transition: color 0.15s;
218+
}
219+
220+
.disclosure-toggle:hover {
221+
color: var(--color-primary);
222+
}
223+
224+
.disclosure-icon {
225+
font-size: 0.625rem;
226+
width: 1rem;
227+
}
228+
229+
.recent-shares {
230+
list-style: none;
231+
margin: 0;
232+
padding: 0 0 0 1.5rem;
233+
display: flex;
234+
flex-direction: column;
235+
gap: 0.5rem;
236+
}
237+
238+
.recent-shares li {
239+
font-size: 0.875rem;
240+
}
241+
242+
.recent-shares a {
142243
color: var(--color-text);
143-
border: 1px solid var(--color-border);
244+
text-decoration: none;
245+
display: block;
246+
overflow: hidden;
247+
text-overflow: ellipsis;
248+
white-space: nowrap;
144249
}
145250
146-
.bluesky-btn:hover {
147-
background: var(--color-bg-secondary);
251+
.recent-shares a:hover {
252+
color: var(--color-primary);
253+
text-decoration: underline;
148254
}
149255
150256
.error {
@@ -154,4 +260,26 @@
154260
border-radius: 8px;
155261
margin-bottom: 1rem;
156262
}
263+
264+
@media (max-width: 600px) {
265+
.user-main {
266+
flex-direction: column;
267+
align-items: stretch;
268+
}
269+
270+
.user-stats {
271+
padding-left: 0;
272+
}
273+
274+
.user-actions {
275+
flex-direction: row;
276+
flex-wrap: wrap;
277+
}
278+
279+
.follow-btn,
280+
.bluesky-link {
281+
flex: 1;
282+
min-width: 120px;
283+
}
284+
}
157285
</style>

0 commit comments

Comments
 (0)