| <script lang="ts"> |
| import type { WebSearchMessage } from "$lib/types/WebSearch"; |
| import CarbonCaretRight from "~icons/carbon/caret-right"; |
| |
| import CarbonCheckmark from "~icons/carbon/checkmark-filled"; |
| import CarbonError from "~icons/carbon/error-filled"; |
| |
| import EosIconsLoading from "~icons/eos-icons/loading"; |
| |
| export let loading = false; |
| export let classNames = ""; |
| export let webSearchMessages: WebSearchMessage[] = []; |
| |
| let detailsOpen: boolean; |
| let error: boolean; |
| $: error = webSearchMessages[webSearchMessages.length - 2]?.type === "error"; |
| </script> |
| |
| <details |
| class="flex w-fit rounded-xl border border-gray-200 bg-white shadow-sm dark:border-gray-800 dark:bg-gray-900 {classNames} max-w-full" |
| bind:open={detailsOpen} |
| > |
| <summary |
| class="align-center flex cursor-pointer select-none list-none py-1 pl-2.5 pr-2 align-text-top transition-all" |
| > |
| {#if error} |
| <CarbonError class="my-auto text-red-700 dark:text-red-500" /> |
| {:else if loading} |
| <EosIconsLoading class="my-auto text-gray-500" /> |
| {:else} |
| <CarbonCheckmark class="my-auto text-gray-500" /> |
| {/if} |
| <span class="px-2 font-medium" class:text-red-700={error} class:dark:text-red-500={error} |
| >Web search |
| </span> |
| <div class="my-auto transition-all" class:rotate-90={detailsOpen}> |
| <CarbonCaretRight /> |
| </div> |
| </summary> |
| |
| <div class="content px-5 pb-5 pt-4"> |
| {#if webSearchMessages.length === 0} |
| <div class="mx-auto w-fit"> |
| <EosIconsLoading class="mb-3 h-4 w-4" /> |
| </div> |
| {:else} |
| <ol> |
| {#each webSearchMessages as message} |
| {#if message.type === "update"} |
| <li class="group border-l pb-6 last:!border-transparent last:pb-0 dark:border-gray-800"> |
| <div class="flex items-start"> |
| <div |
| class="-ml-1.5 h-3 w-3 flex-none rounded-full bg-gray-200 dark:bg-gray-600 {loading |
| ? 'group-last:animate-pulse group-last:bg-gray-300 group-last:dark:bg-gray-500' |
| : ''}" |
| /> |
| <h3 class="text-md -mt-1.5 pl-2.5 text-gray-800 dark:text-gray-100"> |
| {message.message} |
| </h3> |
| </div> |
| {#if message.args} |
| <p class="mt-1.5 pl-4 text-gray-500 dark:text-gray-400"> |
| {message.args} |
| </p> |
| {/if} |
| </li> |
| {:else if message.type === "error"} |
| <li class="group border-l pb-6 last:!border-transparent last:pb-0 dark:border-gray-800"> |
| <div class="flex items-start"> |
| <CarbonError |
| class="-ml-1.5 h-3 w-3 flex-none scale-110 text-red-700 dark:text-red-500" |
| /> |
| <h3 class="text-md -mt-1.5 pl-2.5 text-red-700 dark:text-red-500"> |
| {message.message} |
| </h3> |
| </div> |
| {#if message.args} |
| <p class="mt-1.5 pl-4 text-gray-500 dark:text-gray-400"> |
| {message.args} |
| </p> |
| {/if} |
| </li> |
| {/if} |
| {/each} |
| </ol> |
| {/if} |
| </div> |
| </details> |
| |
| <style> |
| @keyframes grow { |
| 0% { |
| font-size: 0; |
| opacity: 0; |
| } |
| 30% { |
| font-size: 1em; |
| opacity: 0; |
| } |
| 100% { |
| opacity: 1; |
| } |
| } |
| |
| details[open] .content { |
| animation-name: grow; |
| animation-duration: 300ms; |
| animation-delay: 0ms; |
| } |
| |
| details summary::-webkit-details-marker { |
| display: none; |
| } |
| </style> |
| |