ConnectIQComponents: reusable UI components for Garmin
I built a UI library in Monkey C for Garmin Connect IQ, extracting reusable elements from my watch apps. The library is used in TeaStop and Knitting Counter Pro, with shared components and a customizable theme.
- Garmin
- Connect IQ
- Monkey C
- Open source
8 components, one theme
I was repeating code for drawing buttons, cards and indicators in Knitting Counter Pro and TeaStop. I moved these elements into a separate repository called ConnectIQComponents. Version 0.2.0 includes:
- Button / OutlineButton
- Filled or outlined button with an onPress callback.
- Panel / Label
- Rounded surface and text truncated to fit the available width.
- Badge / Divider
- Text badge and a horizontal or vertical separator.
- ProgressBar / ProgressRing
- Progress from 0 to 1, displayed as a bar or segmented ring.
Each component accepts a position, dimensions, visibility and local styles. The theme defines colors, fonts, spacing and corner radius. Components do not depend on application data or storage.
React inspired props and composition
I pass props in a Monkey C dictionary. The add(child) method nests child components, while setProps() updates their content and appearance. Individual components can override the shared theme using :style props.
var theme = new ConnectIQComponents.Theme({
:accent => 0xB3DFAC
});
var button = new ConnectIQComponents.Button({
:text => "Brew tea",
:x => 80, :y => 220,
:width => 200, :height => 50,
:style => {:radius => 25},
:onPress => method(:startBrewing)
}, theme);
// In the view’s onUpdate(dc):
button.draw(dc, 0, 0);
// After updating application state:
button.setProps({:text => "Done"});
WatchUi.requestUpdate();startBrewing is an application method. Touch input is forwarded through press() or the ComponentDelegate adapter. Rendering uses Garmin Graphics and WatchUi, and I explicitly request a redraw after state changes. Layout dimensions are in pixels, so the application is responsible for adapting to each screen.
What changed in TeaStop
I added the library as a Git submodule pinned to v0.2.0. The adapter TeaComponents.mc maps TeaStop colors to the library theme and reuses component instances during rendering.
- The “+ Add”, “Brew tea”, “Options” and time adjustment buttons use Button or OutlineButton.
- Tea list cards use Panel, and the name editor separator uses Divider.
- The segmented brewing indicator uses ProgressRing.
TeaStop delegates still handle actions and touch hit testing. Timers, alarms and session storage remain in the app. The integration changes the drawing layer.
Integration checks
Builds passed for Venu 3, fēnix 7S, Venu Sq 2 and Forerunner 965. All 9 simulator tests passed, covering 7 application regression tests and 2 UI adapter tests. I also checked that TeaStop launches in the Venu 3 simulator. Testing on physical watches is still pending.
Using it in another project
The repository is public and licensed under MIT. You can include the source files or build a Monkey Barrel package. For source integration, I add the repository as a submodule, pin a tag and extend monkey.jungle:
base.sourcePath = source;vendor/ConnectIQComponents/sourceThe library includes documentation, an example app and tests. The API is still experimental, so I pin a specific version and update the dependency deliberately.