Thread viewer for Bluesky
1<script lang="ts">
2 import {
3 Embed, RawRecordEmbed, RawRecordWithMediaEmbed, RawImageEmbed, RawLinkEmbed, RawVideoEmbed,
4 InlineRecordEmbed, InlineRecordWithMediaEmbed, InlineImageEmbed, InlineLinkEmbed, InlineVideoEmbed
5 } from '../../models/embeds.js';
6
7 import EmbedComponent from './EmbedComponent.svelte';
8 import ImagesComponent from './ImagesComponent.svelte';
9 import LinkComponent from './LinkComponent.svelte';
10 import QuoteComponent from './QuoteComponent.svelte';
11 import VideoComponent from './VideoComponent.svelte';
12
13 let { embed }: { embed: Embed } = $props();
14</script>
15
16<div class="embed">
17{#if embed instanceof RawRecordEmbed || embed instanceof InlineRecordEmbed}
18 <QuoteComponent record={embed.record} />
19
20{:else if embed instanceof RawRecordWithMediaEmbed || embed instanceof InlineRecordWithMediaEmbed}
21 <div>
22 <EmbedComponent embed={embed.media} />
23 <QuoteComponent record={embed.record} />
24 </div>
25
26{:else if embed instanceof RawImageEmbed || embed instanceof InlineImageEmbed}
27 <ImagesComponent {embed} />
28
29{:else if embed instanceof RawLinkEmbed || embed instanceof InlineLinkEmbed}
30 <LinkComponent {embed} />
31
32{:else if embed instanceof RawVideoEmbed || embed instanceof InlineVideoEmbed}
33 <VideoComponent {embed} />
34
35{:else}
36 <p>[{embed.type}]</p>
37{/if}
38</div>
39
40<style>
41 .embed :global {
42 a.link-card {
43 display: block;
44 position: relative;
45 max-width: 500px;
46 margin-bottom: 12px;
47 }
48
49 a.link-card:hover {
50 text-decoration: none;
51 }
52
53 a.link-card > div {
54 background-color: #fcfcfd;
55 border: 1px solid #d8d8d8;
56 border-radius: 8px;
57 padding: 11px 15px;
58 }
59
60 a.link-card:hover > div {
61 background-color: #f6f7f8;
62 border: 1px solid #c8c8c8;
63 }
64
65 a.link-card > div:not(:has(p.description)) {
66 padding-bottom: 14px;
67 }
68
69 a.link-card p.domain {
70 color: #888;
71 font-size: 10pt;
72 margin-top: 1px;
73 margin-bottom: 5px;
74 }
75
76 a.link-card h2 {
77 font-size: 12pt;
78 color: #333;
79 margin-top: 8px;
80 margin-bottom: 0;
81 }
82
83 a.link-card p.description {
84 color: #666;
85 font-size: 11pt;
86 margin-top: 8px;
87 margin-bottom: 4px;
88 line-height: 135%;
89 white-space: pre-line;
90 }
91
92 a.link-card.record > div:has(.avatar) {
93 padding-left: 65px;
94 }
95
96 a.link-card.record h2 {
97 margin-top: 3px;
98 }
99
100 a.link-card.record .handle {
101 color: #666;
102 margin-left: 1px;
103 font-weight: normal;
104 font-size: 11pt;
105 vertical-align: text-top;
106 }
107
108 a.link-card.record .avatar {
109 width: 36px;
110 height: 36px;
111 border: 1px solid #ddd;
112 border-radius: 6px;
113 position: absolute;
114 top: 15px;
115 left: 15px;
116 }
117
118 a.link-card.record .stats {
119 margin-top: 9px;
120 margin-bottom: 1px;
121 font-size: 10pt;
122 color: #666;
123 }
124
125 a.link-card.record .stats i.fa-heart {
126 font-size: 9pt;
127 color: #aaa;
128 }
129 }
130
131 @media (prefers-color-scheme: dark) {
132 .embed :global {
133 a.link-card > div {
134 background-color: #303030;
135 border-color: #606060;
136 }
137
138 a.link-card:hover > div {
139 background-color: #383838;
140 border-color: #707070;
141 }
142
143 a.link-card p.domain {
144 color: #666;
145 }
146
147 a.link-card h2 {
148 color: #ccc;
149 }
150
151 a.link-card p.description {
152 color: #888;
153 }
154
155 a.link-card.record .handle {
156 color: #666;
157 }
158
159 a.link-card.record .avatar {
160 border-color: #888;
161 }
162 }
163 }
164</style>