/ src / components / LinkWrapper.svelte
LinkWrapper.svelte
 1  <!--
 2  @component
 3  Wraps a link around the provided slot contents if a valid `FlowAction` or `ExternalUrlAction` is given.
 4  If no valid action is provided, the contents are rendered as-is with no decoration.
 5  
 6  💡 For accessibility, this component should ideally wrap the entire visual block (e.g., `div`, `article`) so that
 7  screen readers and keyboard users interpret the entire element as a single link.
 8  
 9  @example
10  ```
11      <LinkWrapper action={item.clickAction}>
12          <article>
13              <Artwork artwork={item.artwork} />
14              {item.title}
15          </article>
16      </LinkWrapper>
17  ```
18  -->
19  <script lang="ts">
20      import { type Action, isFlowAction } from '@jet-app/app-store/api/models';
21      import { type Opt, isSome } from '@jet/environment/types/optional';
22  
23      import FlowActionComponent from '~/components/jet/action/FlowAction.svelte';
24      import { isExternalUrlAction } from '~/jet/models';
25      import ExternalUrlAction from './jet/action/ExternalUrlAction.svelte';
26      import ShelfBasedPageScrollAction, {
27          isShelfBasedPageScrollAction,
28      } from './jet/action/ShelfBasedPageScrollAction.svelte';
29  
30      export let action: Opt<Action> = null;
31      export let label: Opt<string> = null;
32      export let withoutLabel: Opt<boolean> = false;
33      export let includeExternalLinkArrowIcon: boolean = true;
34  </script>
35  
36  {#if isSome(action) && isFlowAction(action) && isSome(action.pageUrl)}
37      <FlowActionComponent
38          destination={action}
39          aria-label={withoutLabel ? null : label || action.title}
40      >
41          <slot />
42      </FlowActionComponent>
43  {:else if isSome(action) && isExternalUrlAction(action)}
44      <ExternalUrlAction
45          destination={action}
46          aria-label={withoutLabel ? null : label || action.title}
47          includeArrowIcon={includeExternalLinkArrowIcon}
48      >
49          <slot />
50      </ExternalUrlAction>
51  {:else if isSome(action) && isShelfBasedPageScrollAction(action)}
52      <ShelfBasedPageScrollAction
53          destination={action}
54          aria-label={withoutLabel ? null : label || action.title}
55      >
56          <slot />
57      </ShelfBasedPageScrollAction>
58  {:else}
59      <slot />
60  {/if}