Keep workspace focus mode scoped and easy to exit (#2151)
* fix(workspace): keep focus mode scoped and easy to exit Route focus mode through the active workspace so persisted state cannot hide chrome on settings or other screens. Add a visible exit control and keep desktop window chrome aligned and visually quiet. * fix(app): clarify muted chrome semantics
This commit is contained in:
@@ -45,12 +45,14 @@ function MobileMenuIcon({ color }: { color: string }) {
|
||||
|
||||
function SidebarMenuToggleButton({
|
||||
isMobile,
|
||||
extraMutedIdleIcon = false,
|
||||
resolvedStyle,
|
||||
tooltipSide = "right",
|
||||
testID = "menu-button",
|
||||
nativeID = "menu-button",
|
||||
}: Omit<SidebarMenuToggleProps, "style"> & {
|
||||
isMobile: boolean;
|
||||
extraMutedIdleIcon?: boolean;
|
||||
resolvedStyle: StyleProp<ViewStyle>;
|
||||
}) {
|
||||
const { theme } = useUnistyles();
|
||||
@@ -83,7 +85,12 @@ function SidebarMenuToggleButton({
|
||||
accessibilityState={accessibilityState}
|
||||
>
|
||||
{({ hovered, pressed }) => {
|
||||
const color = hovered || pressed ? theme.colors.foreground : theme.colors.foregroundMuted;
|
||||
let color = extraMutedIdleIcon
|
||||
? theme.colors.foregroundExtraMuted
|
||||
: theme.colors.foregroundMuted;
|
||||
if (hovered || pressed) {
|
||||
color = theme.colors.foreground;
|
||||
}
|
||||
return isMobile ? (
|
||||
<MobileMenuIcon color={color} />
|
||||
) : (
|
||||
@@ -121,7 +128,14 @@ export function SidebarMenuToggle({ style, ...props }: SidebarMenuToggleProps =
|
||||
|
||||
export function WindowSidebarMenuToggle({ style, ...props }: SidebarMenuToggleProps = {}) {
|
||||
const resolvedStyle = useMemo(() => [styles.leadingToggle, style], [style]);
|
||||
return <SidebarMenuToggleButton {...props} isMobile={false} resolvedStyle={resolvedStyle} />;
|
||||
return (
|
||||
<SidebarMenuToggleButton
|
||||
{...props}
|
||||
isMobile={false}
|
||||
extraMutedIdleIcon
|
||||
resolvedStyle={resolvedStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function MenuHeader({ title, rightContent, borderless }: MenuHeaderProps) {
|
||||
|
||||
@@ -123,6 +123,7 @@ interface SplitContainerProps {
|
||||
onReorderTabsInPane: (paneId: string, tabIds: string[]) => void;
|
||||
renderPaneEmptyState?: () => ReactNode;
|
||||
focusModeEnabled?: boolean;
|
||||
onExitFocusMode: () => void;
|
||||
}
|
||||
|
||||
interface WorkspaceTabDragData {
|
||||
@@ -390,6 +391,7 @@ export function SplitContainer({
|
||||
onReorderTabsInPane,
|
||||
renderPaneEmptyState = () => null,
|
||||
focusModeEnabled,
|
||||
onExitFocusMode,
|
||||
}: SplitContainerProps) {
|
||||
const inheritedWindowChromeCorners = useWindowChromeCorners();
|
||||
const windowChromeCorners = focusModeEnabled ? inheritedWindowChromeCorners : "none";
|
||||
@@ -611,6 +613,8 @@ export function SplitContainer({
|
||||
dropPreview={dropPreview}
|
||||
tabDropPreview={tabDropPreview}
|
||||
windowChromeCorners={splitRoot.usesFallbackStrip ? "none" : windowChromeCorners}
|
||||
focusModeEnabled={focusModeEnabled}
|
||||
onExitFocusMode={onExitFocusMode}
|
||||
/>
|
||||
<DragOverlay dropAnimation={null}>
|
||||
{activeDragTabId ? (
|
||||
@@ -755,6 +759,8 @@ function SplitNodeView({
|
||||
dropPreview,
|
||||
tabDropPreview,
|
||||
windowChromeCorners,
|
||||
focusModeEnabled,
|
||||
onExitFocusMode,
|
||||
}: SplitNodeViewProps) {
|
||||
const groupId = node.kind === "group" ? node.group.id : null;
|
||||
const groupDirection = node.kind === "group" ? node.group.direction : null;
|
||||
@@ -808,6 +814,8 @@ function SplitNodeView({
|
||||
showDropZones={showDropZones}
|
||||
dropPreview={dropPreview}
|
||||
tabDropPreview={tabDropPreview}
|
||||
focusModeEnabled={focusModeEnabled}
|
||||
onExitFocusMode={onExitFocusMode}
|
||||
/>
|
||||
</WindowChromeRegion>
|
||||
);
|
||||
@@ -857,6 +865,8 @@ function SplitNodeView({
|
||||
dropPreview={dropPreview}
|
||||
tabDropPreview={tabDropPreview}
|
||||
windowChromeCorners={windowChromeCorners}
|
||||
focusModeEnabled={focusModeEnabled}
|
||||
onExitFocusMode={onExitFocusMode}
|
||||
/>
|
||||
</SplitGroupChild>
|
||||
{index < node.group.children.length - 1 ? (
|
||||
@@ -908,6 +918,8 @@ function SplitPaneView({
|
||||
showDropZones,
|
||||
dropPreview,
|
||||
tabDropPreview,
|
||||
focusModeEnabled,
|
||||
onExitFocusMode,
|
||||
}: SplitPaneViewProps) {
|
||||
const { theme: _theme } = useUnistyles();
|
||||
const paneRef = useRef<View | null>(null);
|
||||
@@ -1043,6 +1055,8 @@ function SplitPaneView({
|
||||
tabDropPreviewIndex={
|
||||
tabDropPreview?.paneId === pane.id ? tabDropPreview.indicatorIndex : null
|
||||
}
|
||||
focusModeEnabled={Boolean(focusModeEnabled)}
|
||||
onExitFocusMode={onExitFocusMode}
|
||||
/>
|
||||
</WindowChromeSafeArea>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user