summaryrefslogtreecommitdiff
path: root/src/components/jet/shelf/EditorialLinkShelf.svelte
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /src/components/jet/shelf/EditorialLinkShelf.svelte
init commit
Diffstat (limited to 'src/components/jet/shelf/EditorialLinkShelf.svelte')
-rw-r--r--src/components/jet/shelf/EditorialLinkShelf.svelte122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/components/jet/shelf/EditorialLinkShelf.svelte b/src/components/jet/shelf/EditorialLinkShelf.svelte
new file mode 100644
index 0000000..0946462
--- /dev/null
+++ b/src/components/jet/shelf/EditorialLinkShelf.svelte
@@ -0,0 +1,122 @@
+<script lang="ts" context="module">
+ import type { Shelf, EditorialLink } from '@jet-app/app-store/api/models';
+
+ interface EditorialLinkShelf extends Shelf {
+ contentType: 'smallStoryCard';
+ items: [EditorialLink];
+ }
+
+ export function isEditorialLinkShelf(
+ shelf: Shelf,
+ ): shelf is EditorialLinkShelf {
+ const { contentType, items } = shelf;
+ return contentType === 'editorialLink' && Array.isArray(items);
+ }
+</script>
+
+<script lang="ts">
+ import ShelfWrapper from '~/components/Shelf/Wrapper.svelte';
+ import ChevronRightIcon from '~/sf-symbols/chevron.right.svg';
+ import LinkWrapper from '~/components/LinkWrapper.svelte';
+
+ export let shelf: EditorialLinkShelf;
+ $: item = shelf.items[0];
+ $: ({ clickAction, descriptionText, summaryText } = item);
+</script>
+
+<ShelfWrapper {shelf} withBottomPadding={false}>
+ <article>
+ <LinkWrapper
+ action={clickAction}
+ includeExternalLinkArrowIcon={false}
+ label={descriptionText}
+ >
+ <svelte:fragment>
+ <div>
+ <span class="title">{descriptionText}</span>
+ <span class="subtitle">{summaryText}</span>
+ </div>
+
+ <span class="icon-container" aria-hidden="true">
+ <ChevronRightIcon />
+ </span>
+ </svelte:fragment>
+ </LinkWrapper>
+ </article>
+</ShelfWrapper>
+
+<style lang="scss">
+ @use '@amp/web-shared-styles/sasskit-stylekit/ac-sasskit-config';
+ @use 'ac-sasskit/core/helpers' as *;
+ @use 'ac-sasskit/core/locale' as *;
+
+ article {
+ display: flex;
+ align-items: center;
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 16px;
+ margin: 0 var(--bodyGutter);
+ border-radius: var(--global-border-radius-medium);
+ background-color: var(--systemQuinary);
+ transition: background-color 210ms ease-out;
+ }
+
+ article:hover {
+ cursor: pointer;
+ // a fallback for browsers that don't support relative colors (e.g. the `from` syntax)
+ background-color: var(--systemQuinary);
+ // stylelint-disable-next-line color-function-notation
+ background-color: rgb(
+ from var(--systemQuinary) r g b / calc(alpha + 0.02)
+ );
+ }
+
+ article:hover .icon-container {
+ transform: translateX(2px);
+
+ @include rtl {
+ transform: translateX(-2px) rotate(-180deg);
+ }
+ }
+
+ div {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ }
+
+ .title {
+ font: var(--body-emphasized);
+ }
+
+ .subtitle {
+ color: var(--systemSecondary);
+ }
+
+ .icon-container {
+ position: relative;
+ height: 10px;
+ aspect-ratio: 0.9;
+ transition: transform 210ms ease-out;
+
+ @include rtl {
+ transform: rotate(-180deg);
+ }
+ }
+
+ .icon-container :global(path:not([fill='none'])) {
+ fill: var(--systemPrimary);
+ }
+
+ article :global(a) {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+
+ &:hover {
+ text-decoration: none;
+ }
+ }
+</style>