Tauri v2 plugin for native macOS rounded corners with customizable Traffic Lights positioning. Auto-repositions after fullscreen. App Store compatible.
npm install @cloudworxx/tauri-plugin-mac-rounded-corners



A reusable Tauri plugin that enables native macOS rounded corners with customizable Traffic Lights positioning for frameless windows.
Sascha Klein
Website: cloudworxx.us
Email: hello@cloudworxx.us
- ✅ Rounded corners (12px default, customizable)
- ✅ Traffic Lights positioning (Close, Minimize, Maximize buttons)
- ✅ Auto-reposition after fullscreen (NEW in v1.1.0)
- ✅ App Store compatible - Uses only public macOS APIs
- ✅ Custom titlebar support - Full-size content view
- ✅ Native shadows - Optional shadow effects
- ✅ TypeScript support - Full type definitions
- ✅ Works with decorations: false
- ✅ Zero runtime dependencies
- ✅ MIT Licensed - Free for personal and commercial use
- Auto-reposition: Traffic Lights automatically reposition after fullscreen exit
- New command: reposition_traffic_lights() for manual control
- Event-based: Uses onResized listener for instant repositioning
- Bug fixes: Close button now works correctly, fullscreen positioning fixed
There are two ways to install this plugin: automatic (recommended) or manual.
The plugin includes an automatic installer that copies files and updates your project configuration.
#### 1. Install the package
``bash`
npm install @cloudworxx/tauri-plugin-mac-rounded-corners
The postinstall script automatically:mod.rs
- ✅ Copies to src-tauri/src/plugins/mac_rounded_corners.rssrc-tauri/src/plugins/mod.rs
- ✅ Creates/updates
#### 2. Complete the setup
You still need to manually add:
a) Dependencies to src-tauri/Cargo.toml:
`toml`
[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.26"
objc = "0.2.7"
b) Commands in src-tauri/src/lib.rs:
`rust
mod plugins;
use plugins::mac_rounded_corners;
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
mac_rounded_corners::enable_rounded_corners,
mac_rounded_corners::enable_modern_window_style,
mac_rounded_corners::reposition_traffic_lights
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
`
c) Permissions to tauri.conf.json:
`json`
{
"app": {
"security": {
"capabilities": [
{
"identifier": "main-capability",
"windows": ["*"],
"permissions": [
"core:window:allow-start-dragging",
"core:window:allow-is-fullscreen",
"core:window:allow-is-maximized",
"core:event:allow-listen"
]
}
]
}
}
}
#### 1. Copy Rust Code
`bash`
mkdir -p src-tauri/src/plugins
cp mod.rs src-tauri/src/plugins/mac_rounded_corners.rs
#### 2. Add Dependencies
Add to src-tauri/Cargo.toml:
`toml`
[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.26"
objc = "0.2.7"
#### 3. Register Commands
In src-tauri/src/lib.rs:
`rust
mod plugins;
use plugins::mac_rounded_corners;
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
mac_rounded_corners::enable_rounded_corners,
mac_rounded_corners::enable_modern_window_style,
mac_rounded_corners::reposition_traffic_lights // NEW in v1.1.0
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
`
Create src-tauri/src/plugins/mod.rs:
`rust`
pub mod mac_rounded_corners;
#### 4. Add Required Permissions
IMPORTANT: Add these permissions to tauri.conf.json:
`json`
{
"app": {
"security": {
"capabilities": [
{
"identifier": "main-capability",
"windows": ["*"],
"permissions": [
"core:window:allow-start-dragging",
"core:window:allow-is-fullscreen",
"core:window:allow-is-maximized",
"core:event:allow-listen"
]
}
]
}
}
}
#### 5. Import TypeScript Functions
Option 1: Use from npm package (recommended)
`typescript`
import { enableModernWindowStyle } from '@cloudworxx/tauri-plugin-mac-rounded-corners';
Option 2: Copy TypeScript file locally
`bash`
mkdir -p src/lib
cp node_modules/@cloudworxx/tauri-plugin-mac-rounded-corners/index.ts src/lib/mac-rounded-corners.ts
Then import from local file:
`typescript`
import { enableModernWindowStyle } from './lib/mac-rounded-corners';
After npm installation:
`typescript
import { useEffect } from 'react';
import { enableModernWindowStyle } from '@cloudworxx/tauri-plugin-mac-rounded-corners';
function App() {
useEffect(() => {
// Enable rounded corners on mount
// Auto-repositioning after fullscreen is enabled automatically
enableModernWindowStyle();
}, []);
return
$3
`typescript
import { enableModernWindowStyle } from '@cloudworxx/tauri-plugin-mac-rounded-corners';// Custom corner radius and Traffic Lights position
await enableModernWindowStyle({
cornerRadius: 16, // Default: 12
offsetX: 5, // Move Traffic Lights 5px right
offsetY: 10, // Move Traffic Lights 10px down
});
`$3
`typescript
import { repositionTrafficLights } from '@cloudworxx/tauri-plugin-mac-rounded-corners';// Manually reposition Traffic Lights (useful after window state changes)
await repositionTrafficLights();
`$3
`typescript
import { enableRoundedCorners } from '@cloudworxx/tauri-plugin-mac-rounded-corners';// Simpler version without shadow and layer-based clipping
await enableRoundedCorners({
offsetX: 0,
offsetY: 0,
});
`CSS Setup
Add to your CSS to ensure clean rounded corners:
`css
html, body, #root {
margin: 0;
padding: 0;
background-color: transparent;
overflow: hidden;
}.App {
width: 100%;
height: 100vh;
background-color: #f6f6f6; / Your app background /
}
`Traffic Lights Positioning
The Traffic Lights (Close, Minimize, Maximize) can be positioned using offset values:
- offsetX: Horizontal offset in pixels
- Positive = move right
- Negative = move left
- Default:
0.0- offsetY: Vertical offset in pixels
- Positive = move down
- Negative = move up
- Default:
0.0$3
`typescript
// Standard macOS position (top-left)
enableModernWindowStyle({ offsetX: 0, offsetY: 0 });// Move right and down
enableModernWindowStyle({ offsetX: 10, offsetY: 15 });
// Move left (careful with negative values!)
enableModernWindowStyle({ offsetX: -5, offsetY: 5 });
`⚠️ Warning: Avoid extreme offset values (< -5px or very large positive values) as they may cause Traffic Lights to become unclickable.
API Reference
$3
Enables basic rounded corners with transparent titlebar.
Parameters:
-
config.offsetX (optional): Horizontal Traffic Lights offset (default: 0)
- config.offsetY (optional): Vertical Traffic Lights offset (default: 0)Returns:
Promise$3
Enables modern window style with rounded corners, shadow, and layer-based clipping. Recommended.
Parameters:
-
config.cornerRadius (optional): Corner radius in pixels (default: 12)
- config.offsetX (optional): Horizontal Traffic Lights offset (default: 0)
- config.offsetY (optional): Vertical Traffic Lights offset (default: 0)Returns:
Promise$3
Manually repositions Traffic Lights to their configured position. Useful if you need to manually trigger repositioning.
Returns:
Promise$3
Cleanup function to remove event listeners. Call when component unmounts.
Returns:
voidTauri Configuration
Ensure your
tauri.conf.json has decorations disabled:`json
{
"tauri": {
"windows": [
{
"decorations": false
}
]
}
}
`Important: Do NOT set
transparent: true - this plugin provides rounded corners without requiring the transparency API, making it more reliable and App Store compatible.Platform Support
| Feature | macOS | Windows | Linux |
|---------|-------|---------|-------|
| Rounded Corners | ✅ | ❌ | ❌ |
| Traffic Lights | ✅ (native) | N/A | N/A |
| Shadow | ✅ (native) | ✅ | ✅ |
| Auto-reposition | ✅ | N/A | N/A |
On non-macOS platforms, the plugin commands are no-ops and won't throw errors.
Troubleshooting
$3
Solution: Ensure you have the required permissions in
tauri.conf.json:
`json
"core:window:allow-is-fullscreen",
"core:event:allow-listen"
`$3
- Check your offset values - they may be too extreme
- Ensure all window style masks are set (the plugin handles this)
- Safe ranges:
offsetX: -5 to 20, offsetY: 0 to 20$3
- Ensure
html, body, #root have background-color: transparent
- Remove border-radius from these elements
- Let the Rust layer handle the clipping$3
- This is fixed in v1.1.0 (adds
NSClosableWindowMask)
- Make sure you're using the latest version$3
Add all required permissions to
tauri.conf.json (see Installation step 4)Technical Details
$3
-
NSWindow.styleMask
- NSFullSizeContentViewWindowMask
- setTitlebarAppearsTransparent
- setTitleVisibility
- setHasShadow
- CALayer.setCornerRadius
- setMasksToBounds
- standardWindowButton (for repositioning)No private APIs are used - fully App Store compliant.
$3
The plugin uses Tauri's
onResized event listener to detect when the window exits fullscreen mode. When this event fires, it immediately calls repositionTrafficLights() to restore the custom position. This is event-based and instant (~0-50ms), not polling-based.$3
1.
NSFullSizeContentViewWindowMask allows content in titlebar region
2. Transparent titlebar removes default chrome
3. Layer-based corner radius clips the content
4. Style masks enable Traffic Light functionality
5. Frame manipulation positions the buttons
6. Event listener repositions after state changesRequirements
- Tauri v2.x
- macOS 10.15 or later
- Rust stable toolchain
- Node.js 18+
Changelog
See CHANGELOG.md for detailed version history.
$3
v1.1.0 (2025-01-02)
- Added auto-reposition feature for Traffic Lights after fullscreen
- New
reposition_traffic_lights() command
- Event-based resize listener
- Fixed Close button not working
- Added required permissions documentationv1.0.0 (2025-01-02)
- Initial release
FAQ
Q: Does this work with Tauri v1?
A: No, this plugin is designed for Tauri v2. For Tauri v1, you would need to adapt the code.
Q: Can I use this in production?
A: Yes! The plugin uses only public APIs and is App Store compatible.
Q: Will this work on Windows/Linux?
A: The commands are no-ops on non-macOS platforms, so your app won't crash, but rounded corners are macOS-only.
Q: Can I customize the corner radius?
A: Yes! Use the
cornerRadius parameter in enableModernWindowStyle().Q: Do I need
transparent: true in tauri.conf.json?
A: No! This plugin works without the transparency API, which makes it more reliable and avoids potential App Store issues.Q: Why do Traffic Lights reset position after fullscreen?
A: macOS resets custom button positions during fullscreen transitions. v1.1.0 automatically fixes this with event-based repositioning.
Q: Is this free?
A: Yes! MIT licensed - free for personal and commercial use.
Support
- 📧 Email: hello@cloudworxx.us
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
License
MIT License - see LICENSE file for details.
Copyright (c) 2025 Sascha Klein (cloudworxx.us)
Credits
Created for PromptDeck
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
1. Fork the repository
2. Create your feature branch (
git checkout -b feature/amazing-feature)
3. Commit your changes (git commit -m 'Add some amazing feature')
4. Push to the branch (git push origin feature/amazing-feature`)If you find this plugin useful, please consider giving it a ⭐ on GitHub!
---
Made with ❤️ by Sascha Klein (cloudworxx.us)