Currently, the UI shows a flat list of beverage names derived from the Brandset and Beverage Graph in the kOS System Application. Next, we’ll enhance this list by creating a dedicated Beverage component that displays additional information—such as availability for pouring, which is determined by factors like ingredient status and pump functionality.
Generating the Beverage Component
Use the kosui CLI to generate a new Beverage component within the model-components package:
kosui component beverage
? Which project should the component be created in? model-components
NX Generating @kosdev-code/kos-nx-plugin:kos-component
CREATE libs/model-components/src/components/beverage/beverage.tsx
CREATE libs/model-components/src/components/beverage/index.tsImplementing the Beverage Component
The Beverage component leverages data from the BeverageModel (which extends the AvailabilityModel) to render its UI. Any changes in availability—such as sold-out ingredients or pump issues—will automatically trigger a UI update because the component is wrapped in a kosComponent, which subscribes to kOS model changes.
Here’s the implementation:
// libs/model-components/src/components/beverage/beverage.tsx
import type { BeverageModel } from '@training-zero4/training-zero4-models';
interface Props {
beverage: BeverageModel;
}
export const Beverage: React.FunctionComponent<Props> = kosComponent(
({ beverage }) => {
return (
<BeverageContainer
onPointerDown={handleBeverageSelected} // Handler for user selection (defined elsewhere)
available={beverage.available}
selected={selected} // Passed as a prop or derived from state
primary={beverage.data.colors?.primary}
secondary={beverage.data.colors?.secondary}
>
<BeverageText>{beverage.note ?? 'No Name'}</BeverageText>
</BeverageContainer>
);
}
);
export default Beverage;Key Points:
- Automatic Re-rendering: Wrapping the component in kosComponent subscribes it to any mutations on the underlying kOS models.
- Data Binding: The component reflects properties like available and colors directly from the model, ensuring that any backend updates (e.g., changes in ingredient status) are immediately visible in the UI.
Styling The BeverageContainer
The BeverageContainer component applies styles based on the state of the BeverageModel. For example, it adjusts the background using the primary and secondary colors and adds a thick border when the beverage is selected.
// libs/model-components/src/components/beverage/beverage.tsx
const BeverageContainer = styled(BaseContainer)<{
available?: boolean;
selected?: boolean;
primary?: string;
secondary?: string;
}>`
height: 70px;
width: 400px;
font-size: 24px;
font-family: sans-serif;
border-radius: 20px;
color: #000000;
position: relative;
background: ${(props) => {
if (props.available) {
return `linear-gradient(135deg, ${props.primary ?? 'lightblue'}, ${
props.secondary ?? props.primary ?? 'white'
})`;
}
return `#cccccc`;
}};
border: ${(props) => (props.selected ? `10px solid black` : `margin: 10px`)};
`;Updating the Beverage List
Next, update the BeverageList component to utilize the new Beverage component. This ensures that each beverage is rendered with its enhanced visual details and availability state.
// libs/model-components/src/components/beverage-list/beverage-list.tsx
export const BeverageList: React.FunctionComponent<Props> = kosComponent(
({ beverages }) => {
const items = beverages?.map((beverage) => (
<Beverage beverage={beverage} key={beverage.id} />
));
return <BeverageListContainer>{items}</BeverageListContainer>;
}
);Availability Data Flow
A key question is how beverage availability is reflected in the UI. Here’s an overview:
Backend Changes:
When ingredients are inserted or removed, or when pump errors occur, the Beverage Graph is recalculated.
Event Propagation:
These changes trigger events (sent over websockets) that update the AvailabilityModel.
Reactive UI Updates:
Since the AvailabilityModel is managed by the CUI Kit and rendered by the Beverage component, any change in its available property automatically causes a re-render.
Automatic Subscription:
This behavior is enabled by the kosComponent wrapper, which subscribes the component to changes in any referenced model property. This allows the UI to update efficiently without manual intervention.
Current State and Next Steps
At this stage, the UI displays a list of beverages where the colors and name are derived from the UI schema document. Although the overall appearance hasn’t changed dramatically, you now have a robust foundation for styling beverages based on their dynamic state.

Up Next:
Next, we will cover how to implement beverage selection from the list, allowing users to interact with the UI and trigger backend state changes.
