A trailing configure button on the rail — outside the sortable list and the digit shortcuts — opens a dialog that toggles each surface. The choice is stored as the hidden set so newly added surfaces appear for everyone, and the rail and the mod+alt+digit switcher share the same visibility filter, so badges and shortcuts always agree. Hidden surfaces keep their data and stay reachable from the command palette.
79 lines
3.1 KiB
TypeScript
79 lines
3.1 KiB
TypeScript
import React from 'react';
|
|
import { useI18n } from '@/lib/i18n';
|
|
import { useUIStore } from '@/stores/useUIStore';
|
|
import { SettingsCheckboxRow } from '@/components/sections/shared/SettingsSection';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from '@/components/ui/dialog';
|
|
import { sortContextSurfaces } from '@/lib/surfaces/registry';
|
|
|
|
/**
|
|
* Which surfaces the context rail shows. Everything is on by default and the
|
|
* choice is stored as the *hidden* set, so a surface added in a later release
|
|
* appears for everyone rather than staying invisible to whoever had saved
|
|
* settings before it existed. Hidden surfaces also leave the digit shortcuts
|
|
* (the rail and the shortcut share one visibility filter).
|
|
*/
|
|
export const ContextRailSurfacesDialog: React.FC<{
|
|
open: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
}> = ({ open, onOpenChange }) => {
|
|
const { t } = useI18n();
|
|
const contextRailOrder = useUIStore((state) => state.contextRailOrder);
|
|
const hidden = useUIStore((state) => state.contextRailHiddenSurfaces);
|
|
const setSurfaceVisible = useUIStore((state) => state.setContextRailSurfaceVisible);
|
|
const setHiddenSurfaces = useUIStore((state) => state.setContextRailHiddenSurfaces);
|
|
|
|
// The full registry in the user's rail order — including surfaces a runtime
|
|
// filter currently drops, so a choice made on desktop is editable anywhere.
|
|
const surfaces = React.useMemo(() => sortContextSurfaces(contextRailOrder), [contextRailOrder]);
|
|
|
|
const allVisible = hidden.length === 0;
|
|
const noneVisible = surfaces.every((surface) => hidden.includes(surface.id));
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="max-w-md">
|
|
<DialogHeader>
|
|
<DialogTitle>{t('contextRail.configure.dialogTitle')}</DialogTitle>
|
|
<DialogDescription>{t('contextRail.configure.dialogDescription')}</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="flex flex-col">
|
|
{surfaces.map((surface) => (
|
|
<SettingsCheckboxRow
|
|
key={surface.id}
|
|
settingsItem={`layout.context-rail.surface.${surface.id}`}
|
|
checked={!hidden.includes(surface.id)}
|
|
onChange={(checked) => setSurfaceVisible(surface.id, checked)}
|
|
label={t(surface.labelKey)}
|
|
ariaLabel={t(surface.labelKey)}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
{!allVisible ? (
|
|
<div className="flex items-center justify-between border-t pt-3">
|
|
{noneVisible ? (
|
|
<span className="text-xs text-destructive">{t('contextRail.configure.noneWarning')}</span>
|
|
) : <span />}
|
|
<Button
|
|
variant="link"
|
|
size="xs"
|
|
onClick={() => setHiddenSurfaces([])}
|
|
className="normal-case text-muted-foreground hover:text-foreground"
|
|
>
|
|
{t('contextRail.configure.showAll')}
|
|
</Button>
|
|
</div>
|
|
) : null}
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
};
|