feat(gui-v2): PageHead (Tailwind flex title/sub/#actions) + story

This commit is contained in:
2026-05-18 10:52:09 +02:00
parent 12cff8c03a
commit b0d5e9611f
3 changed files with 75 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
import type { Meta, StoryObj } from '@storybook/vue3-vite'
import Button from 'primevue/button'
import PageHead from '@/components-v2/shared/PageHead.vue'
const meta: Meta<typeof PageHead> = {
title: 'Shared/PageHead',
component: PageHead,
tags: ['autodocs'],
argTypes: { title: { control: 'text' }, sub: { control: 'text' } },
}
export default meta
type Story = StoryObj<typeof PageHead>
export const TitleOnly: Story = { args: { title: 'Evenementen' } }
export const WithSub: Story = { args: { title: 'Evenementen', sub: '3 actieve evenementen' } }
export const WithActions: Story = {
args: { title: 'Evenementen', sub: '3 actief' },
render: args => ({
components: { PageHead, Button },
setup: () => ({ args }),
template: '<PageHead :title="args.title" :sub="args.sub"><template #actions><Button label="Nieuw evenement" /></template></PageHead>',
}),
}

View File

@@ -0,0 +1,27 @@
<script setup lang="ts">
/**
* PageHead — title/sub/#actions. Pure layout (spec §8). CSS translation
* of main.css .page-head 466478 (+ <=640px stack 13551360) to Tailwind.
*/
defineProps<{ title: string; sub?: string }>()
</script>
<template>
<div class="flex flex-wrap items-end justify-between gap-6 mb-5 max-[640px]:flex-col max-[640px]:items-stretch max-[640px]:gap-3.5">
<div class="min-w-0 flex-[1_1_240px] max-[640px]:flex-[0_0_auto]">
<h1 class="m-0 text-2xl font-bold tracking-[-0.01em] text-[var(--p-text-color)] text-balance max-[640px]:text-[22px]">
{{ title }}
</h1>
<div
v-if="sub"
data-sub
class="mt-1 text-[13.5px] text-[var(--p-text-muted-color)]"
>
{{ sub }}
</div>
</div>
<div class="flex flex-wrap items-center gap-2 max-[640px]:w-full max-[640px]:justify-start">
<slot name="actions" />
</div>
</div>
</template>

View File

@@ -0,0 +1,24 @@
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import PageHead from '@/components-v2/shared/PageHead.vue'
describe('PageHead', () => {
it('renders the title and optional sub', () => {
const w = mount(PageHead, { props: { title: 'Evenementen', sub: '3 actief' } })
expect(w.get('h1').text()).toBe('Evenementen')
expect(w.text()).toContain('3 actief')
})
it('omits the sub element when not provided', () => {
const w = mount(PageHead, { props: { title: 'Evenementen' } })
expect(w.find('[data-sub]').exists()).toBe(false)
})
it('renders the #actions slot', () => {
const w = mount(PageHead, { props: { title: 'X' }, slots: { actions: '<button>New</button>' } })
expect(w.get('button').text()).toBe('New')
})
})