dialogs-slice
Skill627 starsChanged 8 days agoMITView on GitHub
Open and close a Ledger Wallet Desktop global dialog through the shared `dialogs` Redux slice (`DIALOG_IDS`, `openDialog`, `selectIsDialogOpen`) and mount it once in `GlobalDialogs`. Use when adding a desktop dialog mounted at the app root and opened from a distant part of the tree, or when editing `apps/ledger-live-desktop/src/renderer/reducers/dialogs.ts`, `src/mvvm/features/GlobalDialogs/` or a feature `*Dialog.ts` helper.
In this repository70 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- analyticsSkill
- batch-feature-devSkill
- ci-runnersSkill
- ci-workflow-refsSkill
- cleanupSkill
- client-idsSkill
- cloud-sync-moduleSkill
- codeownershipSkill
- coin-families-contractSkill
- coin-modulesSkill
- commentsSkill
- configurationSkill
- console-logSkill
- create-changesetSkill
- create-prSkill
- data-layer-advancedSkill
- debug-rn-native-crashSkill
- dependency-patchesSkill
- detect-data-leaksSkill
- device-intent-executorSkill
- devtools-import-boundarySkill
- docs-migrateSkill
- docs-update-or-createSkill
- domain-dataSkill
- e2e-desktop-add-or-updateSkill
- e2e-desktop-onboardSkill
- e2e-earnSkill
- e2e-mobile-add-or-updateSkill
- e2e-mobile-onboardSkill
- e2e-swapSkill
- errorsSkill
- feature-devSkill
- fix-ciSkill
- flow-packageSkill
- get-pr-commentsSkill
- git-conventionsSkill
- i18n-keysSkill
- impacting-prsSkill
- knip-migrationSkill
- ldls-nativeSkill
- ldls-webSkill
- ledger-wallet-cliSkill
- legacy-migrationSkill
- mvvm-architectureSkill
- new-packageSkill
- package-public-apiSkill
- pnpm-resolutionSkill
- prefer-set-hasSkill
- pre-reviewSkill
- react-generalSkill
- rebuild-to-fix-lib-import-errorsSkill
- remove-feature-flagSkill
- run-buildsSkill
- run-e2e-ciSkill
- runner-imagesSkill
- run-testsSkill
- slack-pr-messageSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 2 are distinctive, and 9 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Use this pattern for dialogs that are:
- Very specific: line 17
Do NOT use this for dialogs that are local to a single component or screen -- prefer a simple useState instead.
- Very specific: line 30
Add the new ID to the DIALOG_IDS array in renderer/reducers/dialogs.ts.
- Very specific: line 39
Create myFeature/myNewDialog.ts in the feature folder:
- Very specific: line 72
Add the dialog component to mvvm/features/GlobalDialogs/index.tsx, lazy-loaded and in its own Suspense like the dialogs already there.
- Distinctive: line 99
NEVER create a dedicated Redux slice just for dialog open/close state
- Very specific: line 100
NEVER use this pattern for dialogs local to a single component -- use useState instead
- Very specific: line 101
ALWAYS add new dialog IDs to the DIALOG_IDS array (the type is derived automatically)
- Very specific: line 102
ALWAYS use SCREAMING_SNAKE_CASE for dialog IDs
- Very specific: line 103
ALWAYS mount new global dialogs in GlobalDialogs/index.tsx, not directly in Default.tsx
- Very specific: line 105
No modification to reducers/index.ts or Default.tsx is needed when adding new dialogs
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Global Dialogs Slice Pattern
Centralized Redux state for global dialog open/close, avoiding one slice per dialog.
When to use
Use this pattern for dialogs that are:
- Mounted at the app root (e.g. in
Default.tsx) - Triggered from distant parts of the component tree (e.g. a settings button opening a dialog rendered at root level)
Do NOT use this for dialogs that are local to a single component or screen -- prefer a simple useState instead.
Architecture
- One shared slice:
renderer/reducers/dialogs.tsmanages all global dialog states via aRecord<DialogId, boolean> - Single source of truth:
DIALOG_IDSruntime array defines all IDs;DialogIdtype is derived from it via(typeof DIALOG_IDS)[number] - Feature wrappers: Each feature creates a thin
*Dialog.tsfile that re-exports typed helpers bound to its ID - Single mount point:
mvvm/features/GlobalDialogs/index.tsxrenders all global dialog components at the app root
Adding a new global dialog
Step 1: Register the dialog ID
Add the new ID to the DIALOG_IDS array in renderer/reducers/dialogs.ts. The DialogId type updates automatically:
export const DIALOG_IDS = ["RELEASE_NOTES", "MY_NEW_DIALOG"] as const;
// DialogId is now "RELEASE_NOTES" | "MY_NEW_DIALOG"Step 2: Create the feature dialog file
Create myFeature/myNewDialog.ts in the feature folder:
import {
openDialog,
closeDialog,
selectIsDialogOpen,
type DialogId,
} from "~/renderer/reducers/dialogs";
import type { State } from "~/renderer/reducers";
const DIALOG_ID: DialogId = "MY_NEW_DIALOG";
export const openMyNewDialog = () => openDialog(DIALOG_ID);
export const closeMyNewDialog = () => closeDialog(DIALOG_ID);
export const selectIsMyNewDialogOpen = (state: State) => selectIsDialogOpen(state, DIALOG_ID);Step 3: Use in the view model
import { selectIsMyNewDialogOpen, closeMyNewDialog } from "../myNewDialog";
const useMyNewDialogViewModel = () => {
const isOpen = useSelector(selectIsMyNewDialogOpen);
const dispatch = useDispatch();
const onClose = useCallback(() => dispatch(closeMyNewDialog()), [dispatch]);
return { isOpen, onClose };
};Step 4: Mount in GlobalDialogs
Add the dialog component to
mvvm/features/GlobalDialogs/index.tsx,
lazy-loaded and in its own Suspense like the dialogs already there. A sketch of that file:
const MyNewDialog = lazy(() => import("LLD/features/MyFeature"));
const GlobalDialogs = () => (
<>
{/* ...existing dialogs */}
<Suspense fallback={null}>
<MyNewDialog />
</Suspense>
</>
);Step 5: Trigger from anywhere
import { openMyNewDialog } from "LLD/features/MyFeature/myNewDialog";
dispatch(openMyNewDialog());Rules
- NEVER create a dedicated Redux slice just for dialog open/close state
- NEVER use this pattern for dialogs local to a single component -- use
useStateinstead - ALWAYS add new dialog IDs to the
DIALOG_IDSarray (the type is derived automatically) - ALWAYS use SCREAMING_SNAKE_CASE for dialog IDs
- ALWAYS mount new global dialogs in
GlobalDialogs/index.tsx, not directly inDefault.tsx - Feature dialog files should only contain the ID constant and re-exported typed helpers
- No modification to
reducers/index.tsorDefault.tsxis needed when adding new dialogs
Reference
- Slice:
apps/ledger-live-desktop/src/renderer/reducers/dialogs.ts - Mount point:
apps/ledger-live-desktop/src/mvvm/features/GlobalDialogs/index.tsx - Example:
apps/ledger-live-desktop/src/mvvm/features/ReleaseNotes/releaseNotesDialog.ts
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

