refactor to use CSS grid
This commit is contained in:
parent
8ac0f6b931
commit
8e32989785
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": ["resumarkdown", "spacebar", "testid"]
|
"cSpell.words": ["resumarkdown", "spacebar", "tablist", "testid"]
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-weight: @weight-bold;
|
font-weight: @font-w-bold;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,5 @@
|
|||||||
padding: @padding-lg;
|
padding: @padding-lg;
|
||||||
resize: none;
|
resize: none;
|
||||||
width: .full-without-padding(@padding-lg-x) [];
|
width: .full-without-padding(@padding-lg-x) [];
|
||||||
|
|
||||||
@media screen and (min-width: @sizes[lg]) {
|
|
||||||
font-size: unset;
|
|
||||||
height: .full-without-padding(@padding-xl-y) [];
|
|
||||||
margin: @padding-xl;
|
|
||||||
width: .full-without-padding(@padding-xl-x) [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { navHeight } from '$lib/stores/layout';
|
|
||||||
import { pane as navStore, type Pane } from '$lib/stores/nav';
|
|
||||||
|
|
||||||
export let pane: Pane;
|
|
||||||
|
|
||||||
export let testid: string | undefined = undefined;
|
|
||||||
|
|
||||||
// don't show pane if we're not the current pane
|
|
||||||
let hidden: boolean;
|
|
||||||
$: hidden = pane !== $navStore;
|
|
||||||
|
|
||||||
// always show preview pane on a two column layout
|
|
||||||
let preview: boolean;
|
|
||||||
$: preview = pane === 'preview';
|
|
||||||
|
|
||||||
// offset preview pane upward on desktop
|
|
||||||
let offset: number;
|
|
||||||
$: offset = preview ? $navHeight : 0;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div
|
|
||||||
id={`pane-${pane}`}
|
|
||||||
data-testid={testid}
|
|
||||||
role="tabpanel"
|
|
||||||
class:hidden
|
|
||||||
class:preview
|
|
||||||
style:--offset={`-${offset}px`}
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="less">
|
|
||||||
div {
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: @sizes[lg]) {
|
|
||||||
border-right: 2px solid @color-dark;
|
|
||||||
width: 50%;
|
|
||||||
|
|
||||||
&.preview {
|
|
||||||
border-right: unset !important;
|
|
||||||
display: unset !important;
|
|
||||||
height: calc(100% - var(--offset));
|
|
||||||
transform: translateY(var(--offset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
25
src/lib/components/editor.svelte
Normal file
25
src/lib/components/editor.svelte
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { pane as navStore, type Pane } from '$lib/stores/nav';
|
||||||
|
|
||||||
|
export let pane: Pane;
|
||||||
|
|
||||||
|
export let testid: string | undefined = undefined;
|
||||||
|
|
||||||
|
// don't show pane if we're not the current pane
|
||||||
|
let hidden: boolean;
|
||||||
|
$: hidden = pane !== $navStore;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id={`pane-${pane}`} data-testid={testid} role="tabpanel" class:hidden>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
div {
|
||||||
|
grid-area: editor;
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,4 +1,6 @@
|
|||||||
<h1><slot /></h1>
|
<header>
|
||||||
|
<h1><slot /></h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
h1 {
|
h1 {
|
||||||
@ -8,4 +10,8 @@
|
|||||||
padding: @padding-md;
|
padding: @padding-md;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
grid-area: headline;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -6,10 +6,6 @@
|
|||||||
let selected: boolean;
|
let selected: boolean;
|
||||||
$: selected = destination === $pane;
|
$: selected = destination === $pane;
|
||||||
|
|
||||||
// we need to hide the "preview" tab on desktop
|
|
||||||
let hiddenOnDesktop: boolean;
|
|
||||||
$: hiddenOnDesktop = destination === 'preview';
|
|
||||||
|
|
||||||
function handleKey({ key }: KeyboardEvent) {
|
function handleKey({ key }: KeyboardEvent) {
|
||||||
if (key === ' ' || key === 'Enter' || key === 'Spacebar') {
|
if (key === ' ' || key === 'Enter' || key === 'Spacebar') {
|
||||||
navigate();
|
navigate();
|
||||||
@ -26,7 +22,6 @@
|
|||||||
aria-selected={selected}
|
aria-selected={selected}
|
||||||
role="tab"
|
role="tab"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class:hiddenOnDesktop
|
|
||||||
class:selected
|
class:selected
|
||||||
on:click={navigate}
|
on:click={navigate}
|
||||||
on:keyup={handleKey}
|
on:keyup={handleKey}
|
||||||
@ -36,21 +31,14 @@
|
|||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
li {
|
li {
|
||||||
box-sizing: border-box;
|
@separator: 1px solid @color-dark;
|
||||||
font-weight: @weight-semibold;
|
|
||||||
|
font-weight: @font-w-semibold;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: @padding-md;
|
padding: @padding-md;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
@media screen and (min-width: @sizes[lg]) {
|
|
||||||
width: 50%;
|
|
||||||
|
|
||||||
&.hiddenOnDesktop {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
background-color: darken(@color-light, 20%);
|
background-color: darken(@color-light, 20%);
|
||||||
}
|
}
|
||||||
@ -61,17 +49,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:not(:last-of-type) {
|
&:not(:last-of-type) {
|
||||||
@separator: 1px solid @color-dark;
|
|
||||||
|
|
||||||
border-bottom: @separator;
|
border-bottom: @separator;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-width: @sizes[lg]) {
|
@media screen and (min-width: @sizes[lg]) {
|
||||||
border-bottom: unset;
|
flex: 1;
|
||||||
border-right: @separator;
|
|
||||||
|
|
||||||
&:nth-of-type(n + 2) {
|
&:not(:last-of-type) {
|
||||||
border-right: unset;
|
border-bottom: none;
|
||||||
}
|
border-right: @separator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,8 @@
|
|||||||
border: none;
|
border: none;
|
||||||
color: @color-light;
|
color: @color-light;
|
||||||
font-size: @font-s-md;
|
font-size: @font-s-md;
|
||||||
font-weight: @weight-semibold;
|
font-weight: @font-w-semibold;
|
||||||
padding: @padding-sm;
|
padding: @padding-sm;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@media screen and (min-width: @sizes[lg]) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,25 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import { slide } from 'svelte/transition';
|
import { slide } from 'svelte/transition';
|
||||||
|
|
||||||
import { navHeight } from '$lib/stores/layout';
|
|
||||||
|
|
||||||
import NavToggle from './nav-toggle.svelte';
|
import NavToggle from './nav-toggle.svelte';
|
||||||
|
|
||||||
export let mobile: boolean = true;
|
export let mobile: boolean = true;
|
||||||
|
|
||||||
let open: boolean = false;
|
let open: boolean = false;
|
||||||
|
|
||||||
// magic to offset preview pane on desktop
|
|
||||||
let navRef: HTMLElement;
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
$navHeight = navRef.getBoundingClientRect().height;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav bind:this={navRef}>
|
<nav>
|
||||||
|
{#if mobile}
|
||||||
<NavToggle bind:navOpen={open} />
|
<NavToggle bind:navOpen={open} />
|
||||||
|
{/if}
|
||||||
{#if open || !mobile}
|
{#if open || !mobile}
|
||||||
<ul role="tablist" transition:slide={{ duration: 300 }}>
|
<ul role="tablist" transition:slide={{ duration: 300 }}>
|
||||||
<slot />
|
<slot />
|
||||||
@ -28,6 +20,10 @@
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
nav {
|
||||||
|
grid-area: navtree;
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
@border: 2px solid @color-dark;
|
@border: 2px solid @color-dark;
|
||||||
|
|
||||||
@ -38,12 +34,11 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
@media screen and (min-width: @sizes[lg]) {
|
@media screen and (min-width: @sizes[lg]) {
|
||||||
align-items: center;
|
align-items: stretch;
|
||||||
border-right: @border;
|
border-right: @border;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-evenly;
|
justify-content: space-between;
|
||||||
width: 50%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
32
src/lib/components/preview.svelte
Normal file
32
src/lib/components/preview.svelte
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { pane } from '$lib/stores/nav';
|
||||||
|
|
||||||
|
export let mobile: boolean;
|
||||||
|
|
||||||
|
let hidden: boolean;
|
||||||
|
$: hidden = mobile ? $pane !== 'preview' : true;
|
||||||
|
|
||||||
|
export let markdown: string;
|
||||||
|
export let stylesheet: string;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main class:hidden class:mobile data-testid="preview-pane">
|
||||||
|
<h2>markdown:</h2>
|
||||||
|
<code>{markdown}</code>
|
||||||
|
<h2>stylesheet:</h2>
|
||||||
|
<code>{stylesheet}</code>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
main {
|
||||||
|
grid-area: preview;
|
||||||
|
|
||||||
|
&.mobile {
|
||||||
|
grid-area: editor;
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,3 +0,0 @@
|
|||||||
import { writable } from 'svelte/store';
|
|
||||||
|
|
||||||
export const navHeight = writable(-1);
|
|
@ -1,12 +1,39 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
|
import { pane } from '$lib/stores/nav.js';
|
||||||
|
|
||||||
import CodeInput from '$lib/components/code-input.svelte';
|
import CodeInput from '$lib/components/code-input.svelte';
|
||||||
import Content from '$lib/components/content.svelte';
|
import Editor from '$lib/components/editor.svelte';
|
||||||
import Headline from '$lib/components/headline.svelte';
|
import Headline from '$lib/components/headline.svelte';
|
||||||
import NavItem from '$lib/components/nav-item.svelte';
|
import NavItem from '$lib/components/nav-item.svelte';
|
||||||
import NavTree from '$lib/components/nav-tree.svelte';
|
import NavTree from '$lib/components/nav-tree.svelte';
|
||||||
|
import Preview from '$lib/components/preview.svelte';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
|
let mobile: boolean = data.mobile;
|
||||||
|
|
||||||
|
function checkIsDesktop() {
|
||||||
|
// TODO: figure out how to remove hard-coded value here
|
||||||
|
mobile = !window.matchMedia('screen and (min-width: 1280px)').matches;
|
||||||
|
|
||||||
|
if (!mobile && get(pane) === 'preview') {
|
||||||
|
pane.set('content');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
checkIsDesktop();
|
||||||
|
|
||||||
|
window.addEventListener('resize', checkIsDesktop);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', checkIsDesktop);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
let markdown: string = '';
|
let markdown: string = '';
|
||||||
let stylesheet: string = '';
|
let stylesheet: string = '';
|
||||||
</script>
|
</script>
|
||||||
@ -15,65 +42,40 @@
|
|||||||
<title>resumarkdown</title>
|
<title>resumarkdown</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
<div>
|
<div>
|
||||||
<header>
|
|
||||||
<Headline>resumarkdown</Headline>
|
<Headline>resumarkdown</Headline>
|
||||||
<NavTree mobile={data.mobile}>
|
<NavTree {mobile}>
|
||||||
<NavItem destination="content">content</NavItem>
|
<NavItem destination="content">content</NavItem>
|
||||||
<NavItem destination="style">style</NavItem>
|
<NavItem destination="style">style</NavItem>
|
||||||
|
{#if mobile}
|
||||||
<NavItem destination="preview">preview</NavItem>
|
<NavItem destination="preview">preview</NavItem>
|
||||||
|
{/if}
|
||||||
</NavTree>
|
</NavTree>
|
||||||
</header>
|
<Editor pane="content" testid="content-pane">
|
||||||
<main>
|
|
||||||
<Content pane="content" testid="content-pane">
|
|
||||||
<CodeInput bind:code={markdown} />
|
<CodeInput bind:code={markdown} />
|
||||||
</Content>
|
</Editor>
|
||||||
<Content pane="style" testid="style-pane">
|
<Editor pane="style" testid="style-pane">
|
||||||
<CodeInput bind:code={stylesheet} />
|
<CodeInput bind:code={stylesheet} />
|
||||||
</Content>
|
</Editor>
|
||||||
<Content pane="preview" testid="preview-pane">
|
<Preview {mobile} {markdown} {stylesheet} />
|
||||||
<dl>
|
|
||||||
<dt>markdown:</dt>
|
|
||||||
<dd>{markdown !== '' ? markdown : '???'}</dd>
|
|
||||||
<dt>stylesheet:</dt>
|
|
||||||
<dd>{stylesheet !== '' ? stylesheet : '???'}</dd>
|
|
||||||
</dl>
|
|
||||||
</Content>
|
|
||||||
</main>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
// util
|
|
||||||
.margin-v(@v) {
|
|
||||||
margin-bottom: @v;
|
|
||||||
margin-top: @v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// styles
|
|
||||||
div {
|
div {
|
||||||
align-items: stretch;
|
align-content: start;
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-template-areas:
|
||||||
|
'headline'
|
||||||
|
'navtree'
|
||||||
|
'editor';
|
||||||
|
grid-template-rows: min-content min-content 1fr;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
justify-content: start;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
.margin-v(@padding-lg-y);
|
|
||||||
}
|
|
||||||
|
|
||||||
dl {
|
|
||||||
margin: 0;
|
|
||||||
padding: @padding-xl;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
@media screen and (min-width: @sizes[lg]) {
|
@media screen and (min-width: @sizes[lg]) {
|
||||||
align-items: start;
|
grid-template-columns: repeat(2, 1fr);
|
||||||
display: flex;
|
grid-template-areas:
|
||||||
flex-direction: row;
|
'headline headline'
|
||||||
justify-content: space-between;
|
'navtree preview'
|
||||||
|
'editor preview';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
@fonts-sans: Rubik, Arial, sans-serif;
|
@fonts-sans: Rubik, Arial, sans-serif;
|
||||||
@font-s-lg: 2rem;
|
@font-s-lg: 2rem;
|
||||||
@font-s-md: 1.25rem;
|
@font-s-md: 1.25rem;
|
||||||
@weight-bold: 700;
|
@font-w-bold: 700;
|
||||||
@weight-semibold: 600;
|
@font-w-semibold: 600;
|
||||||
|
|
||||||
// layout
|
// layout
|
||||||
@border-r-xl: 0.75em;
|
@border-r-xl: 0.75em;
|
||||||
|
@ -2,42 +2,21 @@ import { expect, test } from '@playwright/test';
|
|||||||
|
|
||||||
test('desktop page has nav tree', async ({ page }) => {
|
test('desktop page has nav tree', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.locator('nav')).toBeVisible();
|
await expect(page.getByRole('navigation')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('desktop page does not have nav toggle', async ({ page }) => {
|
test('desktop page does not have nav toggle', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.locator('nav button')).toBeHidden();
|
await expect(page.getByRole('navigation').getByRole('button')).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('desktop page has two-column layout', async ({ page }) => {
|
test('desktop page has two-column layout', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.locator('#pane-preview')).toBeVisible();
|
await expect(page.getByTestId('content-pane')).toBeVisible();
|
||||||
|
await expect(page.getByTestId('preview-pane')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('desktop page has no "preview" nav item', async ({ page }) => {
|
test('desktop page has no "preview" nav item', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.getByRole('tab').filter({ hasText: 'preview' })).toBeHidden();
|
await expect(page.getByRole('tab').filter({ hasText: 'preview' })).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('desktop page has equal width for both columns', async ({ page }) => {
|
|
||||||
await page.goto('/');
|
|
||||||
const { width: contentWidth } = (await page.getByTestId('content-pane').boundingBox()) ?? {
|
|
||||||
width: -1,
|
|
||||||
};
|
|
||||||
const { width: previewWidth } = (await page.getByTestId('preview-pane').boundingBox()) ?? {
|
|
||||||
width: -2,
|
|
||||||
};
|
|
||||||
expect(contentWidth).toEqual(previewWidth);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('desktop page has equal width for nav items', async ({ page }) => {
|
|
||||||
await page.goto('/');
|
|
||||||
const visibleTabs = page.getByRole('tab').filter({ hasNotText: 'preview' });
|
|
||||||
const { width: firstTabWidth } = (await visibleTabs.first().boundingBox()) ?? {
|
|
||||||
width: -1,
|
|
||||||
};
|
|
||||||
for (let i = 1; i < (await visibleTabs.count()); i++) {
|
|
||||||
await expect((await visibleTabs.nth(i).boundingBox())?.width).toEqual(firstTabWidth);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
@ -2,9 +2,7 @@ import { expect, test } from '@playwright/test';
|
|||||||
|
|
||||||
test('page has headline', async ({ page }) => {
|
test('page has headline', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
const headline = page.locator('header h1');
|
await expect(page.getByRole('banner')).toHaveText('resumarkdown');
|
||||||
await expect(headline).toBeVisible();
|
|
||||||
await expect(headline).toHaveText('resumarkdown');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('nav items work', async ({ page }) => {
|
test('nav items work', async ({ page }) => {
|
||||||
|
@ -9,25 +9,26 @@ test.use({
|
|||||||
|
|
||||||
test('mobile page has nav tree hidden by default', async ({ page }) => {
|
test('mobile page has nav tree hidden by default', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.locator('nav ul')).toBeHidden();
|
await expect(page.getByRole('navigation').getByRole('tablist')).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('mobile page has nav toggle', async ({ page }) => {
|
test('mobile page has nav toggle', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.locator('nav button')).toBeVisible();
|
await expect(page.getByRole('navigation').getByRole('button')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('nav toggle works', async ({ page }) => {
|
test('nav toggle works', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await page.locator('nav button').click();
|
await page.getByText('show navigation').click();
|
||||||
await expect(page.locator('nav ul')).toBeVisible();
|
await expect(page.getByRole('navigation').getByRole('tablist')).toBeVisible();
|
||||||
await page.locator('nav button').click();
|
await page.getByText('hide navigation').click();
|
||||||
await expect(page.locator('nav ul')).toBeHidden();
|
await expect(page.getByRole('navigation').getByRole('tablist')).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('mobile page has single-column layout', async ({ page }) => {
|
test('mobile page has single-column layout', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.locator('#pane-preview')).toBeHidden();
|
await expect(page.getByTestId('content-pane')).toBeVisible();
|
||||||
|
await expect(page.getByTestId('preview-pane')).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('mobile page has preview nav item', async ({ page }) => {
|
test('mobile page has preview nav item', async ({ page }) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user