master
1---
2import { Icon } from 'astro-icon/components';
3
4import { getLinkPreview } from '@utils/link-preview';
5
6interface Props {
7 url: string;
8 title?: string;
9 description?: string;
10 siteName?: string;
11 image?: string;
12 favicon?: string;
13}
14
15const props = Astro.props as Props;
16
17const preview = await getLinkPreview(props.url, {
18 title: props.title,
19 description: props.description,
20 siteName: props.siteName,
21 image: props.image,
22 favicon: props.favicon,
23});
24---
25
26<a
27 href={preview.url}
28 title={preview.title}
29 class="card card-side border-base-content/25 my-4 overflow-hidden border"
30 data-link-card
31 data-url={preview.url}
32 data-fetched-at={preview.fetchedAt}
33 rel="noopener noreferrer"
34>
35 {
36 preview.image && (
37 <figure class="flex-shrink-0">
38 <img
39 src={preview.image}
40 alt={preview.title || 'Link preview image'}
41 class="h-24 w-32 object-cover"
42 loading="lazy"
43 />
44 </figure>
45 )
46 }
47 <div class="card-body grid grid-cols-[minmax(0,1fr)_auto] items-center p-4">
48 <div class="grid grid-rows-2 gap-2">
49 <div class="flex items-center gap-2">
50 {
51 preview.favicon && (
52 <img
53 src={preview.favicon}
54 alt={preview.siteName}
55 class="h-6 w-6 rounded object-cover"
56 loading="lazy"
57 />
58 )
59 }
60 <span class="card-title truncate">
61 {preview.title}
62 </span>
63 <span class="text-base-content/60 text-sm">
64 {preview.siteName}
65 </span>
66 </div>
67 <p class="text-base-content/50 truncate">
68 {preview.description}
69 </p>
70 </div>
71 <Icon name="material-symbols:arrow-right-alt-rounded" height="1.875rem" width="1.875rem" />
72 </div>
73</a>