Skip to content

Commit add7e8e

Browse files
committed
refactor: enhance KolHeading component to support secondary headline and update snapshots
1 parent 9c8f0b7 commit add7e8e

File tree

8 files changed

+54
-32
lines changed

8 files changed

+54
-32
lines changed

packages/components/src/components/heading/__snapshots__/snapshot.spec.tsx.snap

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,22 @@ exports[`kol-heading should render with _label="Headline" _level=6 1`] = `
7777
</kol-heading>
7878
`;
7979

80+
exports[`kol-heading should render with _label="Headline" _secondaryHeadline="Subheadline" 1`] = `
81+
<kol-heading>
82+
<template shadowrootmode="open">
83+
<hgroup class="kol-heading-group">
84+
<strong class="kol-headline kol-headline--group kol-headline--primary kol-headline--strong">
85+
Headline
86+
<slot name="expert" slot="expert"></slot>
87+
</strong>
88+
<p class="kol-headline kol-headline--group kol-headline--secondary">
89+
Subheadline
90+
</p>
91+
</hgroup>
92+
</template>
93+
</kol-heading>
94+
`;
95+
8096
exports[`kol-heading should render with _label="Headline" 1`] = `
8197
<kol-heading>
8298
<template shadowrootmode="open">

packages/components/src/components/heading/component.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type { JSX } from '@stencil/core';
22
import { Component, h, Host, Prop, Watch } from '@stencil/core';
33

4+
import { BaseWebComponent } from '../../internal/functional-components/base-web-component';
45
import type { WebComponentInterface } from '../../internal/functional-components/generic-types';
5-
import { HeadingFC } from '../../internal/functional-components/heading/component';
66
import type { HeadingApi } from '../../internal/functional-components/heading/api';
7+
import { HeadingFC } from '../../internal/functional-components/heading/component';
78
import { HeadingController } from '../../internal/functional-components/heading/controller';
89
import type { HeadingLevel, LabelWithExpertSlotPropType } from '../../schema';
910

@@ -18,8 +19,8 @@ import type { HeadingLevel, LabelWithExpertSlotPropType } from '../../schema';
1819
},
1920
shadow: true,
2021
})
21-
export class KolHeading implements WebComponentInterface<HeadingApi> {
22-
private readonly ctrl: HeadingController = new HeadingController();
22+
export class KolHeading extends BaseWebComponent<HeadingApi> implements WebComponentInterface<HeadingApi> {
23+
private readonly ctrl: HeadingController = new HeadingController(this.setState, this.getState);
2324

2425
/**
2526
* Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
@@ -60,10 +61,13 @@ export class KolHeading implements WebComponentInterface<HeadingApi> {
6061
}
6162

6263
public render(): JSX.Element {
63-
const { label, level, secondaryHeadline } = this.ctrl.getProps();
6464
return (
6565
<Host>
66-
<HeadingFC label={label} level={level} secondaryHeadline={secondaryHeadline} />
66+
<HeadingFC
67+
label={this.ctrl.getRenderProp('label')}
68+
level={this.ctrl.getRenderProp('level')}
69+
secondaryHeadline={this.ctrl.getRenderProp('secondaryHeadline')}
70+
/>
6771
</Host>
6872
);
6973
}

packages/components/src/components/heading/snapshot.spec.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,9 @@ import { KolHeading } from './component';
77
executeSnapshotTests<HeadingProps>(
88
KolHeadingTag,
99
[KolHeading],
10-
[{ _label: 'Headline' }, ...[0, 1, 2, 3, 4, 5, 6].map((_level) => ({ _label: 'Headline', _level }) as HeadingProps)],
10+
[
11+
{ _label: 'Headline' },
12+
{ _label: 'Headline', _secondaryHeadline: 'Subheadline' },
13+
...[0, 1, 2, 3, 4, 5, 6].map((_level) => ({ _label: 'Headline', _level }) as HeadingProps),
14+
],
1115
);
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import type { LabelWithExpertSlotProp, LevelProp, SecondaryHeadlineProp } from '../../props';
2-
import type { ComponentApi } from '../generic-types';
1+
import { labelWithExpertSlotProp, levelProp, secondaryHeadlineProp } from '../../props';
2+
import type { ApiFromConfig, PropsConfigShape } from '../generic-types';
33

4-
export interface HeadingApi extends ComponentApi {
5-
Props: {
6-
Optional: LevelProp & SecondaryHeadlineProp;
7-
Required: LabelWithExpertSlotProp;
8-
};
9-
}
4+
export const headingPropsConfig = {
5+
optional: [levelProp, secondaryHeadlineProp],
6+
required: [labelWithExpertSlotProp],
7+
} as const satisfies PropsConfigShape;
8+
9+
export type HeadingApi = ApiFromConfig<typeof headingPropsConfig>;
Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
import type { HeadingLevel, LabelWithExpertSlotProp, LevelProp, SecondaryHeadlineProp } from '../../props';
2-
import { labelWithExpertSlotProp, levelProp, secondaryHeadlineProp, withValidPropValue } from '../../props';
1+
import { labelWithExpertSlotProp, levelProp, secondaryHeadlineProp } from '../../props';
32
import { BaseController } from '../base-controller';
4-
import type { ControllerInterface, ResolvedInputProps } from '../generic-types';
3+
import type { ControllerInterface, GetStateFn, ResolvedInputProps, SetStateFn } from '../generic-types';
54
import type { HeadingApi } from './api';
5+
import { headingPropsConfig } from './api';
66

77
export class HeadingController extends BaseController<HeadingApi> implements ControllerInterface<HeadingApi> {
8-
public constructor(states: HeadingApi['States'] = {}) {
9-
super(states, {
10-
label: '',
11-
level: 0 as HeadingLevel,
12-
secondaryHeadline: '',
13-
});
8+
public constructor(setState: SetStateFn<HeadingApi>, getState: GetStateFn<HeadingApi>) {
9+
super(headingPropsConfig, setState, getState);
1410
}
1511

1612
public componentWillLoad(props: ResolvedInputProps<HeadingApi>): void {
@@ -21,20 +17,20 @@ export class HeadingController extends BaseController<HeadingApi> implements Con
2117
}
2218

2319
public watchLabel(value?: string): void {
24-
withValidPropValue<LabelWithExpertSlotProp>(labelWithExpertSlotProp, value, (v) => {
25-
this.setProp('label', v);
20+
labelWithExpertSlotProp.apply(value, (v) => {
21+
this.setRenderProp('label', v);
2622
});
2723
}
2824

29-
public watchLevel(value?: HeadingLevel): void {
30-
withValidPropValue<LevelProp>(levelProp, value, (v) => {
31-
this.setProp('level', v);
25+
public watchLevel(value?: number): void {
26+
levelProp.apply(value, (v) => {
27+
this.setRenderProp('level', v);
3228
});
3329
}
3430

3531
public watchSecondaryHeadline(value?: string): void {
36-
withValidPropValue<SecondaryHeadlineProp>(secondaryHeadlineProp, value, (v) => {
37-
this.setProp('secondaryHeadline', v);
32+
secondaryHeadlineProp.apply(value, (v) => {
33+
this.setRenderProp('secondaryHeadline', v);
3834
});
3935
}
4036
}

packages/components/src/internal/props/label-with-expert-slot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ import { createPropDefinition } from './helpers/factory';
33
import { normalizeString } from './helpers/normalizers';
44

55
export type LabelWithExpertSlotProp = SimpleProp<'label', string>;
6-
export const labelWithExpertSlotProp = createPropDefinition<LabelWithExpertSlotProp>(normalizeString, () => true);
6+
export const labelWithExpertSlotProp = createPropDefinition<LabelWithExpertSlotProp>('label', '', normalizeString);

packages/components/src/internal/props/level.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export type HeadingLevel = (typeof headingLevelOptions)[number];
77

88
export type LevelProp = SimpleProp<'level', HeadingLevel>;
99
export const levelProp = createPropDefinition<LevelProp>(
10+
'level',
11+
0,
1012
(value) => normalizeInteger(value) as HeadingLevel,
1113
(v) => headingLevelOptions.includes(v),
1214
);

packages/components/src/internal/props/secondary-headline.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ import { createPropDefinition } from './helpers/factory';
33
import { normalizeString } from './helpers/normalizers';
44

55
export type SecondaryHeadlineProp = SimpleProp<'secondaryHeadline', string>;
6-
export const secondaryHeadlineProp = createPropDefinition<SecondaryHeadlineProp>(normalizeString, () => true);
6+
export const secondaryHeadlineProp = createPropDefinition<SecondaryHeadlineProp>('secondaryHeadline', '', normalizeString);

0 commit comments

Comments
 (0)