capacitor-edge-to-edge
v2.1.1
Published
A Capacitor plugin for implementing edge-to-edge display with transparent system bars. Supports Android 11-16 (API 30-36) and iOS 14+.
Downloads
3,919
Maintainers
Readme
capacitor-edge-to-edge
A Capacitor plugin for implementing Android edge-to-edge display with native control over system bars (status bar and navigation bar).
Features
✅ Native Edge-to-Edge Mode - Content draws behind system bars
✅ Transparent System Bars - Full control over transparency
✅ Custom Bar Colors - Set any color with alpha support
✅ Light/Dark Icons - Control icon appearance based on background
✅ Safe Area Insets - Get system bar sizes for layout adjustment
✅ Keyboard Detection - Get keyboard height and listen to show/hide events
✅ Android 11-16 Support - Compatible with API 30-36
✅ iOS 14+ Support - Status bar control and safe area handling
✅ Web Platform Support - Fallback implementation for web/PWA
Install
npm install capacitor-edge-to-edge
npx cap syncUsage
Basic Setup
import { EdgeToEdge } from 'capacitor-edge-to-edge';
// Enable edge-to-edge mode
await EdgeToEdge.enable();
// Make system bars transparent
await EdgeToEdge.setTransparentSystemBars({
statusBar: true,
navigationBar: true
});
// Set dark icons for light backgrounds
await EdgeToEdge.setSystemBarAppearance({
statusBarStyle: 'dark',
navigationBarStyle: 'dark'
});Complete Example
import { EdgeToEdge } from 'capacitor-edge-to-edge';
async function setupEdgeToEdge() {
try {
// 1. Enable edge-to-edge mode
await EdgeToEdge.enable();
// 2. Set transparent system bars
await EdgeToEdge.setTransparentSystemBars({
statusBar: true,
navigationBar: true
});
// 3. Configure appearance (light icons for dark backgrounds)
await EdgeToEdge.setSystemBarAppearance({
statusBarStyle: 'light',
navigationBarStyle: 'light'
});
// 4. Get system bar insets for safe area handling
const insets = await EdgeToEdge.getSystemBarInsets();
console.log('Status bar height:', insets.statusBar);
console.log('Navigation bar height:', insets.navigationBar);
// Apply padding to your content
document.body.style.paddingTop = `${insets.top}px`;
document.body.style.paddingBottom = `${insets.bottom}px`;
} catch (error) {
console.error('Edge-to-edge setup failed:', error);
}
}Keyboard Handling
import { EdgeToEdge } from 'capacitor-edge-to-edge';
// Get current keyboard state
const keyboardInfo = await EdgeToEdge.getKeyboardInfo();
console.log('Keyboard height:', keyboardInfo.height);
console.log('Is visible:', keyboardInfo.isVisible);
// Listen to keyboard events
EdgeToEdge.addListener('keyboardWillShow', (event) => {
console.log('Keyboard showing, height:', event.height);
// Adjust your input container
const inputContainer = document.querySelector('.input-container');
inputContainer.style.transform = `translateY(-${event.height}px)`;
});
EdgeToEdge.addListener('keyboardWillHide', () => {
console.log('Keyboard hiding');
// Reset position
const inputContainer = document.querySelector('.input-container');
inputContainer.style.transform = 'translateY(0)';
});
// Clean up when done
EdgeToEdge.removeAllListeners();For more keyboard examples, see KEYBOARD_GUIDE.md.
Theme Integration
// Light mode
await EdgeToEdge.setSystemBarColors({
statusBarColor: '#FFFFFF',
navigationBarColor: '#FFFFFF'
});
await EdgeToEdge.setSystemBarAppearance({
statusBarStyle: 'dark', // Dark icons on light background
navigationBarStyle: 'dark'
});
// Dark mode
await EdgeToEdge.setSystemBarColors({
statusBarColor: '#000000',
navigationBarColor: '#000000'
});
await EdgeToEdge.setSystemBarAppearance({
statusBarStyle: 'light', // Light icons on dark background
navigationBarStyle: 'light'
});
// Semi-transparent overlay
await EdgeToEdge.setSystemBarColors({
statusBarColor: '#80000000', // 50% transparent black
navigationBarColor: '#80000000'
});React/Vue/Angular Integration
// React Hook Example
import { useEffect } from 'react';
import { EdgeToEdge } from 'capacitor-edge-to-edge';
function useEdgeToEdge(theme: 'light' | 'dark') {
useEffect(() => {
const setupBars = async () => {
await EdgeToEdge.enable();
await EdgeToEdge.setTransparentSystemBars({
statusBar: true,
navigationBar: true
});
const style = theme === 'dark' ? 'light' : 'dark';
await EdgeToEdge.setSystemBarAppearance({
statusBarStyle: style,
navigationBarStyle: style
});
};
setupBars();
}, [theme]);
}API
enable()
Enable edge-to-edge mode. Content will draw behind system bars.
await EdgeToEdge.enable();disable()
Disable edge-to-edge mode. Content will be below system bars.
await EdgeToEdge.disable();setTransparentSystemBars(options)
Set system bars to transparent.
await EdgeToEdge.setTransparentSystemBars({
statusBar: true, // Make status bar transparent
navigationBar: true // Make navigation bar transparent
});setSystemBarColors(options)
Set custom colors for system bars. Supports hex colors with alpha channel.
await EdgeToEdge.setSystemBarColors({
statusBarColor: '#FF5733', // Solid color
navigationBarColor: '#80000000' // 50% transparent black
});setSystemBarAppearance(options)
Control icon/text appearance on system bars.
await EdgeToEdge.setSystemBarAppearance({
statusBarStyle: 'light', // 'light' | 'dark'
navigationBarStyle: 'light' // 'light' | 'dark'
});Note:
'light'= Light icons (use for dark backgrounds)'dark'= Dark icons (use for light backgrounds)
getSystemBarInsets()
Get system bar sizes for safe area handling.
const insets = await EdgeToEdge.getSystemBarInsets();
// Returns: {
// statusBar: number, // Status bar height
// navigationBar: number, // Navigation bar height
// top: number, // Top safe area
// bottom: number, // Bottom safe area
// left: number, // Left safe area
// right: number // Right safe area
// }getKeyboardInfo()
Get current keyboard height and visibility.
const keyboardInfo = await EdgeToEdge.getKeyboardInfo();
// Returns: {
// height: number, // Keyboard height in pixels
// isVisible: boolean // Whether keyboard is visible
// }Keyboard Event Listeners
Listen to keyboard show/hide events.
// Available events:
await EdgeToEdge.addListener('keyboardWillShow', (event) => {
// event.height: number
// event.isVisible: boolean
// event.animationDuration?: number (iOS only)
});
await EdgeToEdge.addListener('keyboardWillHide', (event) => {
// Fired when keyboard starts hiding
});
await EdgeToEdge.addListener('keyboardDidShow', (event) => {
// Fired when keyboard animation completes
});
await EdgeToEdge.addListener('keyboardDidHide', (event) => {
// Fired when keyboard is fully hidden
});
// Remove all listeners
await EdgeToEdge.removeAllListeners();Platform Support
| Platform | Status | Notes | |----------|--------|-------| | Android 11-16 | ✅ Full Support | Native edge-to-edge with WindowInsetsController (API 30-36) | | Android 10 | ✅ Compat Mode | Using WindowInsetsControllerCompat | | iOS 14+ | ✅ Full Support | Status bar appearance and safe area insets | | Web | ⚠️ Limited | Meta tags and CSS safe-area-inset |
Android 16 (API 36) Notes
Important Changes:
- Android 16 fully enforces edge-to-edge mode for apps targeting API 36
- The
windowOptOutEdgeToEdgeEnforcementattribute is deprecated and disabled - Apps can no longer opt-out of edge-to-edge display
- This plugin is fully compatible with Android 16's enforcement requirements
If you're migrating from Android 15 (API 35) to Android 16 (API 36):
- Remove any
windowOptOutEdgeToEdgeEnforcementfrom your theme - Ensure proper inset handling using
getSystemBarInsets() - Test your app layout with system bars overlaying content
iOS 14+ Notes
What's Supported:
- ✅ Status bar appearance (light/dark content)
- ✅ Safe area insets detection (including notch and home indicator)
- ✅ Background color changes
- ⚠️ Status bar color is always transparent (iOS limitation)
iOS-Specific Configuration:
Add to your Info.plist for status bar control:
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>For edge-to-edge content on iOS:
// Content extends under status bar automatically
// Use safe area insets to adjust your layoutPlatform Differences:
- iOS status bar is always transparent (system design)
- Navigation bar refers to home indicator on iOS (not a top bar)
- Safe area includes notch, Dynamic Island, and home indicator
CSS Safe Area Support
Add to your global CSS for proper safe area handling:
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
/* Or use CSS variables */
:root {
--safe-area-top: env(safe-area-inset-top, 0px);
--safe-area-bottom: env(safe-area-inset-bottom, 0px);
}Android Configuration
No additional configuration needed! The plugin handles everything automatically.
Comparison with Other Solutions
| Feature | This Plugin | @capacitor/status-bar | @capawesome/edge-to-edge | |---------|-------------|----------------------|-------------------------| | Edge-to-edge mode | ✅ | ❌ | ✅ | | Transparent bars | ✅ | ⚠️ Limited | ✅ | | Custom colors | ✅ | ✅ | ✅ | | Icon appearance | ✅ | ✅ | ⚠️ Limited | | Inset detection | ✅ | ❌ | ⚠️ Limited | | Android 11-16 (API 30-36) | ✅ | ✅ | ✅ | | iOS 14+ | ✅ | ✅ | ⚠️ Limited |
Troubleshooting
Content appears behind system bars
This is expected in edge-to-edge mode. Use getSystemBarInsets() to add appropriate padding:
const insets = await EdgeToEdge.getSystemBarInsets();
document.body.style.paddingTop = `${insets.top}px`;System bars not transparent
Make sure to call both enable() and setTransparentSystemBars():
await EdgeToEdge.enable();
await EdgeToEdge.setTransparentSystemBars({
statusBar: true,
navigationBar: true
});iOS status bar not changing style
Ensure UIViewControllerBasedStatusBarAppearance is set to true in Info.plist:
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>iOS safe area insets not correct
Make sure to call getSystemBarInsets() after the view has loaded:
// In your component's mount/load lifecycle
useEffect(() => {
const updateInsets = async () => {
const insets = await EdgeToEdge.getSystemBarInsets();
// Use insets
};
updateInsets();
}, []);License
MIT
Credits
Created by q1600822305
enable()disable()setTransparentSystemBars(...)setSystemBarColors(...)setSystemBarAppearance(...)getSystemBarInsets()getKeyboardInfo()show()hide()addListener('keyboardWillShow' | 'keyboardDidShow' | 'keyboardWillHide' | 'keyboardDidHide', ...)removeAllListeners()- Interfaces
Capacitor Edge-to-Edge Plugin Provides native edge-to-edge display control for Android 11-16 (API 30-36)
enable()
enable() => Promise<void>Enable edge-to-edge mode (content draws behind system bars) Supported on Android 11-16 (API 30-36)
disable()
disable() => Promise<void>Disable edge-to-edge mode (content below system bars)
setTransparentSystemBars(...)
setTransparentSystemBars(options: TransparentBarsOptions) => Promise<void>Set system bars to transparent
| Param | Type | Description |
| ------------- | ------------------------------------------------------------------------- | ---------------------------------- |
| options | TransparentBarsOptions | Configuration for transparent bars |
setSystemBarColors(...)
setSystemBarColors(options: SystemBarColorsOptions) => Promise<void>Set system bar colors
| Param | Type | Description |
| ------------- | ------------------------------------------------------------------------- | ------------------- |
| options | SystemBarColorsOptions | Color configuration |
setSystemBarAppearance(...)
setSystemBarAppearance(options: SystemBarAppearanceOptions) => Promise<void>Set system bar appearance (light/dark icons)
| Param | Type | Description |
| ------------- | --------------------------------------------------------------------------------- | ------------------------ |
| options | SystemBarAppearanceOptions | Appearance configuration |
getSystemBarInsets()
getSystemBarInsets() => Promise<SystemBarInsetsResult>Get current system bar insets (for safe area handling)
Returns: Promise<SystemBarInsetsResult>
getKeyboardInfo()
getKeyboardInfo() => Promise<KeyboardInfo>Get current keyboard height and visibility
Returns: Promise<KeyboardInfo>
show()
show() => Promise<void>Show the keyboard
Note: This method is alpha and may have issues.
- Android: Supported
- iOS: Not supported (will call unimplemented)
- Web: Not supported
Since: 1.6.0
hide()
hide() => Promise<void>Hide the keyboard
Since: 1.6.0
addListener('keyboardWillShow' | 'keyboardDidShow' | 'keyboardWillHide' | 'keyboardDidHide', ...)
addListener(eventName: 'keyboardWillShow' | 'keyboardDidShow' | 'keyboardWillHide' | 'keyboardDidHide', listenerFunc: (event: KeyboardEvent) => void) => Promise<PluginListenerHandle>Add listener for keyboard events
| Param | Type | Description |
| ------------------ | ----------------------------------------------------------------------------------------------- | ------------------- |
| eventName | 'keyboardWillShow' | 'keyboardDidShow' | 'keyboardWillHide' | 'keyboardDidHide' | - Event name |
| listenerFunc | (event: KeyboardEvent) => void | - Callback function |
Returns: Promise<PluginListenerHandle>
removeAllListeners()
removeAllListeners() => Promise<void>Remove all listeners for this plugin
Interfaces
TransparentBarsOptions
| Prop | Type | Description | Default |
| ------------------- | -------------------- | ------------------------------- | ----------------- |
| statusBar | boolean | Make status bar transparent | true |
| navigationBar | boolean | Make navigation bar transparent | true |
SystemBarColorsOptions
| Prop | Type | Description |
| ------------------------ | ------------------- | ------------------------------------------------------------------ |
| statusBarColor | string | Status bar background color (hex format: #RRGGBB or #AARRGGBB) |
| navigationBarColor | string | Navigation bar background color (hex format: #RRGGBB or #AARRGGBB) |
SystemBarAppearanceOptions
| Prop | Type | Description |
| ------------------------ | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| statusBarStyle | 'light' | 'dark' | Status bar icon/text appearance - "light": Light icons/text (for dark backgrounds) - "dark": Dark icons/text (for light backgrounds) |
| navigationBarStyle | 'light' | 'dark' | Navigation bar button appearance - "light": Light buttons (for dark backgrounds) - "dark": Dark buttons (for light backgrounds) |
SystemBarInsetsResult
| Prop | Type | Description |
| ------------------- | ------------------- | ----------------------------------------------- |
| statusBar | number | Status bar height in pixels |
| navigationBar | number | Navigation bar height in pixels |
| top | number | Top safe area inset |
| bottom | number | Bottom safe area inset |
| left | number | Left safe area inset (for landscape/foldables) |
| right | number | Right safe area inset (for landscape/foldables) |
KeyboardInfo
| Prop | Type | Description |
| -------------------- | -------------------- | ---------------------------------------------------------------------------------- |
| keyboardHeight | number | Keyboard height - Android: in DP units - iOS: in pixels - Web: estimated in pixels |
| isVisible | boolean | Whether keyboard is currently visible |
PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| remove | () => Promise<void> |
KeyboardEvent
| Prop | Type | Description |
| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| keyboardHeight | number | Keyboard height - Android: in DP units (density-independent pixels) - iOS: in pixels - Web: estimated in pixels Compatible with official @capacitor/keyboard plugin |
