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>