Jetpack Compose Style UI for JavaScript
Build beautiful Android-inspired user interfaces with a declarative, composable API. No HTML required.
Layouts
Container components for organizing your UI elements with flexible positioning and sizing.
A layout that arranges its children in a single row or column. The default orientation is vertical.
| Property | Type | Default | Description |
|---|---|---|---|
| orientation | string | 'vertical' | Direction of child arrangement
'vertical'
'horizontal'
|
| gravity | string | undefined | Alignment of children
'center'
'start'
'end'
'center_horizontal'
'center_vertical'
'space_between'
'space_around'
'space_evenly'
|
| width | string | number | undefined | Width of the layout
'match_parent'
'wrap_content'
number (px)
|
| height | string | number | undefined | Height of the layout (same values as width) |
| gap | number | 0 | Space between children (in pixels) |
| padding | number | object | undefined | Inner spacing. Object: { top, right, bottom, left, horizontal, vertical, all } |
| margin | number | undefined | Outer spacing (in pixels) |
| background | string | undefined | CSS background value |
| wrap | boolean | false | Enable flex-wrap for children |
const { LinearLayout, Column, Row, mount } = AndroidLayouts; const { TextView, MaterialButton } = AndroidComponents; // Vertical LinearLayout const layout = LinearLayout({ orientation: 'vertical', width: 'match_parent', padding: 16, gap: 12, gravity: 'center_horizontal' }, [ TextView({ text: 'Hello World', textSize: 24 }), MaterialButton({ text: 'Click Me' }) ]); mount(layout, 'app');
Shorthand functions for vertical and horizontal LinearLayout. Same properties as LinearLayout.
const { Column, Row } = AndroidLayouts; const { TextView, Icon } = AndroidComponents; // Compose-style nesting const card = Column({ padding: 16, gap: 8 }, [ Row({ gravity: 'center_vertical', gap: 12 }, [ Icon({ name: 'bx bx-user', size: 24 }), TextView({ text: 'John Doe', textStyle: 'bold' }) ]), TextView({ text: 'Software Engineer', textColor: '#888' }) ]);
A layout that arranges children in a grid of rows and columns.
| Property | Type | Default | Description |
|---|---|---|---|
| columns | number | 2 | Number of columns |
| rows | number | undefined | Number of rows (optional) |
| gap | number | 0 | Gap between items |
| columnGap | number | undefined | Gap between columns |
| rowGap | number | undefined | Gap between rows |
| autoFlow | string | 'row' | Grid auto flow
'row'
'column'
'dense'
|
const { GridLayout, GridParams } = AndroidLayouts; const { Card, TextView } = AndroidComponents; const grid = GridLayout({ columns: 3, gap: 16, padding: 16 }, [ // Regular item (1 column) Card({}, [TextView({ text: 'Item 1' })]), // Span 2 columns GridParams({ columnSpan: 2 }, Card({}, [TextView({ text: 'Wide Item' })]) ), // Span 2 rows GridParams({ rowSpan: 2 }, Card({}, [TextView({ text: 'Tall Item' })]) ) ]);
A layout that positions children using constraints. Children are positioned absolutely relative to the container.
| Constraint Property | Type | Description |
|---|---|---|
| top, right, bottom, left | number | Distance from parent edge |
| centerHorizontally | boolean | Center child horizontally |
| centerVertically | boolean | Center child vertically |
| width, height | string | number | Size. Use 'match_constraint' to fill between constraints |
const { ConstraintLayout, Constrained } = AndroidLayouts; const { MaterialButton, TextView } = AndroidComponents; const layout = ConstraintLayout({ width: 'match_parent', height: 300 }, [ // Centered title Constrained({ centerHorizontally: true, top: 20 }, TextView({ text: 'Welcome', textSize: 32 }) ), // Button pinned to bottom-right Constrained({ bottom: 16, right: 16 }, MaterialButton({ text: 'Continue' }) ) ]);
A layout for stacking children on top of each other. Use Positioned to place children.
| Position Property | Values | Description |
|---|---|---|
| gravity |
'center'
'top'
'bottom'
'left'
'right'
'top_left'
'top_right'
'bottom_left'
'bottom_right'
|
Position preset for child |
| zIndex | number | Stack order of child |
const { FrameLayout, Positioned } = AndroidLayouts; const { Avatar, Icon } = AndroidComponents; const profilePic = FrameLayout({ width: 80, height: 80 }, [ // Avatar in center Positioned({ gravity: 'center' }, Avatar({ size: 64, text: 'JD' }) ), // Status indicator in bottom-right Positioned({ gravity: 'bottom_right', zIndex: 1 }, Icon({ name: 'bx bxs-circle', size: 16, color: '#3fb950' }) ) ]);
A scrollable container. Also available as EnhancedScrollView with infinite scroll support.
| Property | Type | Default | Description |
|---|---|---|---|
| orientation | string | 'vertical' | Scroll direction: 'vertical' | 'horizontal' |
Methods
Components
Material Design 3 UI components for building interactive interfaces.
A component for displaying text with various styling options.
| Property | Type | Default | Description |
|---|---|---|---|
| text | string | '' | Text content to display |
| textSize | number | 14 | Font size in pixels |
| textColor | string | --md-on-surface | Text color (CSS color value) |
| textStyle | string | 'normal' | Font style
'normal'
'bold'
'italic'
|
| gravity | string | undefined | Text alignment: 'center' | 'end' | 'right' |
| maxLines | number | undefined | Maximum lines before truncation |
| ellipsize | boolean | false | Show ellipsis for overflow |
const { TextView } = AndroidComponents; const title = TextView({ text: 'Welcome Back!', textSize: 32, textStyle: 'bold', textColor: '#6750a4', gravity: 'center' }); // Update text programmatically title.setText('Hello, John!');
A Material Design text input field with floating label and validation.
| Property | Type | Default | Description |
|---|---|---|---|
| label | string | 'Label' | Floating label text |
| type | string | 'text' | Input type
'text'
'password'
'email'
'number'
'tel'
'url'
'textarea'
|
| value | string | '' | Initial value |
| helperText | string | '' | Helper text below input |
| leadingIcon | string | null | Icon class (e.g., 'bx bx-user') |
| maxLength | number | null | Maximum character length |
| showCounter | boolean | false | Show character counter |
| required | boolean | false | Mark as required field |
| passwordToggle | boolean | true | Show/hide password toggle |
Methods
const { MaterialInput } = AndroidComponents; const emailInput = MaterialInput({ label: 'Email Address', type: 'email', leadingIcon: 'bx bx-envelope', helperText: 'We will never share your email', required: true, onInput: (value) => console.log(value), onBlur: (value) => { if (!value.includes('@')) { emailInput.setError('Invalid email format'); } else { emailInput.setSuccess('Looks good!'); } } });
A Material Design toggle switch component.
| Property | Type | Default | Description |
|---|---|---|---|
| checked | boolean | false | Initial checked state |
| label | string | '' | Label text |
| labelPosition | string | 'right' | Label position: 'left' | 'right' |
| showIcon | boolean | true | Show check icon when on |
| disabled | boolean | false | Disable switch |
| onChange | function | undefined | Callback when toggled (receives boolean) |
const { MaterialSwitch } = AndroidComponents; const darkModeSwitch = MaterialSwitch({ label: 'Dark Mode', checked: false, onChange: (isChecked) => { document.documentElement.classList.toggle('dark', isChecked); } });
A Material Design card container with elevation and styling options.
| Property | Type | Default | Description |
|---|---|---|---|
| variant | string | 'elevated' | Card style
'elevated'
'filled'
'outlined'
|
| elevation | number | 1 | Shadow depth (1-5) |
| cornerRadius | number | 12 | Border radius in pixels |
| onClick | function | undefined | Makes card clickable |
const { Card, TextView, Avatar } = AndroidComponents; const { Row, Column } = AndroidLayouts; const userCard = Card({ variant: 'outlined', padding: 16, onClick: () => showProfile() }, [ Row({ gap: 16, gravity: 'center_vertical' }, [ Avatar({ text: 'JD', size: 48 }), Column({ gap: 4 }, [ TextView({ text: 'John Doe', textStyle: 'bold' }), TextView({ text: '@johndoe', textSize: 12 }) ]) ]) ]);
An efficient list/grid component with view recycling, infinite scroll, and empty/loading states.
| Property | Type | Default | Description |
|---|---|---|---|
| data | array | [] | Array of data items |
| adapter | function | null | Function (item, index) => component |
| layoutManager | string | 'linear' | Layout type: 'linear' | 'grid' |
| gridColumns | number | 2 | Columns when using grid layout |
| divider | boolean | false | Show dividers between items |
| onLoadMore | function | null | Async function for infinite scroll |
| emptyText | string | 'No items' | Text shown when empty |
| emptyIcon | string | 'bx bx-inbox' | Icon shown when empty |
const { RecyclerView, Card, TextView } = AndroidComponents; const { Row } = AndroidLayouts; const userList = RecyclerView({ data: users, height: 400, divider: true, emptyText: 'No users found', // Adapter renders each item adapter: (user, index) => Card({ padding: 12 }, [ Row({ gap: 12 }, [ Avatar({ text: user.name }), TextView({ text: user.name }) ]) ]), // Infinite scroll onLoadMore: async (offset) => { const moreUsers = await fetchUsers(offset); return { data: moreUsers, hasMore: moreUsers.length > 0 }; } });
Overlays
Modal dialogs and notification components.
A Material Design dialog with builder pattern. Supports alert, confirm, prompt, and custom content.
Builder Methods
Static Helpers
const { MaterialDialog } = AndroidComponents; // Simple alert MaterialDialog.alert('Success', 'Your changes have been saved!'); // Confirmation dialog MaterialDialog.confirm('Delete Item', 'This action cannot be undone.', { confirmText: 'Delete', confirmStyle: 'filled', confirmError: true, onConfirm: () => deleteItem() }); // Prompt dialog MaterialDialog.prompt('Rename', 'Enter a new name:', { placeholder: 'New name', defaultValue: 'Document', onConfirm: (value) => rename(value) }); // Builder pattern with custom content MaterialDialog({ icon: 'bx bx-cog' }) .setTitle('Settings') .setView(settingsForm) .setNegativeButton('Cancel') .setPositiveButton('Save', saveSettings, { style: 'filled' }) .show();
A brief message that appears at the bottom of the screen with optional action.
| Property | Type | Default | Description |
|---|---|---|---|
| message | string | '' | Message text |
| duration | number | 4000 | Display time in ms (0 = infinite) |
| position | string | 'bottom' | Position: 'bottom' | 'top' |
| type | string | 'default' | Style: 'default' | 'error' | 'success' |
| action | object | null | { text, onClick } |
| showClose | boolean | false | Show close button |
| icon | string | null | Leading icon class |
Static Helpers
const { Snackbar } = AndroidComponents; // Simple message Snackbar.show('Item added to cart'); // Success notification Snackbar.success('Changes saved successfully!'); // Error notification Snackbar.error('Failed to connect to server'); // With action button Snackbar({ message: 'Email archived', action: { text: 'Undo', onClick: () => undoArchive() }, duration: 6000, showClose: true }).show();