diff options
Diffstat (limited to 'src/components/jet/web-navigation')
3 files changed, 252 insertions, 0 deletions
diff --git a/src/components/jet/web-navigation/CategoryTabItem.svelte b/src/components/jet/web-navigation/CategoryTabItem.svelte new file mode 100644 index 0000000..61f2570 --- /dev/null +++ b/src/components/jet/web-navigation/CategoryTabItem.svelte @@ -0,0 +1,67 @@ +<script lang="ts"> + import { createEventDispatcher } from 'svelte'; + import { buildSrc } from '@amp/web-app-components/src/components/Artwork/utils/srcset'; + import Item from '@amp/web-app-components/src/components/Navigation/Item.svelte'; + import ItemContent from '@amp/web-app-components/src/components/Navigation/ItemContent.svelte'; + + const dispatch = createEventDispatcher(); + + export let item: any; + export let selected: boolean = false; + export let translateFn: (key: string) => string; + $$props; // lets the other props automatically passed to navigation item components enter without being delcared explicitly + + const itemClicked = (): void => { + dispatch('selectItem', item); + }; + + $: backgroundImage = item.artwork + ? buildSrc( + item.artwork.template, + { + crop: 'bb', + width: 40, + height: 40, + fileType: 'webp', + }, + {}, + ) + : undefined; +</script> + +<Item {item} {selected} {translateFn}> + <!-- svelte-ignore a11y-click-events-have-key-events --> + <!-- svelte-ignore a11y-no-static-element-interactions --> + <a + href={item.url} + class="navigation-item__link" + role="button" + aria-pressed={selected} + on:click|preventDefault={itemClicked} + > + <ItemContent label={item.label}> + <div + slot="icon" + aria-hidden={true} + class="icon" + style:--background-image={`url(${backgroundImage})`} + /> + </ItemContent> + </a> +</Item> + +<style> + .icon { + display: flex; + align-self: center; + width: 20px; + height: 20px; + background: var(--keyColor); + mask: var(--background-image) center / contain no-repeat; + + @media (--sidebar-visible) { + width: 18px; + height: 18px; + } + } +</style> diff --git a/src/components/jet/web-navigation/PlatformSelectorDropdown.svelte b/src/components/jet/web-navigation/PlatformSelectorDropdown.svelte new file mode 100644 index 0000000..f0fe666 --- /dev/null +++ b/src/components/jet/web-navigation/PlatformSelectorDropdown.svelte @@ -0,0 +1,88 @@ +<script lang="ts"> + import type { WebNavigationLink } from '@jet-app/app-store/api/models/web-navigation'; + + import SFSymbol from '~/components/SFSymbol.svelte'; + import PlatformSelectorItem from '~/components/jet/web-navigation/PlatformSelectorItem.svelte'; + import { getI18n } from '~/stores/i18n'; + import Menu from '~/components/Menu.svelte'; + import { getJet } from '~/jet'; + + export let platformSelectors: WebNavigationLink[]; + + const i18n = getI18n(); + const jet = getJet(); + + $: activeSelector = platformSelectors.find((selector) => selector.isActive); + + const handleShowMenu = () => { + jet.recordCustomMetricsEvent({ + eventType: 'click', + actionType: 'open', + targetType: 'button', + targetId: 'PlatformSelector', + }); + }; +</script> + +{#if activeSelector} + <nav> + <Menu options={platformSelectors} forcedXPosition={25} {handleShowMenu}> + <svelte:fragment slot="trigger"> + <span + class="platform-selector-text" + id="platform-selector-text" + aria-labelledby="app-store-icon-contianer platform-selector-text" + aria-haspopup="menu" + > + {$i18n.t( + 'ASE.Web.AppStore.Navigation.PlatformSelectorText', + { + platform: activeSelector.action.title, + }, + )} + + <SFSymbol name="chevron.down" /> + </span> + </svelte:fragment> + + <svelte:fragment slot="option" let:option> + <PlatformSelectorItem platformSelector={option} /> + </svelte:fragment> + </Menu> + </nav> +{/if} + +<style> + nav { + --menu-item-padding: 0; + --menu-item-margin: 0 0 8px 0; + --menu-popover-padding: 8px; + --menu-common-padding: 8px; + --menu-trigger-padding: 0; + --menu-popover-background-color: var(--pageBg); + --menu-popover-box-shadow: 10px 10px 10px 0 + var(--systemQuaternary-onLight); + --menu-popover-border-radius: 14px; + --menu-popover-border: 1px solid var(--systemQuaternary); + --menu-popover-z-index: calc(var(--z-web-chrome) + 1); + } + + .platform-selector-text { + display: flex; + align-items: center; + gap: var(--platform-selector-trigger-gap, 4px); + font: var(--title-2); + white-space: nowrap; + } + + .platform-selector-text :global(svg) { + height: 0.7em; + position: relative; + top: 2px; + fill: var(--systemPrimary); + } + + nav :global(.menu-popover) { + width: 211px; + } +</style> diff --git a/src/components/jet/web-navigation/PlatformSelectorItem.svelte b/src/components/jet/web-navigation/PlatformSelectorItem.svelte new file mode 100644 index 0000000..9b72fda --- /dev/null +++ b/src/components/jet/web-navigation/PlatformSelectorItem.svelte @@ -0,0 +1,97 @@ +<script lang="ts"> + import { isSome } from '@jet/environment/types/optional'; + import type { WebNavigationLink } from '@jet-app/app-store/api/models/web-navigation'; + import { isSearchResultsPageIntent } from '@jet-app/app-store/api/intents/search-results-page-intent'; + + import FlowAction from '~/components/jet/action/FlowAction.svelte'; + import SystemImage, { + isSystemImageArtwork, + } from '~/components/SystemImage.svelte'; + import SFSymbol from '~/components/SFSymbol.svelte'; + import { getI18n } from '~/stores/i18n'; + + export let platformSelector: WebNavigationLink; + + const i18n = getI18n(); + + $: ({ action, isActive } = platformSelector); + $: ({ artwork } = action); +</script> + +<FlowAction destination={action}> + <span class="platform-selector" class:is-active={isActive}> + {#if isSome(artwork) && isSystemImageArtwork(artwork)} + <div class="icon-container"> + <SystemImage {artwork} /> + </div> + {/if} + + <span + class="platform-title" + aria-label={$i18n.t( + 'ASE.Web.AppStore.Navigation.AX.PlatformSelectorItem', + { + platform: action.title, + }, + )} + > + {action.title} + </span> + + {#if action.destination && isSearchResultsPageIntent(action.destination)} + <span aria-hidden={true} class="search-icon-container"> + <SFSymbol name="magnifyingglass" /> + </span> + {/if} + </span> +</FlowAction> + +<style lang="scss"> + @use '@amp/web-shared-styles/app/core/globalvars' as *; + + .platform-selector { + display: flex; + border-radius: var(--global-border-radius-medium); + padding: 8px; + margin-bottom: 4px; + gap: 10px; + transition: background-color 175ms ease-in; + } + + .platform-selector:not(.is-active):hover { + background-color: rgba(45, 45, 45, 0.035); + + @media (prefers-color-scheme: dark) { + background-color: rgba(45, 45, 45, 0.35); + } + } + + .platform-selector.is-active { + background-color: var(--systemQuinary); + } + + .icon-container { + display: flex; + justify-content: center; + padding-inline-end: 2px; + } + + .icon-container :global(svg) { + max-height: 16px; + width: 23px; + } + + .search-icon-container { + display: flex; + } + + .search-icon-container :global(svg) { + fill: var(--systemSecondary); + width: 16px; + } + + .platform-title { + font: var(--body); + flex-grow: 1; + } +</style> |
