At this point, the CUI Kit (via the Dispense SDK) is successfully displaying beverage data. The next step is to support the primary use case: letting the user select and pour a beverage from the list. The CUI Kit not only manages state but also provides the services and operations needed during beverage selection.
Adding a Selection Handler to the Beverage Component
We begin by enhancing the beverage component to support selection. First, add two new properties: one for handling beverage selection and one to reflect the current selected state. These properties will be passed down from the beverage list.
// libs/model-components/src/components/beverage/beverage.tsx
interface Props {
beverage: BeverageModel;
onBeverageSelected?(beverage: BeverageModel): void;
selected: boolean;
}Next, add a handler inside the component that gets triggered when the beverage is clicked or pressed. The selected state is passed into the styled component to reflect the UI change.
export const Beverage: React.FunctionComponent<Props> = kosComponent(
({ beverage, onBeverageSelected, selected }) => {
const handleBeverageSelected = useCallback(() => {
log.debug(`Beverage selected: ${beverage.rawId}`);
if (onBeverageSelected) {
onBeverageSelected(beverage);
}
}, [beverage]);
return (
<BeverageContainer
onPointerDown={handleBeverageSelected}
selected={selected}
available={beverage.available}
>
<BeverageText>{beverage.note ?? 'No Name'}</BeverageText>
</BeverageContainer>
);
}
);Then, update the styled component to use the selected state. In this example, when a beverage is selected, it gets a thick black border; otherwise, it maintains a margin.
const BeverageContainer = styled(BaseContainer)<{
available?: boolean;
selected?: boolean;
}>`
/* Other styles here... */
${({ selected }) =>
selected ? `border: 10px solid black;` : `margin: 10px;`}
`;Passing Selection State from the Beverage List
Now, update the BeverageList component to pass the selection handler and the selected beverage state down to each individual Beverage component. First, extend the props for BeverageList:
// libs/model-components/src/components/beverage-list/beverage-list.tsx
interface Props {
beverages?: BeverageModel[];
onBeverageSelected?(beverage: BeverageModel): void;
selectedModel?: BeverageModel;
}Then, map through the beverage models and render a Beverage for each, setting the selected prop based on whether the current beverage matches the selected model:
export const BeverageList: React.FunctionComponent<Props> = kosComponent(
({ beverages, onBeverageSelected, selectedModel }) => {
const items = beverages?.map((beverage) => (
<Beverage
key={beverage.id}
beverage={beverage}
onBeverageSelected={onBeverageSelected}
selected={selectedModel === beverage}
/>
));
return <BeverageListContainer>{items}</BeverageListContainer>;
}
);Integrating the Selection Handlers from the CUI Kit
Finally, update the NozzleView to pass down the selection handler and the currently selected beverage from the CUI Kit. This ensures that the beverage list is fully integrated with the state managed by the CUI Kit.
const NozzleView = kosComponent(() => {
// ... (other code)
return (
<NozzleContainer>
{showBeverages ? (
<>
<BeverageList
// The CUI Kit provides a beverage selection handler
onBeverageSelected={beverages.handlers.onSelected}
// The CUI Kit maintains the current selections for Brands, Beverages, and Flavors
selectedModel={selections[DISPENSE_GROUP_BEVERAGE]}
beverages={beverages.models}
/>
<div>
{/* Display the name of the selected beverage */}
<h1>
{selections[DISPENSE_GROUP_BEVERAGE]?.note ?? 'Not Selected'}
</h1>
</div>
</>
) : (
<div>
<h1>{nav.currentGroup}</h1>
</div>
)}
</NozzleContainer>
);
});Data Flow Overview
The CUI Kit and the underlying AvailabilityModel (e.g., Zero4Beverage) remain the single source of truth for the UI state. Handlers provided by the CUI Kit ensure controlled modifications to the state machine. When events occur (such as a user clicking on a beverage), the CUI Kit’s handlers update the corresponding Availability or Nozzle models from the Dispense SDK. These changes can trigger services in the kOS application, and any resulting state changes propagate back to the CUI Kit and UI, causing a re-render.

Current State
The final result is a fully integrated beverage selection experience. When you click on a beverage, it becomes highlighted, and its name is displayed at the bottom of the screen.

This implementation demonstrates how to extend the capabilities of the CUI Kit to handle user interactions for beverage selection and pouring while maintaining a clean, decoupled architecture for state management.
