Skip to content

refactor: mark decorated slots with Slot & DefaultSlot types#12969

Merged
ilhan007 merged 20 commits intomainfrom
chore-jsxSlot
Feb 5, 2026
Merged

refactor: mark decorated slots with Slot & DefaultSlot types#12969
ilhan007 merged 20 commits intomainfrom
chore-jsxSlot

Conversation

@ilhan007
Copy link
Contributor

@ilhan007 ilhan007 commented Jan 27, 2026

Background

Creates unique symbols and marks all slots of all web components so they can be extracted in TS environment.
The specific benefit is for the suggestion and autocompletion of the slots in Vue templates, but same applies in general to other templates supporting Typescript.

Currently all classes have the system _jsxProps and it includes all class members, including slots, but it's not possible to distinguish slots from properties - they are all just class members.

Wrapping the current slot types with Slot and DefaultSlot will mark the slots, so that they can be extracted from _jsxPprops.

// Create a unique symbol as a marker
declare const SlotMarker: unique symbol;
declare const DefaultSlotMarker: unique symbol;

export type Slot<T> = T & { [SlotMarker]: true };
export type DefaultSlot<T> = T & { [DefaultSlotMarker]: true };

Changes in Components

Note: the change is compatible, the old syntax is deprecated, but still supported.

In Short

// If you previously used the `slot` decorator:
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";

// Now use `slot-strict` decorator + `DefaultSlot` and `Slot` types for slot members:
import slot from "@ui5/webcomponents-base/dist/decorators/slot-strict.js";
import type { DefaultSlot, Slot } from "@ui5/webcomponents-base/dist/UI5Element.js";

class MyComponent extends UI5Element {
  @slot()
  header!: Slot<T> // Array<T> -> Slot<T>

  @slot({ type: HTMLElement, default: true })
  items!: DefaultSlot<T>; // Array<T> -> DefaultSlot<T>
}

In Detail

In the components we need to make the following change:

  • Before: current named and default slots are declared like (slot decorator and Array):
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";

@slot()
header!: Array<HTMLElement>;

@slot({
	type: HTMLElement,
	"default": true,
	invalidateOnChildChange: true,
})
items!: Array<ListItemBase | ListItemGroup>;
  • After: start using the new slot-strict decorator + Slot and DefaultSlot types
import slot from "@ui5/webcomponents-base/dist/decorators/slot-strict.js";
import type { DefaultSlot, Slot } from "@ui5/webcomponents-base/dist/UI5Element.js";

@slot()
header!: Slot<HTMLElement>;

@slot({
	type: HTMLElement,
	"default": true,
	invalidateOnChildChange: true,
})
items!: DefaultSlot<ListItemBase | ListItemGroup>;

What This Enables?

This makes slots discoverable,
for example the following code extracts an union of the component slot names:

type ExtractSlots<T> = {
        [K in keyof T]: IsDefaultSlot<NonNullable<T[K]>> extends true 
	? "default"
	: IsSlot<NonNullable<T[K]>> extends true 
		? K
 		: never
 [keyof T];

// union of the slot names ("header" | "footer" | "default")
type DialogSlots = Exclude<ExtractSlots<Dialog>, undefined>; 

let a: DialogSlots;

 a = "footer" // ok
 a = "default" // ok
 a = "header"  // ok
 a = "wrong" // error

and in real case scenario helps to get the correct slot suggestions:

Screenshot 2026-02-06 at 10 40 58

@ui5-webcomponents-bot
Copy link
Collaborator

ui5-webcomponents-bot commented Jan 27, 2026

🧹 Preview deployment cleaned up: https://pr-12969--ui5-webcomponents.netlify.app

@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 27, 2026 13:46 Inactive
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 27, 2026 14:19 Inactive
@nnaydenow
Copy link
Contributor

nnaydenow commented Jan 27, 2026

Something to discuss:

  • Slots are always arrays. Can we remove Array from types?
    From:
items!: DefaultSlot<Array<ListItemBase | ListItemGroup>>

To

items!: DefaultSlot<ListItemBase | ListItemGroup>
  • Can we remove the ! from all slot declaration somehow because slots are always defined with empty array?

@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 27, 2026 17:00 Inactive
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 28, 2026 09:43 Inactive
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 29, 2026 10:10 Inactive
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 29, 2026 13:45 Inactive
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 29, 2026 16:16 Inactive
@ilhan007 ilhan007 changed the title refactor: mark decorated slots with Slot, DefaultSlot types refactor: mark decorated slots with Slo, DefaultSlot types Feb 4, 2026
@ilhan007 ilhan007 changed the title refactor: mark decorated slots with Slo, DefaultSlot types refactor: mark decorated slots with **Slot** & **DefaultSlot** types Feb 4, 2026
@ilhan007 ilhan007 changed the title refactor: mark decorated slots with **Slot** & **DefaultSlot** types refactor: mark decorated slots with Slot & DefaultSlot types Feb 4, 2026
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview February 4, 2026 10:51 Inactive
@ilhan007 ilhan007 requested a review from pskelin February 4, 2026 13:52
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview February 4, 2026 14:07 Inactive
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview February 4, 2026 15:18 Inactive
@ilhan007 ilhan007 merged commit b5cfd36 into main Feb 5, 2026
20 of 21 checks passed
@ilhan007 ilhan007 deleted the chore-jsxSlot branch February 5, 2026 09:41
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview February 5, 2026 09:41 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants