Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions website/src/components/home/TrailerHero.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@ import { describe, expect, it } from 'vitest';
import TrailerHero from './TrailerHero.vue';

describe('TrailerHero', () => {
it('does not render promotional copy or a Steam link over the trailer', () => {
const wrapper = mount(TrailerHero);

expect(wrapper.find('a').exists()).toBe(false);
expect(wrapper.text()).not.toMatch(/watch film/i);
});

it('uses an inline SVG for the play icon', () => {
const wrapper = mount(TrailerHero);
const playButton = wrapper.get(
'button[aria-label="Play the Straif trailer"]'
);

expect(playButton.get('svg').attributes('aria-hidden')).toBe('true');
expect(playButton.element.children).toHaveLength(1);
});

it('loads the privacy-enhanced embed only after activation', async () => {
const wrapper = mount(TrailerHero);
expect(wrapper.find('iframe').exists()).toBe(false);
Expand Down
85 changes: 44 additions & 41 deletions website/src/components/home/TrailerHero.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,49 @@ const trailerSrc =
</script>

<template>
<section class="trailer-hero" aria-labelledby="trailer-title">
<div class="trailer-hero__copy">
<p>Official trailer · YouTube</p>
<h1 id="trailer-title">Straif</h1>
<p>Watch film</p>
</div>
<div class="trailer-hero-shell">
<section class="trailer-hero" aria-labelledby="trailer-title">
<div class="trailer-hero__copy">
<p>Official trailer · YouTube</p>
<h1 id="trailer-title">Straif</h1>
</div>

<div class="trailer-hero__media">
<template v-if="isPlaying">
<iframe
:src="trailerSrc"
title="Straif official trailer"
allow="
accelerometer;
autoplay;
clipboard-write;
encrypted-media;
gyroscope;
picture-in-picture;
web-share;
"
allowfullscreen
/>
</template>
<template v-else>
<img
src="https://i.ytimg.com/vi/CfzotZZ3Sd0/maxresdefault.jpg"
alt=""
width="1280"
height="720"
fetchpriority="high"
/>
<button
type="button"
aria-label="Play the Straif trailer"
@click="isPlaying = true"
>
Play trailer
</button>
</template>
</div>
</section>
<div class="trailer-hero__media">
<template v-if="isPlaying">
<iframe
:src="trailerSrc"
title="Straif official trailer"
allow="
accelerometer;
autoplay;
clipboard-write;
encrypted-media;
gyroscope;
picture-in-picture;
web-share;
"
allowfullscreen
/>
</template>
<template v-else>
<img
src="https://i.ytimg.com/vi/CfzotZZ3Sd0/maxresdefault.jpg"
alt=""
width="1280"
height="720"
fetchpriority="high"
/>
<button
type="button"
aria-label="Play the Straif trailer"
@click="isPlaying = true"
>
<svg aria-hidden="true" viewBox="0 0 24 24" focusable="false">
<path d="M8.5 5.75 19 12 8.5 18.25Z" />
</svg>
</button>
</template>
</div>
</section>
</div>
</template>
45 changes: 45 additions & 0 deletions website/src/components/layout/SiteChrome.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { mount } from '@vue/test-utils';
import { describe, expect, it } from 'vitest';
import SiteFooter from './SiteFooter.vue';
import SiteHeader from './SiteHeader.vue';

const steamUrl = 'https://store.steampowered.com/app/3850480/Straif/';
const routerLinkStub = {
props: ['to'],
template: '<a :href="to"><slot /></a>',
};

function mountWithRouterLink(component) {
return mount(component, {
global: {
stubs: {
RouterLink: routerLinkStub,
},
},
});
}

describe('site Steam links', () => {
it('adds the approved Steam link to the header', () => {
const wrapper = mountWithRouterLink(SiteHeader);
const link = wrapper.get(`a[href="${steamUrl}"]`);

expect(link.text()).toBe('Get Straif');
expect(link.attributes()).toMatchObject({
target: '_blank',
rel: 'noopener noreferrer',
});
expect(link.get('svg').attributes('aria-hidden')).toBe('true');
});

it('adds the approved Steam link to the footer', () => {
const wrapper = mountWithRouterLink(SiteFooter);
const link = wrapper.get(`a[href="${steamUrl}"]`);

expect(link.text()).toBe('Steam');
expect(link.attributes()).toMatchObject({
target: '_blank',
rel: 'noopener noreferrer',
});
});
});
15 changes: 14 additions & 1 deletion website/src/components/layout/SiteFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,20 @@
<nav aria-label="Footer navigation">
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/leaderboard">Leaderboard</RouterLink>
<a href="https://straifapi.pumped.software/docs">API</a>
<a
href="https://store.steampowered.com/app/3850480/Straif/"
target="_blank"
rel="noopener noreferrer"
>
Steam
</a>
<a
href="https://straifapi.pumped.software/docs"
target="_blank"
rel="noopener noreferrer"
>
API
</a>
</nav>
</footer>
</template>
13 changes: 13 additions & 0 deletions website/src/components/layout/SiteHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@
<nav aria-label="Primary navigation">
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/leaderboard">Leaderboard</RouterLink>
<a
class="site-header__cta"
href="https://store.steampowered.com/app/3850480/Straif/"
target="_blank"
rel="noopener noreferrer"
>
<svg aria-hidden="true" viewBox="0 0 24 24" focusable="false">
<circle cx="15.5" cy="8.5" r="4.25" />
<circle cx="5.75" cy="17.25" r="2.75" />
<path d="m8.1 15.8 4.4-4.4" />
</svg>
Get Straif
</a>
</nav>
</header>
</template>
74 changes: 53 additions & 21 deletions website/src/styles/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,26 @@ a {
font-weight: 500;
}

.site-header nav .site-header__cta {
display: inline-flex;
align-items: center;
gap: 0.45rem;
border: 1px solid var(--color-border-strong);
color: var(--color-text);
padding: 0.45rem 0.65rem;
white-space: nowrap;
}

.site-header__cta svg {
width: 1rem;
height: 1rem;
fill: none;
stroke: currentColor;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 1.75;
}

.site-header nav a.router-link-exact-active {
color: var(--color-text);
}
Expand All @@ -185,12 +205,21 @@ a {
text-transform: uppercase;
}

.trailer-hero-shell {
width: min(
calc(100% - var(--page-gutter) - var(--page-gutter)),
84rem,
calc(156.4444vh - 7.1111rem)
);
margin-top: clamp(0.75rem, 2vw, 1.5rem);
margin-inline: auto;
}

.trailer-hero {
position: relative;
isolation: isolate;
width: min(100%, 100rem, calc(177.7778vh - 7.1111rem));
max-height: calc(100vh - 4rem);
margin-inline: auto;
width: 100%;
max-height: calc(88vh - 4rem);
overflow: hidden;
aspect-ratio: 16 / 9;
background: var(--color-surface);
Expand Down Expand Up @@ -239,14 +268,15 @@ a {
transform var(--transition-fast);
}

.trailer-hero__media button::before {
width: 0;
height: 0;
margin-left: 0.2rem;
border-top: 0.45rem solid transparent;
border-bottom: 0.45rem solid transparent;
border-left: 0.72rem solid var(--color-text);
content: '';
.trailer-hero__media button svg {
width: 1.25rem;
height: 1.25rem;
color: var(--color-text);
transform: translateX(0.08rem);
}

.trailer-hero__media button path {
fill: currentColor;
}

.trailer-hero__media button:active {
Expand All @@ -259,9 +289,9 @@ a {
right: var(--page-gutter);
bottom: var(--page-gutter);
left: var(--page-gutter);
display: flex;
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: flex-end;
justify-content: space-between;
gap: 1.5rem;
pointer-events: none;
}
Expand All @@ -278,10 +308,6 @@ a {
text-transform: uppercase;
}

.trailer-hero__copy > p:last-child {
text-align: right;
}

.trailer-hero h1,
.page-heading h1 {
font-size: clamp(3rem, 8vw, 7.5rem);
Expand Down Expand Up @@ -718,9 +744,19 @@ a {
}

.site-header {
gap: 0.75rem;
padding-block: 1.25rem;
}

.site-header nav {
justify-content: flex-end;
gap: 0.625rem;
}

.site-header nav .site-header__cta {
padding-inline: 0.45rem;
}

.site-footer {
flex-direction: column;
gap: 1rem;
Expand All @@ -742,10 +778,6 @@ a {
font-size: 0.625rem;
}

.trailer-hero__copy > p:last-child {
display: none;
}

.game-intro {
grid-template-columns: minmax(0, 1fr);
gap: 2rem;
Expand Down
Loading