Skip to content

Commit d585c43

Browse files
authored
feature: phone cleanup across watch, clips, events, matches, servers and the left nav (#974)
1 parent 3aaaa53 commit d585c43

36 files changed

Lines changed: 558 additions & 282 deletions

‎components/MatchOptions.vue‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ import { SELECT_NONE, nullableSelectField } from "~/utilities/selectNone";
9393
square
9494
size="lg"
9595
block
96+
class="max-md:grid max-md:grid-cols-2 max-md:[&>button:last-of-type:nth-of-type(odd)]:col-span-2"
9697
@update:model-value="
9798
(value) => !mapPoolLocked && form.setFieldValue('type', value)
9899
"
@@ -110,8 +111,8 @@ import { SELECT_NONE, nullableSelectField } from "~/utilities/selectNone";
110111

111112
<FormField name="map_pool" v-if="!isRush">
112113
<FormItem>
113-
<Card>
114-
<div class="p-6 space-y-6">
114+
<Card class="max-md:border-0 max-md:bg-transparent max-md:shadow-none">
115+
<div class="p-6 space-y-6 max-md:p-0">
115116
<div
116117
class="grid gap-6"
117118
:class="hideBestOf ? 'sm:grid-cols-1' : 'sm:grid-cols-2'"
@@ -203,7 +204,7 @@ import { SELECT_NONE, nullableSelectField } from "~/utilities/selectNone";
203204
</div>
204205

205206
<div
206-
class="flex items-center justify-between gap-3 border-t border-border pt-4"
207+
class="flex items-center justify-between gap-3 border-t border-border pt-4 max-md:flex-wrap max-md:gap-y-2"
207208
>
208209
<div
209210
class="min-w-0 font-mono text-[0.7rem] tracking-[0.22em] uppercase text-muted-foreground"
@@ -235,7 +236,7 @@ import { SELECT_NONE, nullableSelectField } from "~/utilities/selectNone";
235236
enter-from-class="opacity-0"
236237
leave-to-class="opacity-0"
237238
>
238-
<div v-show="form.values.map_veto" class="shrink-0">
239+
<div v-show="form.values.map_veto" class="ml-auto shrink-0">
239240
<FormField
240241
v-slot="{ value, handleChange }"
241242
name="custom_map_pool"

‎components/MatchTableRow.vue‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,6 @@ import MatchOverviewDrawer from "~/components/match/MatchOverviewDrawer.vue";
11291129
</span>
11301130
</span>
11311131
<ScrollArrows
1132-
v-if="filteredPlayerClips.length > 1"
11331132
:can-left="highlightsScrollRef?.state?.canScrollLeft"
11341133
:can-right="highlightsScrollRef?.state?.canScrollRight"
11351134
@scroll="(d) => highlightsScrollRef?.scrollByDirection(d)"

‎components/clips/ClipDetailModal.vue‎

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ import { useClipModal } from "~/composables/useClipModal";
7575
import { useClipShare } from "~/composables/useClipShare";
7676
import { useClipFileSize } from "~/composables/useClipFileSize";
7777
import { useClipDelete } from "~/composables/useClipDelete";
78+
import { useScrollArrows } from "~/composables/useScrollArrows";
79+
import ScrollArrows from "~/components/common/ScrollArrows.vue";
7880
import { Spinner } from "~/components/ui/spinner";
7981
8082
const apiDomain = computed(() => useRuntimeConfig().public.apiDomain as string);
@@ -684,6 +686,7 @@ watch(
684686
685687
// Keep the playing tile centred in the "Up next" strip.
686688
const stripRef = ref<HTMLElement | null>(null);
689+
const stripScroll = useScrollArrows(stripRef);
687690
watch(
688691
[activeClipIndex, () => !!clip.value, expanded],
689692
async () => {
@@ -893,39 +896,21 @@ const edgeButton =
893896
:kills="clip.kills_count"
894897
:round="clip.round"
895898
:title="clip.title"
896-
:size="expanded ? 'lg' : undefined"
897-
:class="expanded ? '' : '!bg-black/60 backdrop-blur-sm'"
899+
size="lg"
898900
/>
899-
<span
900-
v-if="duration"
901-
:class="
902-
expanded
903-
? onVideoChip
904-
: [tileChip, 'bg-black/60 text-white/90 backdrop-blur-sm']
905-
"
906-
>
901+
<span v-if="duration" :class="onVideoChip">
907902
{{ duration }}
908903
</span>
909904
<span
910-
:class="
911-
expanded
912-
? onVideoChip
913-
: [
914-
tileChip,
915-
'gap-1 bg-black/60 text-white/90 backdrop-blur-sm',
916-
]
917-
"
905+
:class="onVideoChip"
918906
:title="$t('clips.tile.views', { count: views }, views)"
919907
>
920908
<Eye class="h-3.5 w-3.5" />
921909
{{ views }}
922910
</span>
923911
<span
924912
v-if="!expanded && hasQueueNav"
925-
:class="[
926-
tileChip,
927-
'bg-black/60 text-white/90 backdrop-blur-sm',
928-
]"
913+
:class="onVideoChip"
929914
>
930915
{{ activeClipIndex + 1 }} / {{ clipQueue.length }}
931916
</span>
@@ -948,6 +933,7 @@ const edgeButton =
948933
:download-name="downloadFilename"
949934
:size-label="fileSize"
950935
content-class="z-[70]"
936+
trigger-class="h-[30px] rounded-md sm:h-9"
951937
@copy="copyLink"
952938
>
953939
<template v-if="canAdminister">
@@ -1009,7 +995,7 @@ const edgeButton =
1009995
<button
1010996
v-if="!expanded"
1011997
type="button"
1012-
:class="[onVideoAction, '!h-8 !w-8']"
998+
:class="onVideoAction"
1013999
:aria-label="$t('common.close')"
10141000
@click.stop="closeClip"
10151001
>
@@ -1528,9 +1514,10 @@ const edgeButton =
15281514
</template>
15291515
</div>
15301516

1517+
<!-- Full-screen on phones: Up next sits on the bottom edge. -->
15311518
<section
15321519
v-if="clipQueue.length > 1"
1533-
class="border-t border-white/[0.06] px-5 pb-6 pt-4 sm:px-6"
1520+
class="border-t border-white/[0.06] px-5 pb-6 pt-4 max-sm:mt-auto max-sm:pb-[max(1.5rem,env(safe-area-inset-bottom))] sm:px-6"
15341521
>
15351522
<div
15361523
:class="[
@@ -1542,11 +1529,18 @@ const edgeButton =
15421529
<span :class="tacticalSectionTickClasses"></span>
15431530
{{ $t("clips.detail.up_next") }}
15441531
</span>
1545-
<span
1546-
v-if="hasQueueNav"
1547-
class="normal-case tabular-nums tracking-normal"
1548-
>
1549-
{{ activeClipIndex + 1 }} / {{ clipQueue.length }}
1532+
<span class="inline-flex items-center gap-3">
1533+
<span
1534+
v-if="hasQueueNav"
1535+
class="normal-case tabular-nums tracking-normal"
1536+
>
1537+
{{ activeClipIndex + 1 }} / {{ clipQueue.length }}
1538+
</span>
1539+
<ScrollArrows
1540+
:can-left="stripScroll.state.canScrollLeft"
1541+
:can-right="stripScroll.state.canScrollRight"
1542+
@scroll="stripScroll.scrollByDirection"
1543+
/>
15501544
</span>
15511545
</div>
15521546
<div
@@ -1557,7 +1551,7 @@ const edgeButton =
15571551
v-for="q in clipQueue"
15581552
:key="q.id"
15591553
type="button"
1560-
class="group/q relative isolate aspect-video w-52 shrink-0 snap-start overflow-hidden rounded-lg border bg-card text-left transition-[border-color,transform] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--tac-amber))] motion-safe:active:scale-[0.97]"
1554+
class="group/q relative isolate aspect-video w-52 shrink-0 snap-start overflow-hidden max-sm:w-[80%] rounded-lg border bg-card text-left transition-[border-color,transform] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--tac-amber))] motion-safe:active:scale-[0.97]"
15611555
:class="
15621556
q.id === clipId
15631557
? 'border-[hsl(var(--tac-amber)/0.7)]'

‎components/clips/ClipPlayer.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ defineExpose({ play, pause, toggle, videoEl: videoRef, isFullscreen });
840840
:fullscreen="isFullscreen"
841841
:muted="muted"
842842
:volume="volume"
843-
:visible="true"
843+
:visible="hudVisible"
844844
align="end"
845845
@toggle-fullscreen="toggleFullscreen"
846846
@toggle-mute="toggleMute"

‎components/clips/ClipShareMenu.vue‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
DropdownMenuTrigger,
99
} from "~/components/ui/dropdown-menu";
1010
import { backClosesMenus, useBackDismiss } from "~/composables/useBackDismiss";
11+
import { cn } from "@/lib/utils";
1112
1213
// The one Share button a clip carries in its player's tray, on highlights and
1314
// lineups alike: copy the link, download the file, and whatever the surface
@@ -21,6 +22,7 @@ const props = withDefaults(
2122
downloadLabel?: string | null;
2223
sizeLabel?: string | null;
2324
contentClass?: string | null;
25+
triggerClass?: string | null;
2426
// Back closes this menu first. Off where the page runs its own history,
2527
// as the highlight modal does.
2628
dismissOnBack?: boolean;
@@ -32,6 +34,7 @@ const props = withDefaults(
3234
downloadLabel: null,
3335
sizeLabel: null,
3436
contentClass: null,
37+
triggerClass: null,
3538
dismissOnBack: false,
3639
},
3740
);
@@ -76,7 +79,12 @@ function onDownload(event: Event) {
7679
<DropdownMenuTrigger as-child>
7780
<button
7881
type="button"
79-
class="inline-flex h-8 items-center justify-center gap-1.5 rounded-full border border-white/20 bg-black/70 pl-2.5 pr-3 text-xs font-medium text-white/85 backdrop-blur-md transition-colors hover:border-[hsl(var(--tac-amber)/0.55)] hover:text-[hsl(var(--tac-amber))] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--tac-amber))] data-[state=open]:border-[hsl(var(--tac-amber)/0.55)] data-[state=open]:text-[hsl(var(--tac-amber))]"
82+
:class="
83+
cn(
84+
'inline-flex h-8 items-center justify-center gap-1.5 rounded-full border border-white/20 bg-black/70 pl-2.5 pr-3 text-xs font-medium text-white/85 backdrop-blur-md transition-colors hover:border-[hsl(var(--tac-amber)/0.55)] hover:text-[hsl(var(--tac-amber))] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--tac-amber))] data-[state=open]:border-[hsl(var(--tac-amber)/0.55)] data-[state=open]:text-[hsl(var(--tac-amber))]',
85+
triggerClass,
86+
)
87+
"
8088
@click.stop
8189
>
8290
<Share2 class="h-3.5 w-3.5" />

‎components/common/BackLink.vue‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
<script setup lang="ts">
22
import type { RouteLocationRaw } from "vue-router";
3-
import { useBackToList } from "~/composables/useHistoryBack";
3+
import {
4+
useBackToList,
5+
useTopBarBackShown,
6+
} from "~/composables/useHistoryBack";
47
58
defineOptions({ inheritAttrs: false });
69
710
const props = defineProps<{ to: RouteLocationRaw }>();
811
912
const stepBackTo = useBackToList();
13+
const topBarBack = useTopBarBackShown();
1014
1115
function onClick(event: MouseEvent, navigate: (event?: MouseEvent) => unknown) {
1216
const plain =
@@ -26,7 +30,7 @@ function onClick(event: MouseEvent, navigate: (event?: MouseEvent) => unknown) {
2630
</script>
2731

2832
<template>
29-
<NuxtLink v-slot="{ href, navigate }" :to="to" custom>
33+
<NuxtLink v-if="!topBarBack" v-slot="{ href, navigate }" :to="to" custom>
3034
<a :href="href" v-bind="$attrs" @click="onClick($event, navigate)">
3135
<slot />
3236
</a>

‎components/common/ScrollArrows.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const { t } = useI18n();
1515
</script>
1616

1717
<template>
18-
<div v-show="canLeft || canRight" class="inline-flex items-center gap-1">
18+
<div class="inline-flex items-center gap-1">
1919
<button
2020
type="button"
2121
:aria-label="t('ui.scroll.left')"

‎components/events/EventPastTile.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const count = (key: string) =>
2020
:to="`/events/${event.id}`"
2121
class="group/tile flex w-56 shrink-0 snap-start flex-col overflow-hidden rounded-lg border border-border bg-card/40 text-left transition-colors duration-150 hover:border-[hsl(var(--tac-amber)/0.45)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
2222
>
23-
<span class="relative block aspect-[2/1] overflow-hidden bg-muted/40">
23+
<span class="relative block aspect-[3/1] overflow-hidden bg-muted/40">
2424
<img
2525
v-if="bannerSrc"
2626
:src="bannerSrc"

‎components/events/EventUpNext.vue‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,27 @@ const facts = computed(() => {
6161
v-if="hero"
6262
class="grid overflow-hidden rounded-lg border border-[hsl(var(--tac-amber)/0.35)] bg-card/40 transition-colors duration-150 has-[[data-card-link]:hover]:border-[hsl(var(--tac-amber)/0.6)] lg:grid-cols-[minmax(0,1fr)_21rem]"
6363
>
64+
<!-- One column: the whole 3:1 banner, the title under it. -->
6465
<NuxtLink
6566
:to="path"
6667
data-card-link
67-
class="group/media relative isolate flex min-h-[18rem] items-end overflow-hidden px-4 pb-5 pt-28 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring sm:px-6 sm:pb-6"
68+
class="group/media relative isolate flex flex-col overflow-hidden focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring lg:min-h-[18rem] lg:flex-row lg:items-end lg:px-6 lg:pb-6 lg:pt-28"
6869
>
69-
<img
70+
<div
7071
v-if="bannerSrc"
71-
:src="bannerSrc"
72-
alt=""
73-
class="absolute inset-0 -z-20 h-full w-full object-cover object-[50%_40%] transition-transform [transition-duration:600ms] [transition-timing-function:cubic-bezier(0.16,1,0.3,1)] motion-reduce:transition-none group-hover/media:scale-[1.03]"
74-
/>
75-
<div aria-hidden="true" class="hero-scrim absolute inset-0 -z-10"></div>
76-
<div class="grid min-w-0 max-w-[40rem] gap-2.5">
72+
class="aspect-[3/1] overflow-hidden lg:absolute lg:inset-0 lg:-z-20 lg:aspect-auto"
73+
>
74+
<img
75+
:src="bannerSrc"
76+
alt=""
77+
class="h-full w-full object-cover object-[50%_40%] transition-transform [transition-duration:600ms] [transition-timing-function:cubic-bezier(0.16,1,0.3,1)] motion-reduce:transition-none group-hover/media:scale-[1.03]"
78+
/>
79+
</div>
80+
<div
81+
aria-hidden="true"
82+
class="hero-scrim absolute inset-0 -z-10 max-lg:hidden"
83+
></div>
84+
<div class="grid min-w-0 max-w-[40rem] gap-2.5 px-5 pb-5 pt-4 lg:p-0">
7785
<p
7886
class="m-0 flex flex-wrap items-center gap-x-1.5 text-[0.8125rem] text-foreground/80"
7987
>

‎components/match/MatchHighlightsReel.vue‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ import type { Clip } from "~/types/clip";
1515
import { resolveAvatarUrl } from "~/utilities/avatarUrl";
1616
import { useClipModal } from "~/composables/useClipModal";
1717
import { useClipShare } from "~/composables/useClipShare";
18+
import { useScrollArrows } from "~/composables/useScrollArrows";
1819
import { NuxtLink } from "#components";
1920
import ClipPlayer from "~/components/clips/ClipPlayer.vue";
2021
import ClipKillBadge from "~/components/clips/ClipKillBadge.vue";
22+
import ScrollArrows from "~/components/common/ScrollArrows.vue";
2123
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
2224
import { Button } from "~/components/ui/button";
2325
@@ -150,6 +152,8 @@ const hasMoreQueue = computed(
150152
() => queueVisibleCount.value < fullQueue.value.length,
151153
);
152154
const queueScrollEl = ref<HTMLElement | null>(null);
155+
// Below lg the queue is a horizontal strip.
156+
const queueScroll = useScrollArrows(queueScrollEl);
153157
const queueSentinelEl = ref<HTMLElement | null>(null);
154158
let queueObserver: IntersectionObserver | null = null;
155159
function ensureQueueObserver() {
@@ -460,10 +464,20 @@ function clipTeamName(c: Clip): string | null {
460464
class="flex items-center justify-between gap-3 px-1 pb-1.5 pt-1 text-[13px] font-bold lg:px-3.5 lg:pb-2 lg:pt-3"
461465
>
462466
{{ $t("match.up_next") }}
463-
<span class="font-medium tabular-nums text-muted-foreground">
464-
{{
465-
$t("match.highlights.clip_count", { count: filteredClips.length })
466-
}}
467+
<span class="inline-flex items-center gap-3">
468+
<span class="font-medium tabular-nums text-muted-foreground">
469+
{{
470+
$t("match.highlights.clip_count", {
471+
count: filteredClips.length,
472+
})
473+
}}
474+
</span>
475+
<ScrollArrows
476+
class="lg:hidden"
477+
:can-left="queueScroll.state.canScrollLeft"
478+
:can-right="queueScroll.state.canScrollRight"
479+
@scroll="queueScroll.scrollByDirection"
480+
/>
467481
</span>
468482
</div>
469483
<ol

0 commit comments

Comments
 (0)