🐛 fix: add separate border-radius for bottom-right corner on macOS 26 Chrome (#11287)

* 🐛 fix: add separate border-radius for bottom-right corner on macOS 26 Chrome

Fix issue where the main container's bottom-right corner radius was not applied correctly on macOS 26 Chrome.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* 📝 docs(CLAUDE): add PR Linear Issue Association guidelines

Include a new section in CLAUDE.md outlining the requirement to use magic keywords in PR bodies for associating with Linear issues, enhancing clarity on issue tracking.

Signed-off-by: Innei <tukon479@gmail.com>

---------

Signed-off-by: Innei <tukon479@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Innei
2026-01-06 23:13:30 +08:00
committed by GitHub
parent 9c6d31af5c
commit 544931a9c6
6 changed files with 68 additions and 5 deletions

View File

@@ -74,6 +74,10 @@ The project follows a well-organized monorepo structure:
- **Dev**: Translate `locales/zh-CN/namespace.json` locale file only for preview
- DON'T run `pnpm i18n`, let CI auto handle it
## Linear Issue Management
Follow [Linear rules in CLAUDE.md](CLAUDE.md#linear-issue-management-ignore-if-not-installed-linear-mcp) when working with Linear issues.
## Project Rules Index
All following rules are saved under `.cursor/rules/` directory:

View File

@@ -78,6 +78,10 @@ When creating new Linear issues using `mcp__linear-server__create_issue`, **MUST
- Code review context
- Future reference and debugging
### PR Linear Issue Association (REQUIRED)
**When creating PRs for Linear issues, MUST include magic keywords in PR body:** `Fixes LOBE-123`, `Closes LOBE-123`, or `Resolves LOBE-123`
### IMPORTANT: Per-Issue Completion Rule
**When working on multiple issues (e.g., parent issue with sub-issues), you MUST update status and add comment for EACH issue IMMEDIATELY after completing it.** Do NOT wait until all issues are done to update them in batch.

View File

@@ -1,6 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { isArc, isSonomaOrLaterSafari } from './platform';
import { isArc, isMacOSWithLargeWindowBorders, isSonomaOrLaterSafari } from './platform';
describe('isSonomaOrLaterSafari', () => {
beforeEach(() => {
@@ -12,6 +12,31 @@ describe('isSonomaOrLaterSafari', () => {
});
});
describe('isMacOSWithLargeWindowBorders', () => {
it('should return true for macOS 10.15+', () => {
vi.stubGlobal('navigator', {
userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',
});
expect(isMacOSWithLargeWindowBorders()).toBe(true);
});
it('should return false for non-macOS userAgent', () => {
vi.stubGlobal('navigator', { userAgent: 'Windows NT 10.0; Win64; x64' });
expect(isMacOSWithLargeWindowBorders()).toBe(false);
});
it('should return false in Electron', () => {
vi.stubGlobal('navigator', {
userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Electron/30.0.0 Safari/537.36',
});
expect(isMacOSWithLargeWindowBorders()).toBe(false);
});
});
it('should return false when userAgent is not Macintosh', () => {
vi.stubGlobal('navigator', { userAgent: 'Windows NT 10.0; Win64; x64' });
expect(isSonomaOrLaterSafari()).toBe(false);

View File

@@ -25,6 +25,28 @@ export const browserInfo = {
export const isMacOS = () => getPlatform() === 'Mac OS';
/**
*
* We can't use it to detect the macOS real version, and we also don't know if it's macOS 26, only an estimated value.
* @returns true if the current browser is macOS and the version is 10.15 or later
*/
export const isMacOSWithLargeWindowBorders = () => {
if (isOnServerSide || typeof navigator === 'undefined') return false;
// keep consistent with the original logic: only for macOS on web (exclude Electron)
const isElectron =
/Electron\//.test(navigator.userAgent) || Boolean((window as any)?.process?.type);
if (isElectron || !isMacOS()) return false;
const match = navigator.userAgent.match(/Mac OS X (\d+)[._](\d+)/);
if (!match) return false;
const majorVersion = parseInt(match[1], 10);
const minorVersion = parseInt(match[2], 10);
return majorVersion >= 10 && minorVersion >= 15;
};
export const isArc = () => {
if (isOnServerSide) return false;
return (

View File

@@ -6,6 +6,7 @@ import { isDesktop } from '@/const/version';
import { useIsDark } from '@/hooks/useIsDark';
import { useGlobalStore } from '@/store/global';
import { systemStatusSelectors } from '@/store/global/selectors';
import { isMacOSWithLargeWindowBorders } from '@/utils/platform';
import { styles } from './DesktopLayoutContainer/style';
@@ -23,12 +24,15 @@ const DesktopLayoutContainer: FC<PropsWithChildren> = ({ children }) => {
);
const innerCssVariables = useMemo<Record<string, string>>(() => {
const borderRadius =
typeof window !== 'undefined' && (window.lobeEnv?.darwinMajorVersion ?? 0) >= 25
? '12px'
: cssVar.borderRadius;
const darwinMajorVersion =
typeof window !== 'undefined' ? (window.lobeEnv?.darwinMajorVersion ?? 0) : 0;
const borderRadius = darwinMajorVersion >= 25 ? '12px' : cssVar.borderRadius;
const borderBottomRightRadius =
darwinMajorVersion >= 26 || isMacOSWithLargeWindowBorders() ? '12px' : borderRadius;
return {
'--container-border-bottom-right-radius': borderBottomRightRadius,
'--container-border-color': isDarkMode ? cssVar.colorBorderSecondary : cssVar.colorBorder,
'--container-border-radius': borderRadius,
};

View File

@@ -11,6 +11,10 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
border: 1px solid var(--container-border-color, ${cssVar.colorBorder});
border-radius: var(--container-border-radius, ${cssVar.borderRadius});
border-end-end-radius: var(
--container-border-bottom-right-radius,
var(--container-border-radius, ${cssVar.borderRadius})
);
background: ${cssVar.colorBgContainer};
`,