Ionic
Use touchcn components inside an existing Ionic Angular, React, or Vue app — coexistence, CSS boundaries, structure conflicts, and a migration path.
touchcn and Ionic can run side by side in the same app. touchcn
components are plain DOM with tcn-* classes, so they render fine inside an ion-content, and adding
touchcn does not change how you bootstrap Ionic. This guide covers what to watch for when the two share
a page and how to migrate incrementally.
Coexistence model
Install touchcn as in Getting started and register its provider once at the
app root, alongside your existing Ionic setup — the two providers are independent. A touchcn component
placed inside ion-content behaves like any other child element:
<ion-content>
<button tcnButton variant="primary">Save</button>
</ion-content><IonContent>
<TcnButton variant="primary">Save</TcnButton>
</IonContent><ion-content>
<TcnButton variant="primary">Save</TcnButton>
</ion-content>CSS boundaries
The two systems keep their styling in separate namespaces, which is what makes coexistence practical:
- Design tokens do not overlap. Ionic themes through
--ion-*CSS variables that only its ownion-*elements read; touchcn themes through--color-*tokens consumed by.tcn-*classes. Neither sees the other’s variables, so re-theming Ionic does not shift touchcn components and vice versa. - Ionic components are largely shadow-encapsulated. Most
ion-*elements render into a shadow root, so Tailwind’s preflight (which resets base elements in the light DOM) does not reach inside them. Preflight still resets your own light-DOM markup — headings, lists, buttons you write directly — so expect that reset to apply to non-Ionic elements exactly as it would in any Tailwind project. - Load order. Import Ionic’s stylesheets and Tailwind (with the touchcn token layer) both from your
global stylesheet. touchcn’s platform chrome lives in an
@layer componentsblock at single-class specificity, so ordinary Ionic rules and your own utilities out-rank it; if a specific reset ever collides, adjust import order or scope the narrower rule rather than raising specificity globally.
Structure conflicts
Do not nest touchcn chrome inside Ionic chrome. A tcn-navbar inside ion-header /
ion-toolbar, or a tcn-tabbar inside ion-footer, produces two stacked bars and two safe-area
insets applied to the same edge. Pick one chrome per screen: keep Ionic’s ion-header / ion-tab-bar,
or use touchcn’s — not both on the same edge.
Overlays need a note on stacking. touchcn overlays (dialogs, sheets, the select and datepicker panels)
are position: fixed and layer with Tailwind’s z-40 (navbar/tabbar) and z-50 (overlays) — low
numbers. Ionic layers much higher: its toolbar sits at z-index: 10, menus and inline overlays around
1000, and Ionic assigns its runtime overlays (ion-modal, ion-alert, ion-action-sheet,
ion-toast, …) a z-index starting at 20000. The practical consequences:
- A touchcn overlay renders above ordinary Ionic content and toolbars — fine for a dialog over a normal page.
- A touchcn overlay renders below an active Ionic runtime overlay (modal, alert, toast). If you
genuinely need a touchcn overlay on top of an Ionic modal, raise its
z-indexpast Ionic’s20000+ range explicitly — but that usually signals you should present one or the other, not stack them.
Migration path
Migrate leaf-first, so each step is low-risk and visually contained:
- Start with leaf components — buttons, badges, cards, list rows. They have no structural
dependencies, so swapping an
ion-buttonfortcnButtontouches one element. - Replace form controls and overlays next — inputs, selects, switches, dialogs — screen by screen.
- Swap the chrome last, per page — replace
ion-header/ion-tab-barwithtcn-navbar/tcn-tabbaronly when a whole screen has otherwise moved over, to avoid the double-chrome conflict above. - Keep Ionic’s router. touchcn ships no router; leave routing and page lifecycle to Ionic
(
ion-router/ Angular Router / your React Router or Vue Router setup). touchcn components live inside those routed pages.