| name | page |
| description | Guide for creating page components. This skill should be used when users want to create a new page component (or update an existing page component) |
File structure
Each page lives in its own folder under src/pages/[name]/ and typically includes:
[name]-page.ts- page component[name]-page.stories.ts- Storybook story (imports./[name]-page.js)
It can also include other assets like styles, sub-components, etc.
The page name and custom element tag should be kebab-case (e.g., user-profile).
Page component
- Extend
LitElement(orwithStore(LitElement)when using store bindings) and register viacustomElements.define('my-page', MyPage). - Define styles in
static stylesand always includeBSHelpersCSSin the array. - Define reactive properties with
static properties: PropertyDeclarations, thendeclareeach field.- Use
attribute: falsefor non-primitive or store-backed properties. - Initialize defaults in the constructor when needed.
- Use
Linking properties to app state
- Use the
storeproperty insidePropertyDeclarationsto link to a ReatomAtom. - Wrap the class with
withStorefromlit-reatom. - Keep state props typed (e.g.,
declare appSession: ReturnType<typeof appSessionAtom>).
Tasks (DOM events)
- Use DOM events to trigger service logic via
helpers/domTask.ts. - Declare task params/returns in
src/setup/tasks.ts(TaskEventRegistry). - Register handlers in
src/setup/services.tsusingregisterTaskHandler. - Dispatch tasks from components via
dispatchTask(this, 'task-name', params)
Configure routing
- Register the page route in
src/main.tsas a children of the app route. - Add a
ui5-side-navigation-iteminsrc/pages/app-shell/app-shell-page.tsfor navigation.
Example:
import { LitElement, html, css, PropertyDeclarations } from 'lit'
import { withStore } from 'lit-reatom'
import { BSHelpersCSS } from 'helpers/bootstrapCSS'
import { dispatchTask } from 'helpers/domTask'
import { myDataAtom, MyData } from 'stores/myData'
export class MyComponent extends withStore(LitElement) {
static properties: PropertyDeclarations = {
title: {},
myData: { attribute: false, store: myDataAtom },
}
declare title?: string
declare myData: MyData
constructor() {
super()
this.title = 'My Component'
}
loadData() {
dispatchTask(this, 'load-data', { id: 1 })
}
render() {
return html`<div class="container">
${this.title ? html`<p>${this.title}</p>` : ''}
<div>
<p>Data ID: ${this.myData?.id}</p>
<p>Data Name: ${this.myData?.name}</p>
</div>
<button class="btn btn-primary" @click=${this.loadData}>Load data</button>
</div> `
}
static styles = [
BSHelpersCSS,
css`
/* component styles */
`,
]
}
customElements.define('my-component', MyComponent)
Storybook story
Keep stories simple and use the Components/<PageName> naming pattern from existing pages.
Example:
import './my-page.js'
export default {
title: 'Components/MyPage',
component: 'my-page',
parameters: {
actions: {
handles: [],
},
},
args: {},
}
export const Default = { args: {} }