feat: macOS 改用原生圆角与原生红绿灯

- tauri.conf.json: decorations=true + titleBarStyle=Overlay + transparent
  + hiddenTitle + trafficLightPosition,启用原生圆角/squircle 与原生红绿灯
- main.css: 移除 #root 的 CSS border-radius,避免圆弧覆盖原生连续曲率
- App.tsx: macOS 下隐藏自绘 Windows 风格三按钮
- ContentArea.tsx: 侧栏隐藏(沉浸/竖屏)时 header 左侧为红绿灯留白
- Sidebar.tsx: macOS 下 logo 区上内边距增大,避开红绿灯

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
JSR
2026-07-05 16:16:28 +08:00
parent 210a1994e6
commit c460800532
5 changed files with 27 additions and 8 deletions
+5 -2
View File
@@ -19,8 +19,11 @@
"height": 680, "height": 680,
"resizable": true, "resizable": true,
"fullscreen": false, "fullscreen": false,
"decorations": false, "decorations": true,
"transparent": false, "transparent": true,
"hiddenTitle": true,
"titleBarStyle": "Overlay",
"trafficLightPosition": { "x": 16, "y": 22 },
"center": true, "center": true,
"minWidth": 360, "minWidth": 360,
"minHeight": 640 "minHeight": 640
+5 -1
View File
@@ -57,6 +57,10 @@ function MainContent(): React.JSX.Element {
const { currentTheme } = useTheme() const { currentTheme } = useTheme()
const [messageApi, contextHolder] = message.useMessage() const [messageApi, contextHolder] = message.useMessage()
const { isIosDevice, isAndroidDevice, defaultPortraitMode } = useMemo(getMobileDeviceInfo, []) const { isIosDevice, isAndroidDevice, defaultPortraitMode } = useMemo(getMobileDeviceInfo, [])
const isMacDesktop =
typeof navigator !== "undefined" &&
/mac/i.test(navigator.userAgent) &&
!/iphone|ipad|ipod|android/i.test(navigator.userAgent)
const [immersiveMode, setImmersiveMode] = useState(false) const [immersiveMode, setImmersiveMode] = useState(false)
const normalizeStoredBottomKeys = (raw: unknown): MobileNavKey[] => { const normalizeStoredBottomKeys = (raw: unknown): MobileNavKey[] => {
@@ -791,7 +795,7 @@ function MainContent(): React.JSX.Element {
hasAnyPassword={hasAnyPassword} hasAnyPassword={hasAnyPassword}
onAuthClick={() => setAuthVisible(true)} onAuthClick={() => setAuthVisible(true)}
onLogout={logout} onLogout={logout}
showWindowControls={!isIosDevice && !isAndroidDevice} showWindowControls={!isIosDevice && !isAndroidDevice && !isMacDesktop}
isPortraitMode={isPortraitMode} isPortraitMode={isPortraitMode}
isMobileDevice={isMobileDevice} isMobileDevice={isMobileDevice}
sidebarCollapsed={sidebarCollapsed} sidebarCollapsed={sidebarCollapsed}
+2 -4
View File
@@ -209,10 +209,8 @@ html.platform-macos body {
background: transparent; background: transparent;
} }
html.platform-macos #root { /* macOS:保留原生窗口圆角与 squircle(由 NSWindow 在系统层裁剪),
border-radius: 12px; 不再用 CSS border-radius 覆盖,避免圆弧破坏原生连续曲率。 */
overflow: hidden;
}
.ss-group-board-modal .ant-modal { .ss-group-board-modal .ant-modal {
max-height: calc(100vh - 24px); max-height: calc(100vh - 24px);
+7
View File
@@ -104,6 +104,12 @@ export function ContentArea({
bottomInset = 0, bottomInset = 0,
}: ContentAreaProps): React.JSX.Element { }: ContentAreaProps): React.JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
const isMacOS =
typeof navigator !== "undefined" &&
/mac/i.test(navigator.userAgent) &&
!/iphone|ipad|ipod|android/i.test(navigator.userAgent)
// macOS 使用原生红绿灯,侧栏隐藏(沉浸/竖屏)时顶部左侧需为红绿灯留白
const macTrafficLightsInset = isMacOS && (isPortraitMode || immersiveMode)
const location = useLocation() const location = useLocation()
const navigate = useNavigate() const navigate = useNavigate()
const isSubPage = location.pathname !== "/" && !location.pathname.startsWith("/home") const isSubPage = location.pathname !== "/" && !location.pathname.startsWith("/home")
@@ -418,6 +424,7 @@ export function ContentArea({
background: "var(--ss-header-bg)", background: "var(--ss-header-bg)",
borderBottom: "1px solid var(--ss-border-color)", borderBottom: "1px solid var(--ss-border-color)",
flexShrink: 0, flexShrink: 0,
paddingLeft: macTrafficLightsInset ? "80px" : 0,
WebkitAppRegion: "drag", WebkitAppRegion: "drag",
position: "relative", position: "relative",
} as React.CSSProperties } as React.CSSProperties
+8 -1
View File
@@ -213,13 +213,20 @@ export function Sidebar({
const showFloatingPanel = floatingExpand && collapsed && floatingExpanded const showFloatingPanel = floatingExpand && collapsed && floatingExpanded
const isMacOS =
typeof navigator !== "undefined" &&
/mac/i.test(navigator.userAgent) &&
!/iphone|ipad|ipod|android/i.test(navigator.userAgent)
const renderSidebarBody = (isCollapsedView: boolean, hideMenu = false) => ( const renderSidebarBody = (isCollapsedView: boolean, hideMenu = false) => (
<> <>
<div <div
data-tauri-drag-region data-tauri-drag-region
style={ style={
{ {
padding: isCollapsedView ? "20px 8px 12px" : "24px 24px 16px", padding: isCollapsedView
? `${isMacOS ? 40 : 20}px 8px 12px`
: `${isMacOS ? 44 : 24}px 24px 16px`,
textAlign: "center", textAlign: "center",
WebkitAppRegion: "drag", WebkitAppRegion: "drag",
userSelect: "none", userSelect: "none",