tangled
alpha
login
or
join now
flo-bit.dev
/
blento
21
fork
atom
your personal website on atproto - mirror
blento.app
21
fork
atom
overview
issues
pulls
pipelines
make it pop!
Florian
2 months ago
9e0832fe
2ad0f78c
+86
-77
16 changed files
expand all
collapse all
unified
split
package.json
src
app.css
app.html
lib
cards
ATProtoCollectionsCard
ATProtoCollectionsCard.svelte
BaseCard
BaseCard.svelte
BlueskyPostCard
BlueskyPostCard.svelte
LinkCard
EditingLinkCard.svelte
LinkCard.svelte
LivestreamCard
Icon.svelte
LivestreamCard.svelte
SpecialCards
UpdatedBlentos
UpdatedBlentosCard.svelte
TextCard
EditingTextCard.svelte
TextCard.svelte
components
bluesky-post
BlueskyPost.svelte
post
Post.svelte
embeds
Images.svelte
+2
-2
package.json
···
1
1
{
2
2
-
"name": "svelte-atproto-client-oauth",
2
2
+
"name": "blento",
3
3
"private": true,
4
4
-
"version": "0.0.1",
4
4
+
"version": "0.1.0",
5
5
"type": "module",
6
6
"scripts": {
7
7
"dev": "vite dev",
+2
-1
src/app.css
···
5
5
6
6
@source '../node_modules/@foxui';
7
7
8
8
-
@custom-variant dark (&:where(.dark, .dark *));
8
8
+
@custom-variant dark (&:where(.dark, .dark *):not(:where(.light, .light *)));
9
9
+
@custom-variant accent (&:where(.accent, .accent *));
9
10
10
11
.body::-webkit-scrollbar-track {
11
12
background-color: transparent;
+2
-2
src/app.html
···
1
1
<!doctype html>
2
2
-
<html lang="en">
2
2
+
<html lang="en" class="stone">
3
3
<head>
4
4
<meta charset="utf-8" />
5
5
<meta name="viewport" content="width=device-width, initial-scale=1" />
···
11
11
data-website-id="c55efa23-9abe-4a7e-b8fd-81b9fa7e8052"
12
12
></script>
13
13
</head>
14
14
-
<body data-sveltekit-preload-data="hover" class="bg-base-100/70 dark:bg-base-950">
14
14
+
<body data-sveltekit-preload-data="hover" class="bg-base-200/50 dark:bg-base-950">
15
15
<div style="display: contents">%sveltekit.body%</div>
16
16
</body>
17
17
</html>
+1
-1
src/lib/cards/ATProtoCollectionsCard/ATProtoCollectionsCard.svelte
···
37
37
<span>My AT Protocol Collections</span>
38
38
39
39
{#if collections}
40
40
-
<Badge size="md">{collections.length}</Badge>
40
40
+
<Badge size="md" class="accent:text-accent-950">{collections.length}</Badge>
41
41
{/if}
42
42
</div>
43
43
<div class="flex flex-wrap overflow-y-scroll gap-2 px-4 overflow-x-hidden w-full">
+6
-4
src/lib/cards/BaseCard/BaseCard.svelte
···
7
7
import { getColor } from '..';
8
8
9
9
const colors = {
10
10
-
base: 'border-base-300 shadow-lg dark:shadow-none inset-shadow-sm inset-shadow-base-500/10 shadow-base-900/5 bg-base-50 dark:border-base-700 dark:bg-base-900/30 border',
10
10
+
base: 'bg-base-50 dark:bg-base-900',
11
11
accent:
12
12
-
'border-accent-300 shadow-lg inset-shadow-sm inset-shadow-accent-500/10 shadow-accent-900/10 bg-accent-50 dark:border-accent-900 dark:bg-accent-900/10 border dark:inset-shadow-accent-500/20',
12
12
+
'bg-accent-400 dark:bg-accent-500 accent',
13
13
transparent: ''
14
14
} as Record<string, string>;
15
15
···
42
42
'card group focus-within:outline-accent-500 @container/card absolute z-0 rounded-3xl outline-offset-2 transition-all duration-200 focus-within:outline-2 isolate',
43
43
color ? (colors[color] ?? colors.accent) : colors.base,
44
44
color !== 'accent' && item.color !== 'base' && item.color !== 'transparent' ? color : '',
45
45
-
showOutline ? 'outline-2' : ''
45
45
+
showOutline ? 'outline-2' : '',
46
46
]}
47
47
style={`
48
48
--mx: ${item.mobileX};
···
60
60
--columns: ${COLUMNS}`}
61
61
{...rest}
62
62
>
63
63
-
<div class="relative h-full w-full overflow-hidden rounded-[23px] isolate">
63
63
+
<div class={["relative h-full w-full overflow-hidden rounded-[23px] isolate text-base-900 dark:text-base-50",
64
64
+
color !== 'base' && color != 'transparent' ? 'light' : ''
65
65
+
]}>
64
66
{@render children?.()}
65
67
</div>
66
68
{@render controls?.()}
+1
src/lib/cards/BlueskyPostCard/BlueskyPostCard.svelte
···
31
31
</script>
32
32
33
33
<div class="flex h-full flex-col justify-center-safe overflow-y-scroll p-4">
34
34
+
<div class="text-2xl accent:text-base-950 w-fit font-semibold mb-6 mx-auto p-1 px-2 bg-base-200/50 dark:bg-base-700/30 rounded-xl">My latest bluesky post</div>
34
35
{#if feed?.[0]?.post}
35
36
<BlueskyPost showLogo feedViewPost={feed?.[0].post}></BlueskyPost>
36
37
<div class="h-4 w-full"></div>
+16
-16
src/lib/cards/LinkCard/EditingLinkCard.svelte
···
13
13
<div class="flex h-full flex-col justify-between p-4">
14
14
<div>
15
15
{#if item.cardData.favicon}
16
16
-
{#if !faviconHasError}
17
17
-
<img
18
18
-
class="mb-2 size-8 rounded-lg object-cover"
19
19
-
onerror={() => (faviconHasError = true)}
20
20
-
src={item.cardData.favicon}
21
21
-
alt=""
22
22
-
/>
23
23
-
{:else}
24
24
-
<div
25
25
-
class="bg-base-100 border-base-300 dark:border-base-800 dark:bg-base-900 mb-2 inline-flex size-8 items-center justify-center rounded-lg border shadow-sm"
26
26
-
>
16
16
+
<div
17
17
+
class="bg-base-100 border-base-300 dark:border-base-800 dark:bg-base-900 mb-2 inline-flex size-8 items-center justify-center rounded-xl border shadow-sm"
18
18
+
>
19
19
+
{#if !faviconHasError}
20
20
+
<img
21
21
+
class="size-6 rounded-lg object-cover"
22
22
+
onerror={() => (faviconHasError = true)}
23
23
+
src={item.cardData.favicon}
24
24
+
alt=""
25
25
+
/>
26
26
+
{:else}
27
27
<svg
28
28
xmlns="http://www.w3.org/2000/svg"
29
29
fill="none"
···
38
38
d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"
39
39
/>
40
40
</svg>
41
41
-
</div>
42
42
-
{/if}
41
41
+
{/if}
42
42
+
</div>
43
43
{/if}
44
44
45
45
<div
46
46
-
class="hover:bg-base-200/70 dark:hover:bg-base-800/70 -m-1 rounded-md p-1 transition-colors duration-200"
46
46
+
class="hover:bg-base-200/70 dark:hover:bg-base-800/70 accent:hover:bg-accent-400 -m-1 rounded-md p-1 transition-colors duration-200"
47
47
>
48
48
<PlainTextEditor
49
49
-
class="text-base-900 dark:text-base-50 text-lg font-semibold"
49
49
+
class="text-base-900 dark:text-base-50 text-lg font-bold"
50
50
key="title"
51
51
bind:item
52
52
/>
53
53
</div>
54
54
<!-- <div class="text-base-800 dark:text-base-100 mt-2 text-xs">{item.cardData.description}</div> -->
55
55
-
<div class="text-accent-600 dark:text-accent-400 mt-2 text-xs font-light">
55
55
+
<div class="text-accent-600 accent:text-accent-950 font-semibold dark:text-accent-400 mt-2 text-xs">
56
56
{item.cardData.domain}
57
57
</div>
58
58
</div>
+17
-15
src/lib/cards/LinkCard/LinkCard.svelte
···
12
12
<div class="flex h-full flex-col justify-between p-4">
13
13
<div>
14
14
{#if item.cardData.favicon}
15
15
-
{#if !faviconHasError}
16
16
-
<img
17
17
-
class="mb-2 size-8 rounded-lg object-cover"
18
18
-
onerror={() => (faviconHasError = true)}
19
19
-
src={item.cardData.favicon}
20
20
-
alt=""
21
21
-
/>
22
22
-
{:else}
23
23
-
<div
24
24
-
class="bg-base-100 border-base-300 dark:border-base-800 dark:bg-base-900 mb-2 inline-flex size-8 items-center justify-center rounded-lg border shadow-sm"
25
25
-
>
15
15
+
<div
16
16
+
class="bg-base-100 border-base-300 dark:border-base-800 dark:bg-base-900 mb-2 inline-flex size-8 items-center justify-center rounded-xl border shadow-sm"
17
17
+
>
18
18
+
{#if !faviconHasError}
19
19
+
<img
20
20
+
class="size-6 rounded-lg object-cover"
21
21
+
onerror={() => (faviconHasError = true)}
22
22
+
src={item.cardData.favicon}
23
23
+
alt=""
24
24
+
/>
25
25
+
{:else}
26
26
<svg
27
27
xmlns="http://www.w3.org/2000/svg"
28
28
fill="none"
···
37
37
d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"
38
38
/>
39
39
</svg>
40
40
-
</div>
41
41
-
{/if}
40
40
+
{/if}
41
41
+
</div>
42
42
{/if}
43
43
<div
44
44
class={[
45
45
-
'text-base-900 dark:text-base-50 text-lg font-semibold',
45
45
+
'text-base-900 dark:text-base-50 text-lg font-bold',
46
46
(isMobile() && item.mobileH < 8) || (!isMobile() && item.h < 4) ? 'line-clamp-2' : ''
47
47
]}
48
48
>
49
49
{item.cardData.title}
50
50
</div>
51
51
<!-- <div class="text-base-800 dark:text-base-100 mt-2 text-xs">{item.cardData.description}</div> -->
52
52
-
<div class="text-accent-600 dark:text-accent-400 mt-2 text-xs font-light">
52
52
+
<div
53
53
+
class="text-accent-600 accent:text-accent-950 dark:text-accent-400 mt-2 text-xs font-semibold"
54
54
+
>
53
55
{item.cardData.domain}
54
56
</div>
55
57
</div>
+3
-3
src/lib/cards/LivestreamCard/Icon.svelte
···
10
10
>
11
11
<path
12
12
d="M11.9916 22.0341L12.0261 8.22875L21.5 5.31238L21.1203 17.5991L11.9916 22.0341Z"
13
13
-
class="fill-accent-500"
13
13
+
class="fill-accent-500 accent:fill-accent-800"
14
14
/>
15
15
<path
16
16
d="M2.46593 17.858L11.9916 22.0341L12.0261 8.22876L2 5.45044L2.46593 17.858Z"
17
17
-
class="fill-accent-300"
17
17
+
class="fill-accent-300 accent:fill-accent-700"
18
18
/>
19
19
<path
20
20
d="M21.5 5.31239L12.0261 8.22876L2 5.45044L11.6292 3L21.5 5.31239Z"
21
21
-
class="fill-accent-200"
21
21
+
class="fill-accent-200 accent:fill-accent-600"
22
22
/>
23
23
</svg>
+3
-3
src/lib/cards/LivestreamCard/LivestreamCard.svelte
···
76
76
<circle cx="50" cy="50" r="30" fill="currentColor" />
77
77
</svg>
78
78
79
79
-
live</Badge
79
79
+
<span class="accent:text-base-900">live</span></Badge
80
80
>
81
81
{:else if latestLivestream.online === false}
82
82
-
<Badge size="sm">ended</Badge>
82
82
+
<Badge size="sm" class="accent:text-base-900">ended</Badge>
83
83
{:else}
84
84
<div class="h-[22px]"></div>
85
85
{/if}
···
87
87
88
88
<a href={latestLivestream?.href} target="_blank" rel="noopener noreferrer">
89
89
<div
90
90
-
class="text-accent-700 dark:text-accent-300 hover:text-accent-600 dark:hover:text-accent-400 text-xl font-semibold transition-colors duration-150"
90
90
+
class="text-accent-700 dark:text-accent-300 accent:text-accent-950 hover:accent:text-accent-900 hover:text-accent-600 dark:hover:text-accent-400 text-xl font-semibold transition-colors duration-150"
91
91
>
92
92
{latestLivestream?.title}
93
93
</div>
+15
-19
src/lib/cards/SpecialCards/UpdatedBlentos/UpdatedBlentosCard.svelte
···
7
7
8
8
let { item }: ContentComponentProps = $props();
9
9
10
10
-
11
10
const data = getAdditionalUserData();
12
11
// svelte-ignore state_referenced_locally
13
13
-
const profiles = (data[item.cardType] as ProfileViewDetailed[]);
12
12
+
const profiles = data[item.cardType] as ProfileViewDetailed[];
14
13
</script>
15
14
16
16
-
<div class="pointer-events-none">
17
17
-
<div
18
18
-
class="from-base-50 dark:from-base-950 absolute inset-0 bg-gradient-to-t to-transparent"
19
19
-
></div>
20
20
-
<div class="absolute bottom-3 left-4 text-sm font-semibold">recently updated blentos</div>
21
21
-
</div>
22
22
-
<div class="flex h-full max-w-full items-center gap-4 overflow-x-scroll px-8 overflow-y-hidden">
23
23
-
{#each profiles as profile}
24
24
-
<a
25
25
-
href="/{profile.handle}"
26
26
-
class=" hover:bg-base-200 dark:hover:bg-base-800 mb-4 flex h-fit min-w-24 flex-col items-center justify-center gap-2 rounded-xl p-2"
27
27
-
target="_blank"
28
28
-
>
29
29
-
<div class="line-clamp-2 font-semibold">{profile.displayName || profile.handle}</div>
30
30
-
<img src={profile.avatar} class="aspect-square size-20 rounded-full" alt="" />
31
31
-
</a>
32
32
-
{/each}
15
15
+
<div class="h-full flex flex-col">
16
16
+
<div class="text-2xl font-bold px-4 py-2">Recently updated blentos</div>
17
17
+
<div class="flex grow max-w-full items-center gap-4 overflow-x-scroll overflow-y-hidden px-4">
18
18
+
{#each profiles as profile}
19
19
+
<a
20
20
+
href="/{profile.handle}"
21
21
+
class="bg-base-100 dark:bg-base-800 hover:bg-base-200 dark:hover:bg-base-700 flex h-52 w-44 min-w-44 flex-col items-center justify-center gap-2 rounded-xl transition-colors duration-150 p-2 accent:bg-accent-200/30 accent:hover:bg-accent-200/50"
22
22
+
target="_blank"
23
23
+
>
24
24
+
<img src={profile.avatar} class="aspect-square size-28 rounded-full" alt="" />
25
25
+
<div class="line-clamp-1 text-lg font-bold">{profile.displayName || profile.handle}</div>
26
26
+
</a>
27
27
+
{/each}
28
28
+
</div>
33
29
</div>
+1
-1
src/lib/cards/TextCard/EditingTextCard.svelte
···
9
9
10
10
<div
11
11
class={[
12
12
-
'prose dark:prose-invert prose-base prose-a:no-underline prose-a:text-accent-600 dark:prose-a:text-accent-400 prose-sm hover:bg-base-500/20 prose-p:first:mt-0 prose-p:last:mb-0 h-full overflow-y-scroll rounded-md p-2 inline-flex w-full',
12
12
+
'prose dark:prose-invert prose-sm prose-a:no-underline prose-a:text-accent-600 dark:prose-a:text-accent-400 accent:prose-a:text-accent-950 accent:prose-a:underline accent:prose-p:text-base-900 hover:bg-base-500/20 prose-p:first:mt-0 prose-p:last:mb-0 h-full overflow-y-scroll rounded-md p-2 inline-flex w-full',
13
13
textAlignClasses[item.cardData.textAlign as string],
14
14
verticalAlignClasses[item.cardData.verticalAlign as string]
15
15
]}
+1
-1
src/lib/cards/TextCard/TextCard.svelte
···
12
12
13
13
<div
14
14
class={[
15
15
-
'prose dark:prose-invert prose-base prose-a:no-underline prose-a:text-accent-600 dark:prose-a:text-accent-400 prose-sm prose-p:first:mt-0 prose-p:last:mb-0 inline-flex h-full w-full overflow-y-scroll rounded-md p-3',
15
15
+
'prose dark:prose-invert prose-sm prose-a:no-underline prose-a:text-accent-600 dark:prose-a:text-accent-400 accent:prose-a:text-accent-950 accent:prose-a:underline accent:prose-p:text-base-900 prose-p:first:mt-0 prose-p:last:mb-0 inline-flex h-full w-full overflow-y-scroll rounded-md p-3',
16
16
textAlignClasses?.[item.cardData.textAlign as string],
17
17
verticalAlignClasses[item.cardData.verticalAlign as string]
18
18
]}
+1
-1
src/lib/components/bluesky-post/BlueskyPost.svelte
···
16
16
17
17
{#snippet logo()}
18
18
<a
19
19
-
class="text-accent-700 dark:text-accent-400 hover:text-accent-600 dark:hover:text-accent-500"
19
19
+
class="text-accent-700 dark:text-accent-400 hover:text-accent-600 dark:hover:text-accent-500 accent:text-accent-900 accent:hover:text-accent-800"
20
20
href={postData?.href}
21
21
>
22
22
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="size-4" viewBox="0 0 600 530">
+14
-7
src/lib/components/post/Post.svelte
···
116
116
<div class="flex items-start gap-4">
117
117
{#if data.author.href}
118
118
<a
119
119
-
class="hover:bg-accent-900/5 group/post-author -mx-2 -my-0.5 flex flex-col items-baseline gap-x-2 gap-y-0.5 rounded-xl px-2 py-0.5 sm:flex-row"
119
119
+
class="hover:bg-accent-900/5 accent:hover:bg-accent-100/10 group/post-author -mx-2 -my-0.5 flex flex-col items-baseline gap-x-2 gap-y-0.5 rounded-xl px-2 py-0.5 sm:flex-row"
120
120
href={data.author.href}
121
121
>
122
122
{#if data.author.displayName}
123
123
<div
124
124
-
class="text-base-900 group-hover/post-author:text-accent-600 dark:text-base-50 dark:group-hover/post-author:text-accent-300 line-clamp-1 text-sm leading-tight font-semibold"
124
124
+
class="text-base-900 group-hover/post-author:text-accent-600 dark:text-base-50 dark:group-hover/post-author:text-accent-300 accent:group-hover/post-author:text-accent-950 line-clamp-1 text-sm leading-tight font-semibold"
125
125
>
126
126
{data.author.displayName}
127
127
</div>
128
128
{/if}
129
129
<div
130
130
class={cn(
131
131
-
'group-hover/post-author:text-accent-600 dark:group-hover/post-author:text-accent-400 text-sm',
131
131
+
'group-hover/post-author:text-accent-600 dark:group-hover/post-author:text-accent-400 accent:text-accent-950 accent:group-hover/post-author:text-accent-900 text-sm',
132
132
!data.author.displayName
133
133
? 'text-base-900 dark:text-base-50 font-semibold'
134
134
: 'text-base-600 dark:text-base-400'
···
144
144
<div class="text-base-900 dark:text-base-50 text-sm leading-tight font-semibold">
145
145
{data.author.displayName}
146
146
</div>
147
147
-
<div class="text-base-600 dark:text-base-400 text-sm">
147
147
+
<div class="text-base-600 dark:text-base-400 accent:text-accent-950 text-sm">
148
148
@{data.author.handle}
149
149
</div>
150
150
</div>
151
151
{/if}
152
152
153
153
-
<div class="text-base-600 dark:text-base-400 block text-sm no-underline">
153
153
+
<div
154
154
+
class="text-base-600 dark:text-base-400 accent:text-accent-950 block text-sm no-underline"
155
155
+
>
154
156
<RelativeTime date={new Date(data.createdAt)} locale="en" />
155
157
</div>
156
158
</div>
···
160
162
{/if}
161
163
</div>
162
164
163
163
-
<Prose size="md">
165
165
+
<Prose
166
166
+
size="md"
167
167
+
class="accent:prose-a:text-accent-950 accent:text-base-900 accent:prose-p:text-base-900 accent:prose-a:underline"
168
168
+
>
164
169
{#if data.htmlContent}
165
170
{@html data.htmlContent}
166
171
{:else}
···
173
178
{/if}
174
179
175
180
{#if showReply || showRepost || showLike || showBookmark || customActions}
176
176
-
<div class="text-base-500 dark:text-base-400 mt-4 flex justify-between gap-2">
181
181
+
<div
182
182
+
class="text-base-500 dark:text-base-400 accent:text-base-900 mt-4 flex justify-between gap-2"
183
183
+
>
177
184
{#if showReply}
178
185
<PostAction onclick={onReplyClick}>
179
186
<svg
+1
-1
src/lib/components/post/embeds/Images.svelte
···
21
21
? `aspect-ratio: ${image.aspectRatio.width} / ${image.aspectRatio.height}`
22
22
: 'aspect-ratio: 1 / 1'}
23
23
class={[
24
24
-
'border-base-500/20 dark:border-base-400/20 w-fit max-w-full rounded-2xl border max-h-[40rem] object-contain',
24
24
+
'border-base-500/20 dark:border-base-400/20 w-fit max-w-full rounded-2xl border max-h-[40rem] object-contain accent:border-accent-900',
25
25
className
26
26
]}
27
27
/>