@classic-homes/theme-svelte 1.13.0 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { render, screen } from '@testing-library/svelte';
|
|
3
|
+
import PageHeader from '../lib/components/PageHeader.svelte';
|
|
4
|
+
/**
|
|
5
|
+
* The title must carry its own type scale. Tailwind preflight resets heading
|
|
6
|
+
* size/weight and outranks the theme's layered base rule in consumer apps, so
|
|
7
|
+
* a bare <h1> is body-sized there - PageHeader cannot lean on it.
|
|
8
|
+
*/
|
|
9
|
+
describe('PageHeader title typography', () => {
|
|
10
|
+
it('sets the Spectral display scale on the default h1', () => {
|
|
11
|
+
render(PageHeader, { props: { title: 'All Available Homes' } });
|
|
12
|
+
const h1 = screen.getByRole('heading', { level: 1 });
|
|
13
|
+
expect(h1).toHaveClass('text-h1', 'font-serif', 'italic');
|
|
14
|
+
});
|
|
15
|
+
it('follows the `as` level: h2 is Figtree at the h2 scale', () => {
|
|
16
|
+
render(PageHeader, { props: { title: 'Flying Horse', as: 'h2' } });
|
|
17
|
+
const h2 = screen.getByRole('heading', { level: 2 });
|
|
18
|
+
expect(h2).toHaveClass('text-h2', 'font-sans', 'not-italic');
|
|
19
|
+
expect(h2).not.toHaveClass('text-h1', 'italic');
|
|
20
|
+
});
|
|
21
|
+
it('applies the same scale to the centered variant', () => {
|
|
22
|
+
render(PageHeader, { props: { title: 'About', variant: 'centered' } });
|
|
23
|
+
expect(screen.getByRole('heading', { level: 1 })).toHaveClass('text-h1', 'font-serif');
|
|
24
|
+
});
|
|
25
|
+
it('leaves the hero and form display styles alone', () => {
|
|
26
|
+
const { unmount } = render(PageHeader, { props: { title: 'Ship', variant: 'hero' } });
|
|
27
|
+
const hero = screen.getByRole('heading', { level: 1 });
|
|
28
|
+
expect(hero).toHaveClass('text-5xl', 'font-black');
|
|
29
|
+
expect(hero).not.toHaveClass('text-h1', 'font-serif');
|
|
30
|
+
unmount();
|
|
31
|
+
render(PageHeader, { props: { title: 'Sign in', variant: 'form' } });
|
|
32
|
+
const form = screen.getByRole('heading', { level: 1 });
|
|
33
|
+
expect(form).toHaveClass('font-light');
|
|
34
|
+
expect(form).not.toHaveClass('text-h1');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -10,9 +10,12 @@
|
|
|
10
10
|
* - Optional subtitle with branded styling
|
|
11
11
|
* - Optional actions slot for CTA buttons
|
|
12
12
|
* - Consistent typography using design tokens: `default` and `centered`
|
|
13
|
-
*
|
|
14
|
-
* 500 italic
|
|
15
|
-
*
|
|
13
|
+
* set the theme heading scale for the rendered level explicitly (h1 =
|
|
14
|
+
* Spectral 500 italic via `text-h1`, h2-h6 = Figtree 600 via `text-h2`..
|
|
15
|
+
* `text-h6`). They do not lean on the bare-element styles: Tailwind
|
|
16
|
+
* preflight outranks the theme's `@layer` heading rules in consumer apps,
|
|
17
|
+
* which left the title at body size. `hero` and `form` are display styles
|
|
18
|
+
* with their own scale.
|
|
16
19
|
*/
|
|
17
20
|
import type { Snippet } from 'svelte';
|
|
18
21
|
import { cn } from '../utils.js';
|
|
@@ -92,10 +95,26 @@
|
|
|
92
95
|
}: Props = $props();
|
|
93
96
|
|
|
94
97
|
const styles = $derived(pageHeaderVariants({ variant }));
|
|
98
|
+
|
|
99
|
+
/** Theme type style per heading level; `hero`/`form` carry their own */
|
|
100
|
+
const levelTypeClass: Record<NonNullable<Props['as']>, string> = {
|
|
101
|
+
h1: 'font-serif italic text-h1',
|
|
102
|
+
h2: 'font-sans not-italic text-h2',
|
|
103
|
+
h3: 'font-sans not-italic text-h3',
|
|
104
|
+
h4: 'font-sans not-italic text-h4',
|
|
105
|
+
h5: 'font-sans not-italic text-h5',
|
|
106
|
+
h6: 'font-sans not-italic text-h6',
|
|
107
|
+
};
|
|
108
|
+
const titleClass = $derived(
|
|
109
|
+
cn(
|
|
110
|
+
styles.title(),
|
|
111
|
+
variant === 'default' || variant === 'centered' ? levelTypeClass[as] : undefined
|
|
112
|
+
)
|
|
113
|
+
);
|
|
95
114
|
</script>
|
|
96
115
|
|
|
97
116
|
<header class={cn(styles.container(), className)} {...restProps}>
|
|
98
|
-
<svelte:element this={as} class={
|
|
117
|
+
<svelte:element this={as} class={titleClass}>{title}</svelte:element>
|
|
99
118
|
{#if subtitle}
|
|
100
119
|
<p class={styles.subtitle()}>{subtitle}</p>
|
|
101
120
|
{/if}
|
|
@@ -9,9 +9,12 @@
|
|
|
9
9
|
* - Optional subtitle with branded styling
|
|
10
10
|
* - Optional actions slot for CTA buttons
|
|
11
11
|
* - Consistent typography using design tokens: `default` and `centered`
|
|
12
|
-
*
|
|
13
|
-
* 500 italic
|
|
14
|
-
*
|
|
12
|
+
* set the theme heading scale for the rendered level explicitly (h1 =
|
|
13
|
+
* Spectral 500 italic via `text-h1`, h2-h6 = Figtree 600 via `text-h2`..
|
|
14
|
+
* `text-h6`). They do not lean on the bare-element styles: Tailwind
|
|
15
|
+
* preflight outranks the theme's `@layer` heading rules in consumer apps,
|
|
16
|
+
* which left the title at body size. `hero` and `form` are display styles
|
|
17
|
+
* with their own scale.
|
|
15
18
|
*/
|
|
16
19
|
import type { Snippet } from 'svelte';
|
|
17
20
|
declare const PageHeader: import("svelte").Component<{
|