
Konsta Ui
- 500 installs
- 57 repo stars
- Updated July 13, 2026
- cap-go/capgo-skills
konsta-ui is a Capgo agent skill that teaches Konsta UI Tailwind components for Capacitor apps so developers can ship polished mobile-first interfaces with native iOS and Android feel without custom platform styling.
About
konsta-ui is a cap-go/capgo-skills agent skill for building polished mobile-first interfaces inside Capacitor hybrid apps using Konsta UI components styled with Tailwind CSS. Konsta UI provides iOS and Android adaptive components—lists, sheets, toggles, and navigation patterns—that inherit platform-appropriate appearance without maintaining separate Swift, Kotlin, or bespoke CSS theme files. Developers reach for konsta-ui when scaffolding Capacitor screens, replacing generic web UI with touch-native patterns, or aligning Capgo mobile releases with App Store and Play Store UX expectations. The skill fits teams already using Capacitor and Tailwind who want consistent cross-platform mobile UI faster than hand-rolling platform-specific styles.
- Konsta UI component selection
- Tailwind mobile styling patterns
- iOS and Android visual parity
- Capacitor page layout recipes
- Accessible touch-first patterns
Konsta Ui by the numbers
- 500 all-time installs (skills.sh)
- Ranked #594 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cap-go/capgo-skills --skill konsta-uiAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 500 |
|---|---|
| repo stars | ★ 57 |
| Last updated | July 13, 2026 |
| Repository | cap-go/capgo-skills ↗ |
How do you build native-feeling Capacitor UI with Tailwind?
Build polished mobile-first interfaces in Capacitor apps using Konsta UI Tailwind components that feel native on iOS and Android without bespoke platform styling.
Who is it for?
Developers building Capacitor hybrid apps who want Konsta UI Tailwind components instead of hand-written platform-specific mobile CSS.
Skip if: Teams building fully native Swift or Kotlin apps without Capacitor should skip konsta-ui in favor of platform-native UI frameworks.
When should I use this skill?
User builds Capacitor mobile UI, mentions Konsta UI, or needs iOS and Android adaptive Tailwind components in a hybrid app.
What you get
Capacitor app screens composed of Konsta UI Tailwind components with iOS and Android adaptive styling
- Konsta UI component screens
- Cross-platform mobile layouts
Files
Konsta UI Design Guide
Build pixel-perfect iOS and Material Design apps with Konsta UI.
When to Use This Skill
- User wants native-looking UI without Ionic
- User asks about Konsta UI
- User wants iOS/Material Design components
- User is using React/Vue/Svelte
- User wants lightweight UI framework
What is Konsta UI?
Konsta UI provides:
- Pixel-perfect iOS and Material Design components
- Works with React, Vue, and Svelte
- Tailwind CSS integration
- ~40 mobile-optimized components
- Small bundle size (~30KB gzipped)
Getting Started
Installation
# React
npm install konsta
# Vue
npm install konsta
# Svelte
npm install konsta
# Required: Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -pTailwind Configuration
// tailwind.config.js
const konstaConfig = require('konsta/config');
module.exports = konstaConfig({
content: [
'./src/**/*.{js,ts,jsx,tsx,vue,svelte}',
],
// Extend or override Konsta config
theme: {
extend: {},
},
});Setup (React)
// App.tsx
import { App, Page, Navbar, Block } from 'konsta/react';
export default function MyApp() {
return (
<App theme="ios"> {/* or theme="material" */}
<Page>
<Navbar title="My App" />
<Block>
<p>Hello Konsta UI!</p>
</Block>
</Page>
</App>
);
}Setup (Vue)
<!-- App.vue -->
<template>
<k-app theme="ios">
<k-page>
<k-navbar title="My App" />
<k-block>
<p>Hello Konsta UI!</p>
</k-block>
</k-page>
</k-app>
</template>
<script setup>
import { kApp, kPage, kNavbar, kBlock } from 'konsta/vue';
</script>Core Components
Page Structure
import {
App,
Page,
Navbar,
NavbarBackLink,
Block,
BlockTitle,
} from 'konsta/react';
function MyPage() {
return (
<App theme="ios">
<Page>
<Navbar
title="Page Title"
subtitle="Subtitle"
left={<NavbarBackLink onClick={() => history.back()} />}
/>
<BlockTitle>Section Title</BlockTitle>
<Block strong inset>
<p>Block content with rounded corners and padding.</p>
</Block>
</Page>
</App>
);
}Lists
import {
List,
ListItem,
ListInput,
ListButton,
} from 'konsta/react';
import { ChevronRight } from 'framework7-icons/react';
function MyList() {
return (
<>
{/* Simple list */}
<List>
<ListItem title="Item 1" />
<ListItem title="Item 2" />
<ListItem title="Item 3" />
</List>
{/* List with details */}
<List strong inset>
<ListItem
title="John Doe"
subtitle="Designer"
text="Additional info text"
media={<img src="/avatar.jpg" className="w-10 h-10 rounded-full" />}
link
/>
<ListItem
title="Settings"
after="On"
link
/>
</List>
{/* Form list */}
<List strongIos insetIos>
<ListInput
label="Email"
type="email"
placeholder="Enter email"
/>
<ListInput
label="Password"
type="password"
placeholder="Enter password"
/>
<ListButton>Login</ListButton>
</List>
</>
);
}Forms
import {
List,
ListInput,
Toggle,
Radio,
Checkbox,
Stepper,
Range,
} from 'konsta/react';
import { useState } from 'react';
function MyForm() {
const [toggle, setToggle] = useState(false);
const [gender, setGender] = useState('male');
return (
<List strongIos insetIos>
{/* Text inputs */}
<ListInput
label="Name"
type="text"
placeholder="Your name"
clearButton
/>
<ListInput
label="Email"
type="email"
placeholder="Email address"
/>
<ListInput
label="Bio"
type="textarea"
placeholder="About yourself"
inputClassName="!h-20 resize-none"
/>
{/* Toggle */}
<ListItem
title="Notifications"
after={
<Toggle
checked={toggle}
onChange={() => setToggle(!toggle)}
/>
}
/>
{/* Radio */}
<ListItem
title="Male"
media={
<Radio
checked={gender === 'male'}
onChange={() => setGender('male')}
/>
}
/>
<ListItem
title="Female"
media={
<Radio
checked={gender === 'female'}
onChange={() => setGender('female')}
/>
}
/>
{/* Checkbox */}
<ListItem
title="Agree to terms"
media={<Checkbox />}
/>
{/* Stepper */}
<ListItem
title="Quantity"
after={<Stepper value={1} min={1} max={10} />}
/>
{/* Range */}
<ListItem
title="Volume"
innerChildren={<Range value={50} />}
/>
</List>
);
}Buttons
import { Button, Segmented, SegmentedButton } from 'konsta/react';
import { useState } from 'react';
function Buttons() {
const [active, setActive] = useState(0);
return (
<div className="space-y-4 p-4">
{/* Button variants */}
<Button>Default</Button>
<Button large>Large</Button>
<Button small>Small</Button>
<Button rounded>Rounded</Button>
<Button outline>Outline</Button>
<Button clear>Clear</Button>
<Button tonal>Tonal</Button>
{/* Colors */}
<Button colors={{ fillBg: 'bg-red-500', fillText: 'text-white' }}>
Custom Color
</Button>
{/* Disabled */}
<Button disabled>Disabled</Button>
{/* Segmented control */}
<Segmented strong>
<SegmentedButton active={active === 0} onClick={() => setActive(0)}>
Tab 1
</SegmentedButton>
<SegmentedButton active={active === 1} onClick={() => setActive(1)}>
Tab 2
</SegmentedButton>
<SegmentedButton active={active === 2} onClick={() => setActive(2)}>
Tab 3
</SegmentedButton>
</Segmented>
</div>
);
}Cards
import { Card, Button } from 'konsta/react';
function Cards() {
return (
<Card>
<img
src="/card-image.jpg"
className="w-full h-48 object-cover"
alt=""
/>
<div className="p-4">
<h3 className="font-bold text-lg">Card Title</h3>
<p className="text-gray-500 mt-2">
Card description text goes here. This is a standard
card with image, title, and content.
</p>
<div className="flex gap-2 mt-4">
<Button small>Action 1</Button>
<Button small outline>Action 2</Button>
</div>
</div>
</Card>
);
}Dialogs and Sheets
import {
Dialog,
DialogButton,
Sheet,
Popup,
Button,
Page,
Navbar,
Block,
} from 'konsta/react';
import { useState } from 'react';
function Dialogs() {
const [dialogOpen, setDialogOpen] = useState(false);
const [sheetOpen, setSheetOpen] = useState(false);
const [popupOpen, setPopupOpen] = useState(false);
return (
<>
<Button onClick={() => setDialogOpen(true)}>Open Dialog</Button>
<Button onClick={() => setSheetOpen(true)}>Open Sheet</Button>
<Button onClick={() => setPopupOpen(true)}>Open Popup</Button>
{/* Alert dialog */}
<Dialog
opened={dialogOpen}
onBackdropClick={() => setDialogOpen(false)}
title="Dialog Title"
content="Dialog content goes here."
buttons={
<>
<DialogButton onClick={() => setDialogOpen(false)}>
Cancel
</DialogButton>
<DialogButton strong onClick={() => setDialogOpen(false)}>
OK
</DialogButton>
</>
}
/>
{/* Bottom sheet */}
<Sheet
opened={sheetOpen}
onBackdropClick={() => setSheetOpen(false)}
>
<div className="p-4">
<h2 className="font-bold text-lg mb-4">Sheet Title</h2>
<p>Sheet content</p>
<Button onClick={() => setSheetOpen(false)} className="mt-4">
Close
</Button>
</div>
</Sheet>
{/* Full page popup */}
<Popup opened={popupOpen} onBackdropClick={() => setPopupOpen(false)}>
<Page>
<Navbar
title="Popup"
right={
<Button clear onClick={() => setPopupOpen(false)}>
Close
</Button>
}
/>
<Block>Popup content</Block>
</Page>
</Popup>
</>
);
}Tabbar Navigation
import { App, Page, Tabbar, TabbarLink, Icon } from 'konsta/react';
import { Home, Search, Person } from 'framework7-icons/react';
import { useState } from 'react';
function TabsApp() {
const [activeTab, setActiveTab] = useState('home');
return (
<App theme="ios">
<Page>
{/* Page content based on active tab */}
{activeTab === 'home' && <HomeContent />}
{activeTab === 'search' && <SearchContent />}
{activeTab === 'profile' && <ProfileContent />}
{/* Tabbar */}
<Tabbar labels className="left-0 bottom-0 fixed">
<TabbarLink
active={activeTab === 'home'}
onClick={() => setActiveTab('home')}
icon={<Home />}
label="Home"
/>
<TabbarLink
active={activeTab === 'search'}
onClick={() => setActiveTab('search')}
icon={<Search />}
label="Search"
/>
<TabbarLink
active={activeTab === 'profile'}
onClick={() => setActiveTab('profile')}
icon={<Person />}
label="Profile"
/>
</Tabbar>
</Page>
</App>
);
}Theming
Theme Selection
import { App } from 'konsta/react';
// Auto-detect platform
<App theme="parent">
// Force iOS style
<App theme="ios">
// Force Material style
<App theme="material">Dark Mode
import { App } from 'konsta/react';
// Auto dark mode (follows system)
<App dark>
// Explicit dark mode
<App dark={true}>
// Explicit light mode
<App dark={false}>Custom Colors with Tailwind
// tailwind.config.js
const konstaConfig = require('konsta/config');
module.exports = konstaConfig({
theme: {
extend: {
colors: {
primary: {
DEFAULT: '#6366f1',
dark: '#4f46e5',
},
},
},
},
// Override Konsta's primary color
konstaConfig: {
colors: {
primary: '#6366f1',
},
},
});Component-Level Styling
// Override individual component colors
<Button
colors={{
fillBg: 'bg-indigo-500',
fillActiveBg: 'bg-indigo-600',
fillText: 'text-white',
}}
>
Custom Button
</Button>
<Toggle
colors={{
bgChecked: 'bg-green-500',
}}
/>With Capacitor
Safe Area Handling
import { App, Page } from 'konsta/react';
function MyApp() {
return (
<App
theme="ios"
safeAreas // Enable safe area handling
>
<Page>
{/* Content respects safe areas */}
</Page>
</App>
);
}Capacitor Integration
import { App, Page, Button } from 'konsta/react';
import { Capacitor } from '@capacitor/core';
function MyApp() {
const isNative = Capacitor.isNativePlatform();
return (
<App
theme={Capacitor.getPlatform() === 'ios' ? 'ios' : 'material'}
safeAreas={isNative}
>
<Page>
<Button onClick={handleNativeAction}>
Native Action
</Button>
</Page>
</App>
);
}Comparison: Konsta vs Ionic
| Feature | Konsta UI | Ionic |
|---|---|---|
| Bundle Size | ~30KB | ~200KB |
| Components | ~40 | ~100+ |
| Tailwind Integration | Native | Possible |
| Routing | External | Built-in |
| Framework Support | React, Vue, Svelte | React, Vue, Angular |
| Native Features | UI only | UI + Plugins |
Choose Konsta when:
- You want Tailwind-first approach
- You need smaller bundle size
- You're using Svelte
- You want simpler setup
Choose Ionic when:
- You need comprehensive component library
- You want built-in routing
- You need more complex components
- You prefer all-in-one solution
Best Practices
Performance
// Lazy load heavy components
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}Accessibility
// Konsta components are accessible by default
// Add labels for screen readers
<ListInput
label="Email"
type="email"
placeholder="Enter email"
// aria-label is automatically set from label
/>
// For icon-only buttons
<Button aria-label="Close menu">
<Icon name="close" />
</Button>Resources
- Konsta UI Documentation: https://konstaui.com/
- Konsta React Docs: https://konstaui.com/react
- Konsta Vue Docs: https://konstaui.com/vue
- Konsta Svelte Docs: https://konstaui.com/svelte
- GitHub: https://github.com/konstaui/konsta
{
"version": "1.0.0",
"organization": "Capgo",
"date": "January 2026",
"abstract": "Guide to using Konsta UI for pixel-perfect iOS and Material Design components. Tailwind CSS native integration, works with React, Vue, and Svelte. Lightweight alternative to Ionic Framework.",
"triggers": [
"konsta ui",
"konsta",
"tailwind mobile",
"ios material components",
"lightweight ui",
"svelte capacitor"
],
"references": [
"https://konstaui.com/",
"https://konstaui.com/react",
"https://github.com/konstaui/konsta"
]
}
Related skills
FAQ
What stack does konsta-ui target?
konsta-ui targets Capacitor hybrid mobile apps using Konsta UI components with Tailwind CSS, producing iOS and Android adaptive interfaces without separate native styling codebases.
Why use Konsta UI in Capacitor apps?
konsta-ui helps Capacitor developers ship touch-native lists, sheets, and controls that automatically match iOS and Android platform conventions instead of generic web layouts.
When should developers invoke konsta-ui?
Developers invoke konsta-ui when scaffolding Capacitor screens, replacing plain HTML UI, or implementing Capgo mobile features that need platform-adaptive Tailwind components.