Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/pos-list-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/ui-extensions': minor
---

Add the `s-pos-list` web component for structured, incrementally loaded POS lists.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"Modal",
"NumberField",
"POSBlock",
"POSList",
"Page",
"PosBlock",
"Route",
Expand Down Expand Up @@ -137,6 +138,7 @@
"Modal",
"NumberField",
"POSBlock",
"POSList",
"Page",
"PosBlock",
"Route",
Expand Down Expand Up @@ -257,6 +259,7 @@
"Modal",
"NumberField",
"POSBlock",
"POSList",
"Page",
"PosBlock",
"Route",
Expand Down Expand Up @@ -379,6 +382,7 @@
"Modal",
"NumberField",
"POSBlock",
"POSList",
"Page",
"PosBlock",
"Route",
Expand Down Expand Up @@ -501,6 +505,7 @@
"Modal",
"NumberField",
"POSBlock",
"POSList",
"Page",
"PosBlock",
"Route",
Expand Down Expand Up @@ -623,6 +628,7 @@
"Modal",
"NumberField",
"POSBlock",
"POSList",
"Page",
"PosBlock",
"Route",
Expand Down Expand Up @@ -745,6 +751,7 @@
"Modal",
"NumberField",
"POSBlock",
"POSList",
"Page",
"PosBlock",
"Route",
Expand Down Expand Up @@ -827,6 +834,7 @@
"Modal",
"NumberField",
"POSBlock",
"POSList",
"Page",
"PosBlock",
"Route",
Expand Down Expand Up @@ -1644,6 +1652,18 @@
"pos.register-details.block.render"
]
},
"POSList": {
"targets": [
"pos.cart.line-item-details.action.render",
"pos.customer-details.action.render",
"pos.draft-order-details.action.render",
"pos.home.modal.render",
"pos.order-details.action.render",
"pos.product-details.action.render",
"pos.purchase.post.action.render",
"pos.register-details.action.render"
]
},
"Page": {
"targets": [
"pos.cart.line-item-details.action.render",
Expand Down
200 changes: 200 additions & 0 deletions packages/ui-extensions/src/surfaces/point-of-sale/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5416,6 +5416,144 @@ declare module 'preact' {
}
}

declare const posListTagName = 's-pos-list';
type POSListImageDisplayStrategy = 'auto' | 'always' | 'never';
type POSListRowSubtitleColor =
| 'neutral'
| 'subdued'
| 'disabled'
| 'warning'
| 'critical'
| 'success'
| 'interactive'
| 'highlight';
type POSListRowSubtitle =
| string
| {
/** The subtitle text. */
content: string;
/**
* The semantic color applied to the subtitle.
*
* @default 'neutral'
*/
color?: POSListRowSubtitleColor;
};
type POSListBadge = {
/** The badge text. */
text: string;
/**
* The semantic appearance of the badge.
*
* @default 'neutral'
*/
tone?: 'neutral' | 'critical' | 'warning' | 'success' | 'highlight';
};
type POSListRowImage = {
/** The URL of the image displayed at the start of the row. */
src?: string;
/** A numeric badge displayed over the image. */
badge?: number;
};
type POSListToggleSwitch = {
/**
* The current state of the toggle switch.
*
* @default false
*/
checked?: boolean;
/**
* Whether the toggle switch prevents interaction.
*
* @default false
*/
disabled?: boolean;
};
type POSListRowStart = {
/** The primary text for the row. */
label: string;
/** Up to three lines of supporting text displayed below the label. */
subtitles?: [POSListRowSubtitle, POSListRowSubtitle?, POSListRowSubtitle?];
/** Status or category badges displayed with the row content. */
badges?: POSListBadge[];
/** The image displayed at the start of the row. */
image?: POSListRowImage;
};
type POSListRowEnd = {
/** Supporting text displayed at the end of the row. */
label?: string;
/**
* Whether to display a chevron at the end of the row.
*
* @default false
*/
showChevron?: boolean;
/** A toggle switch displayed at the end of the row. */
toggleSwitch?: POSListToggleSwitch;
};
type POSListRow = {
/** A unique identifier for the row. */
id: string;
/** The primary content displayed at the start of the row. */
start: POSListRowStart;
/**
* Callback invoked when the row is activated.
*
* When provided, the row is interactive.
*/
onClick?: (event: CallbackEvent<typeof posListTagName>) => void;
/** Optional content displayed at the end of the row. */
end?: POSListRowEnd;
};
/**
* Displays structured rows with text, badges, images, and optional trailing content.
*
* @publicDocs
*/
interface POSListJSXProps {
/** A unique identifier for the element. */
id?: string;
/**
* The rows displayed in the list.
*
* @default []
*/
rows?: POSListRow[];
/**
* Controls whether rows reserve space for images.
*
* - `auto`: Displays images or placeholders when a row includes an image source.
* - `always`: Displays images or placeholders for every row.
* - `never`: Displays rows without images or image placeholders.
*
* @default 'auto'
*/
imageDisplayStrategy?: POSListImageDisplayStrategy;
/**
* Whether additional rows are being loaded.
*
* @default false
*/
loadingMore?: boolean;
/** Callback when more rows should be loaded. */
onLoadMore?: ((event: CallbackEvent<typeof posListTagName>) => void) | null;
/** Content displayed before the rows as part of the list's scrollable content. */
header?: ComponentChild;
}
type POSListElementProps = Omit<POSListJSXProps, 'header'>;
declare global {
interface HTMLElementTagNameMap {
[posListTagName]: HtmlElementTagNameProps<POSListElementProps>;
}
}
declare module 'preact' {
namespace createElement.JSX {
interface IntrinsicElements {
[posListTagName]: IntrinsicElementProps<POSListElementProps>;
}
}
}

export type {
BadgeJSXProps,
BannerJSXProps,
Expand All @@ -5438,6 +5576,7 @@ export type {
ModalJSXProps,
NumberFieldJSXProps,
PageJSXProps,
POSListJSXProps,
PosBlockJSXProps,
QrCodeJSXProps,
ScrollBoxJSXProps,
Expand All @@ -5458,6 +5597,52 @@ export type {
TimePickerJSXProps,
};

/**
* Events emitted by the POS list.
* @publicDocs
*/
interface POSListEvents {
/** Fired when more rows should be loaded. */
loadmore?: (event: CallbackEvent<typeof posListTagName>) => void;
}

/**
* Content slots for the POS list.
* @publicDocs
*/
interface POSListSlots {
/** Content displayed before the rows as part of the list's scrollable content. */
header?: HTMLElement;
}

/**
* Displays structured rows with text, badges, images, and optional trailing content.
* @publicDocs
*/
interface POSList {
/** A unique identifier for the element. */
id?: string;
/**
* The rows displayed in the list.
* @default []
*/
rows?: POSListRow[];
/**
* Controls whether rows reserve space for images.
*
* - `auto`: Displays images or placeholders when a row includes an image source.
* - `always`: Displays images or placeholders for every row.
* - `never`: Displays rows without images or image placeholders.
* @default 'auto'
*/
imageDisplayStrategy?: POSListImageDisplayStrategy;
/**
* Whether additional rows are being loaded.
* @default false
*/
loadingMore?: boolean;
}

/**
* The link component provides event callbacks for handling user interactions. Learn more about [handling events](/docs/api/polaris/using-polaris-web-components#handling-events).
* @publicDocs
Expand Down Expand Up @@ -7771,3 +7956,18 @@ declare global {
}
}
}

declare module 'react' {
namespace JSX {
interface IntrinsicElements {
[posListTagName]: IntrinsicElementProps<POSListElementProps>;
}
}
}
declare global {
namespace JSX {
interface IntrinsicElements {
[posListTagName]: IntrinsicElementProps<POSListElementProps>;
}
}
}
Loading
Loading