From 72e962ef256530fe016033352a282c4edf5686f6 Mon Sep 17 00:00:00 2001 From: Trang Doan Date: Tue, 8 Sep 2026 13:05:13 -0400 Subject: [PATCH 1/8] ENG-2188 Node type settings are spread across seven inner tabs; put them on one page A node type's settings become one vertical page: Identity (Index first, then Description, Tag, Color, Format), Creation, Canvas, Legacy (Specification), the sync-gated Suggestive mode, and Attributes last. Index and Template are drill-down rows on the ENG-2186 primitive, each with its own sub-page. Specification's toggle reads "Enabled" (its lowercase block text stays the storage key via blockKey) and the query builder renders only while it is on. Format loses its DEPRECATED note: Specification is the one in migration. Co-Authored-By: Claude Fable 5.1 --- .../settings/DiscourseNodeSpecification.tsx | 27 +- .../settings/DiscourseNodeSuggestiveRules.tsx | 49 ++- .../components/settings/GrammarNodesRoute.tsx | 26 +- .../src/components/settings/NodeConfig.tsx | 382 ++++++++---------- .../src/components/settings/NodeIndexPage.tsx | 26 ++ .../components/settings/NodeTemplatePage.tsx | 27 ++ .../components/SettingsDrillDownRow.tsx | 31 ++ .../settings/utils/settingsNavigation.ts | 5 + apps/roam/src/styles/settingsStyles.css | 7 + 9 files changed, 326 insertions(+), 254 deletions(-) create mode 100644 apps/roam/src/components/settings/NodeIndexPage.tsx create mode 100644 apps/roam/src/components/settings/NodeTemplatePage.tsx create mode 100644 apps/roam/src/components/settings/components/SettingsDrillDownRow.tsx diff --git a/apps/roam/src/components/settings/DiscourseNodeSpecification.tsx b/apps/roam/src/components/settings/DiscourseNodeSpecification.tsx index ea32cd0e9..e387f6ec3 100644 --- a/apps/roam/src/components/settings/DiscourseNodeSpecification.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeSpecification.tsx @@ -155,7 +155,8 @@ const NodeSpecification = ({ -
- -
+ {enabled && ( +
+ +
+ )} ); }; diff --git a/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx b/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx index 67a546c92..5af703692 100644 --- a/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx @@ -1,5 +1,5 @@ import React, { useState, useMemo } from "react"; -import { Button, Intent } from "@blueprintjs/core"; +import { Button, Collapse, Intent } from "@blueprintjs/core"; import DualWriteBlocksPanel from "./components/EphemeralBlocksPanel"; import getSubTree from "roamjs-components/util/getSubTree"; import { DiscourseNode } from "~/utils/getDiscourseNodes"; @@ -17,6 +17,7 @@ import { TEMPLATE_SETTING_KEYS, } from "~/components/settings/utils/settingKeys"; import { RenderRoamBlock } from "~/utils/roamReactComponents"; +import Description from "~/components/settings/SettingsDescription"; import { ROAM_DOCS, withDocsLink } from "./utils/docs"; const DiscourseNodeSuggestiveRules = ({ @@ -42,6 +43,7 @@ const DiscourseNodeSuggestiveRules = ({ }).uid || "", [nodeUid], ); + const [isTemplateOpen, setIsTemplateOpen] = useState(false); const [isUpdating, setIsUpdating] = useState(false); @@ -68,18 +70,39 @@ const DiscourseNodeSuggestiveRules = ({ }; return ( -
- +
+
+
+
+ {/* Collapse unmounts its children, so the buffer block only exists while open. */} + +
+ +
+
+
= { + [nodeConfigSegmentIds.index]: "Index", + [nodeConfigSegmentIds.template]: "Template", +}; + const GrammarNodesRoute = ({ onloadArgs, }: { @@ -18,7 +26,7 @@ const GrammarNodesRoute = ({ const { segments, goToDepth } = useSettingsNav(); const nodes = getDiscourseNodes().filter(excludeDefaultNodes); - const [nodeTypeUid] = segments; + const [nodeTypeUid, subPage] = segments; const node = nodeTypeUid ? nodes.find((n) => n.type === nodeTypeUid) : undefined; @@ -29,8 +37,10 @@ const GrammarNodesRoute = ({ if (isStalePath) goToDepth(0); }, [isStalePath, goToDepth]); - const resolveLabel = (segment: string): string => - nodes.find((n) => n.type === segment)?.text ?? segment; + const resolveLabel = (segment: string, segmentIndex: number): string => + segmentIndex === 0 + ? (nodes.find((n) => n.type === segment)?.text ?? segment) + : (SUB_PAGE_LABELS[segment] ?? segment); return (
@@ -40,12 +50,16 @@ const GrammarNodesRoute = ({ resolveLabel={resolveLabel} />
- {node ? ( - - ) : ( + {!node ? (
+ ) : subPage === nodeConfigSegmentIds.index ? ( + + ) : subPage === nodeConfigSegmentIds.template ? ( + + ) : ( + )}
diff --git a/apps/roam/src/components/settings/NodeConfig.tsx b/apps/roam/src/components/settings/NodeConfig.tsx index b4114b63b..4f0672a86 100644 --- a/apps/roam/src/components/settings/NodeConfig.tsx +++ b/apps/roam/src/components/settings/NodeConfig.tsx @@ -1,13 +1,9 @@ import React, { useState, useCallback, useEffect, useRef } from "react"; import getDiscourseNodes, { DiscourseNode } from "~/utils/getDiscourseNodes"; -import DualWriteBlocksPanel from "./components/EphemeralBlocksPanel"; import { getSubTree } from "roamjs-components/util"; import Description from "~/components/settings/SettingsDescription"; import { Label, - Tabs, - Tab, - TabId, InputGroup, ControlGroup, Tooltip, @@ -18,8 +14,6 @@ import DiscourseNodeAttributes from "./DiscourseNodeAttributes"; import DiscourseNodeCanvasSettings, { formatHexColor, } from "./DiscourseNodeCanvasSettings"; -import DiscourseNodeIndex from "./DiscourseNodeIndex"; -import { OnloadArgs } from "roamjs-components/types"; import setInputSetting from "roamjs-components/util/setInputSetting"; import { getDiscourseNodeSetting, @@ -30,7 +24,6 @@ import { CANVAS_KEYS, DISCOURSE_NODE_KEYS, SPECIFICATION_KEYS, - TEMPLATE_SETTING_KEYS, } from "~/components/settings/utils/settingKeys"; import DiscourseNodeSuggestiveRules from "./DiscourseNodeSuggestiveRules"; import { getNodeTagStyles } from "~/utils/getDiscourseNodeColors"; @@ -40,6 +33,10 @@ import { DiscourseNodeSelectPanel, } from "./components/BlockPropSettingPanels"; import { ROAM_DOCS, withDocsLink } from "./utils/docs"; +import { SettingsGroup } from "./components/SettingsHeadings"; +import SettingsDrillDownRow from "./components/SettingsDrillDownRow"; +import { useSettingsNav } from "./navigation/SettingsNavContext"; +import { nodeConfigSegmentIds } from "./utils/settingsNavigation"; export const getCleanTagText = (tag: string): string => { return tag.replace(/^#+/, "").trim().toUpperCase(); @@ -168,13 +165,7 @@ const generateTagPlaceholder = (node: DiscourseNode): string => { return `#${nodeTextPrefix}-candidate`; // Evidence = #evi-candidate }; -const NodeConfig = ({ - node, - onloadArgs, -}: { - node: DiscourseNode; - onloadArgs: OnloadArgs; -}) => { +const NodeConfig = ({ node }: { node: DiscourseNode }) => { const getUid = (key: string) => getSubTree({ parentUid: node.type, @@ -184,19 +175,17 @@ const NodeConfig = ({ const descriptionUid = getUid("Description"); const shortcutUid = getUid("Shortcut"); const tagUid = getUid("Tag"); - const templateUid = getUid("Template"); const overlayUid = getUid("Overlay"); const canvasUid = getUid("Canvas"); const graphOverviewUid = getUid("Graph Overview"); const specificationUid = getUid("Specification"); - const indexUid = getUid("Index"); const suggestiveRulesUid = getUid("Suggestive Rules"); const attributeNode = getSubTree({ parentUid: node.type, key: "Attributes", }); - const [selectedTabId, setSelectedTabId] = useState("general"); + const nav = useSettingsNav(); const [tagError, setTagError] = useState(""); const [formatError, setFormatError] = useState(""); const [shortcutError, setShortcutError] = useState(""); @@ -302,220 +291,169 @@ const NodeConfig = ({ ); return ( - <> - setSelectedTabId(id)} - selectedTabId={selectedTabId} - renderActiveTabPanelOnly={true} - > - - - -
- -
- -
- } - /> - + + - -
- } + description={`The saved list of all ${node.text} pages \u2014 which pages appear and which columns show.`} + buttonText={`See all ${node.text} nodes`} + onClick={() => nav.push(nodeConfigSegmentIds.index)} + /> + + + - - - - - } + description={withDocsLink( + `The format ${node.text} pages should have.`, + ROAM_DOCS.grammarNodes, + )} + settingKeys={[DISCOURSE_NODE_KEYS.format]} + initialValue={node.format} + error={formatError} + onChange={setFormatValue} + order={3} + parentUid={node.type} + uid={formatUid} + /> + + + + - - - - } + description={withDocsLink( + `The template that auto fills ${node.text} page when generated.`, + ROAM_DOCS.creatingNodes, + )} + buttonText="Edit template" + onClick={() => nav.push(nodeConfigSegmentIds.template)} /> - - >( - node.type, - [DISCOURSE_NODE_KEYS.attributes], - )} - /> - c.text)} - initialValue={ - getDiscourseNodeSetting(node.type, [ - DISCOURSE_NODE_KEYS.overlay, - ]) ?? "" - } - order={0} - parentUid={node.type} - uid={overlayUid} - /> - - } + + + + + + + + + + + + {isSyncEnabled() && ( + + + + )} + + + >( + node.type, + [DISCOURSE_NODE_KEYS.attributes], + )} /> - - - - + c.text)} + initialValue={ + getDiscourseNodeSetting(node.type, [ + DISCOURSE_NODE_KEYS.overlay, + ]) ?? "" } + order={0} + parentUid={node.type} + uid={overlayUid} /> - {isSyncEnabled() && ( - - - - } - /> - )} - - + + ); }; diff --git a/apps/roam/src/components/settings/NodeIndexPage.tsx b/apps/roam/src/components/settings/NodeIndexPage.tsx new file mode 100644 index 000000000..c39558a82 --- /dev/null +++ b/apps/roam/src/components/settings/NodeIndexPage.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import { getSubTree } from "roamjs-components/util"; +import { OnloadArgs } from "roamjs-components/types"; +import { DiscourseNode } from "~/utils/getDiscourseNodes"; +import DiscourseNodeIndex from "./DiscourseNodeIndex"; + +const NodeIndexPage = ({ + node, + onloadArgs, +}: { + node: DiscourseNode; + onloadArgs: OnloadArgs; +}): JSX.Element => { + const indexUid = getSubTree({ parentUid: node.type, key: "Index" }).uid; + return ( +
+ +
+ ); +}; + +export default NodeIndexPage; diff --git a/apps/roam/src/components/settings/NodeTemplatePage.tsx b/apps/roam/src/components/settings/NodeTemplatePage.tsx new file mode 100644 index 000000000..94947976d --- /dev/null +++ b/apps/roam/src/components/settings/NodeTemplatePage.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import { getSubTree } from "roamjs-components/util"; +import { DiscourseNode } from "~/utils/getDiscourseNodes"; +import DualWriteBlocksPanel from "./components/EphemeralBlocksPanel"; +import { TEMPLATE_SETTING_KEYS } from "~/components/settings/utils/settingKeys"; +import { ROAM_DOCS, withDocsLink } from "./utils/docs"; + +const NodeTemplatePage = ({ node }: { node: DiscourseNode }): JSX.Element => { + const templateUid = getSubTree({ parentUid: node.type, key: "Template" }).uid; + return ( +
+ +
+ ); +}; + +export default NodeTemplatePage; diff --git a/apps/roam/src/components/settings/components/SettingsDrillDownRow.tsx b/apps/roam/src/components/settings/components/SettingsDrillDownRow.tsx new file mode 100644 index 000000000..1bb0b2c84 --- /dev/null +++ b/apps/roam/src/components/settings/components/SettingsDrillDownRow.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import { Button, Intent, Label } from "@blueprintjs/core"; +import Description from "~/components/settings/SettingsDescription"; + +const SettingsDrillDownRow = ({ + title, + description, + buttonText, + onClick, +}: { + title: string; + description: React.ReactNode; + buttonText: string; + onClick: () => void; +}): JSX.Element => ( + +); + +export default SettingsDrillDownRow; diff --git a/apps/roam/src/components/settings/utils/settingsNavigation.ts b/apps/roam/src/components/settings/utils/settingsNavigation.ts index 2d27b08da..bcef6a444 100644 --- a/apps/roam/src/components/settings/utils/settingsNavigation.ts +++ b/apps/roam/src/components/settings/utils/settingsNavigation.ts @@ -14,6 +14,11 @@ export type SettingsNavAction = | { type: "pop" } | { type: "truncate"; depth: number }; +export const nodeConfigSegmentIds = { + index: "index", + template: "template", +} as const; + export const rootPath = (tabId: string): SettingsPath => [tabId]; export const tabIdOf = (path: SettingsPath): string => path[0] ?? ""; diff --git a/apps/roam/src/styles/settingsStyles.css b/apps/roam/src/styles/settingsStyles.css index 4a76d35a3..c6d345e00 100644 --- a/apps/roam/src/styles/settingsStyles.css +++ b/apps/roam/src/styles/settingsStyles.css @@ -81,3 +81,10 @@ .dg-settings-page-header__crumb { cursor: pointer; } + +.dg-settings-node-page { + display: flex; + flex-direction: column; + gap: 44px; + padding: 2px; +} From fabb50c3cd73aa9290a7b3ddccaeec7322b23a4d Mon Sep 17 00:00:00 2001 From: Trang Doan Date: Mon, 31 Aug 2026 11:27:14 -0400 Subject: [PATCH 2/8] ENG-2185 Move export settings out of Settings into the Export panel The 7 export controls were used by exactly one surface but lived in Settings, so changing an option meant leaving the Export flow, opening Settings, and coming back. Move them into a collapsed "Export options" disclosure at the bottom of the Export dialog's Export tab, and remove the Advanced > Export tab that ENG-2186 parked in Settings for this change to take out. The controls, their storage keys, and the read path in getExportSettings are unchanged, so saved values persist and export behaviour is untouched. The advancedExport tab id goes with it, and the saved "discourse-graph-export" deep link now resolves to the default tab instead of a tab that no longer renders. Co-Authored-By: Claude Opus 5 --- apps/roam/src/components/Export.tsx | 66 +++++++++++++++---- .../ExportSettings.tsx => ExportOptions.tsx} | 10 +-- .../roam/src/components/settings/Settings.tsx | 9 --- .../components/settings/utils/settingsTabs.ts | 4 +- .../roam/guides/sharing-discourse-graph.md | 2 +- 5 files changed, 63 insertions(+), 28 deletions(-) rename apps/roam/src/components/{settings/ExportSettings.tsx => ExportOptions.tsx} (94%) diff --git a/apps/roam/src/components/Export.tsx b/apps/roam/src/components/Export.tsx index 0f1c350fb..4941b4dd6 100644 --- a/apps/roam/src/components/Export.tsx +++ b/apps/roam/src/components/Export.tsx @@ -15,8 +15,9 @@ import { RadioGroup, Radio, FormGroup, + Collapse, } from "@blueprintjs/core"; -import React, { useState, useEffect, useMemo, FormEvent } from "react"; +import React, { useState, useEffect, useMemo, useRef, FormEvent } from "react"; import MenuItemSelect from "roamjs-components/components/MenuItemSelect"; import { saveAs } from "file-saver"; import { Result } from "roamjs-components/types/query-builder"; @@ -91,7 +92,12 @@ import { type NodeUidWithType, } from "~/utils/publishNodesToGroups"; import { getLoggedInClient, getSupabaseContext } from "~/utils/supabaseContext"; -import { isNodeSharingEnabled } from "~/components/settings/utils/accessors"; +import { + bulkReadSettings, + isNodeSharingEnabled, +} from "~/components/settings/utils/accessors"; +import refreshConfigTree from "~/utils/refreshConfigTree"; +import ExportOptions from "./ExportOptions"; const ExportProgress = ({ id }: { id: string }) => { const [progress, setProgress] = useState(0); @@ -225,6 +231,22 @@ const ExportDialog: ExportDialogComponent = ({ if (initialPanel) setSelectedTabId(INITIAL_PANEL_TO_TAB_ID[initialPanel]); }, [initialPanel, sharingEnabled]); const [includeDiscourseContext, setIncludeDiscourseContext] = useState(false); + const [exportOptionsOpen, setExportOptionsOpen] = useState(false); + const exportOptionsOpened = useRef(false); + const exportGlobalSettings = useMemo( + () => bulkReadSettings().globalSettings, + [], + ); + + // The export option panels write legacy config blocks alongside block props, so + // the cached config tree has to be refreshed the way SettingsDialog does. Gated + // on the section having been opened because refreshConfigTree re-reads every + // node page and re-registers the datalog translators, which is too heavy to run + // on every close of a dialog that is opened for each export. + const closeDialog = (): void => { + if (exportOptionsOpened.current) refreshConfigTree(); + onClose(); + }; const [gitHubAccessToken, setGitHubAccessToken] = useState( getSetting("oauth-github", null), ); @@ -756,7 +778,7 @@ const ExportDialog: ExportDialogComponent = ({ }); } finally { setLoading(false); - onClose(); + closeDialog(); } }; @@ -796,7 +818,7 @@ const ExportDialog: ExportDialogComponent = ({ fileCount: files.length, }); } - onClose(); + closeDialog(); } catch (e) { setError("Failed to export files."); posthog.capture("Export Dialog: Export Failed", { @@ -888,7 +910,7 @@ const ExportDialog: ExportDialogComponent = ({ : "success", id: "query-builder-publish-success", }); - if (hasPublishedNodes) onClose(); + if (hasPublishedNodes) closeDialog(); } catch (e) { internalError({ error: e as Error, @@ -981,11 +1003,33 @@ const ExportDialog: ExportDialogComponent = ({ + +
+
{error} -
- -
-
+ +
+ +
+
From f66ae1389b938f657ceddbfd830e3cbaf6b9c810 Mon Sep 17 00:00:00 2001 From: Trang Doan Date: Sat, 5 Sep 2026 19:12:07 -0400 Subject: [PATCH 6/8] ENG-2185 Discourse context on its own line above the export options row Review feedback: the checkbox sits right-aligned on the line above; the line below is the Export options toggle on the left and the result count on the right. Co-Authored-By: Claude Fable 5.1 --- apps/roam/src/components/Export.tsx | 58 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/apps/roam/src/components/Export.tsx b/apps/roam/src/components/Export.tsx index 6d76d657b..e8ab30a57 100644 --- a/apps/roam/src/components/Export.tsx +++ b/apps/roam/src/components/Export.tsx @@ -978,7 +978,30 @@ const ExportDialog: ExportDialogComponent = ({ /> -
+
+ + { + setIncludeDiscourseContext( + (e.target as HTMLInputElement).checked, + ); + }} + labelElement={ + + Discourse context + + } + /> + +
+
From 9430d47725e9c0849a8b4c9b4b5772ccde0b51b1 Mon Sep 17 00:00:00 2001 From: Trang Doan Date: Mon, 7 Sep 2026 18:20:13 -0400 Subject: [PATCH 7/8] ENG-2185 Drop unit tests and trim comments to the decisions they record Co-Authored-By: Claude Fable 5.1 --- apps/roam/src/components/Export.tsx | 18 +++++------------- .../components/settings/utils/settingsTabs.ts | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/apps/roam/src/components/Export.tsx b/apps/roam/src/components/Export.tsx index e8ab30a57..6d96250ac 100644 --- a/apps/roam/src/components/Export.tsx +++ b/apps/roam/src/components/Export.tsx @@ -234,20 +234,15 @@ const ExportDialog: ExportDialogComponent = ({ const [includeDiscourseContext, setIncludeDiscourseContext] = useState(false); const [exportOptionsOpen, setExportOptionsOpen] = useState(false); const exportOptionsOpened = useRef(false); - // Re-read on every open rather than once at mount: Collapse unmounts the option - // panels while closed, so each open seeds them from the current stored values - // instead of whatever the dialog saw when it first rendered. + // Collapse unmounts the panels while closed, so each open seeds them from current values. const exportGlobalSettings = useMemo( () => bulkReadSettings().globalSettings, // eslint-disable-next-line react-hooks/exhaustive-deps [exportOptionsOpen], ); - // The export option panels write legacy config blocks alongside block props, so - // the cached config tree has to be refreshed the way SettingsDialog does. Gated - // on the section having been opened because refreshConfigTree re-reads every - // node page and re-registers the datalog translators, which is too heavy to run - // on every close of a dialog that is opened for each export. + // Option panels also write legacy config blocks, so refresh the tree as SettingsDialog + // does, but only if they were opened: refreshConfigTree re-reads every node page. const closeDialog = (): void => { if (exportOptionsOpened.current) refreshConfigTree(); onClose(); @@ -1055,11 +1050,8 @@ const ExportDialog: ExportDialogComponent = ({ // eslint-disable-next-line @typescript-eslint/no-misused-promises setTimeout(async () => { try { - // The export reads settings inside its callback, and the number - // and select panels defer their write behind a short timer. The - // await matters as much as the flush: committing only starts the - // Roam block update, so an option edited a moment ago would - // otherwise still read as its previous value here. + // Awaited, not just fired: a commit only starts the Roam update, and an option edited + // a moment ago would otherwise still read as its previous value here. await flushPendingSettingWrites(); const exportType = exportTypes.find( (e) => e.name === activeExportType, diff --git a/apps/roam/src/components/settings/utils/settingsTabs.ts b/apps/roam/src/components/settings/utils/settingsTabs.ts index 77a23f94f..0c0e8e163 100644 --- a/apps/roam/src/components/settings/utils/settingsTabs.ts +++ b/apps/roam/src/components/settings/utils/settingsTabs.ts @@ -23,7 +23,7 @@ export const SETTINGS_TAB_ALIASES: Record = { "canvas-shortcuts-personal-settings": SETTINGS_TAB_IDS.featuresCanvas, "left-sidebar-personal-settings": SETTINGS_TAB_IDS.featuresLeftSidebar, "left-sidebar-global-settings": SETTINGS_TAB_IDS.featuresLeftSidebar, - // Export options left Settings in ENG-2185; they now live in the Export dialog. + // Export options now live in the Export dialog. "discourse-graph-export": SETTINGS_TAB_IDS.preferencesGeneral, "discourse-nodes": SETTINGS_TAB_IDS.grammarNodes, "discourse-relations": SETTINGS_TAB_IDS.grammarRelations, From 5b39f50174d0cb76b23fa1be016fcee9e70bb5bf Mon Sep 17 00:00:00 2001 From: Trang Doan Date: Wed, 9 Sep 2026 15:35:47 -0400 Subject: [PATCH 8/8] ENG-2185 Put Discourse context inside Export options with an info tooltip Co-Authored-By: Claude Fable 5.1 --- apps/roam/src/components/Export.tsx | 44 ++++++++++++----------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/apps/roam/src/components/Export.tsx b/apps/roam/src/components/Export.tsx index 6d96250ac..495903500 100644 --- a/apps/roam/src/components/Export.tsx +++ b/apps/roam/src/components/Export.tsx @@ -9,12 +9,10 @@ import { ProgressBar, Toaster, Toast, - Tooltip, Tab, Tabs, RadioGroup, Radio, - FormGroup, Collapse, } from "@blueprintjs/core"; import React, { useState, useEffect, useMemo, useRef, FormEvent } from "react"; @@ -99,6 +97,7 @@ import { import refreshConfigTree from "~/utils/refreshConfigTree"; import { flushPendingSettingWrites } from "~/utils/pendingSettingWrites"; import ExportOptions from "./ExportOptions"; +import Description from "~/components/settings/SettingsDescription"; const ExportProgress = ({ id }: { id: string }) => { const [progress, setProgress] = useState(0); @@ -973,30 +972,7 @@ const ExportDialog: ExportDialogComponent = ({ /> -
- - { - setIncludeDiscourseContext( - (e.target as HTMLInputElement).checked, - ); - }} - labelElement={ - - Discourse context - - } - /> - -
-
+