diff --git a/web-client/src/ui/doc/Doc.css b/web-client/src/ui/doc/Doc.css index 031ddf2d..36905e2d 100644 --- a/web-client/src/ui/doc/Doc.css +++ b/web-client/src/ui/doc/Doc.css @@ -1,8 +1,14 @@ #doc-container { display: flex; + flex-direction: column; + height: 100%; --note-min-width: 48px; } +#doc-content-container { + display: flex; +} + #doc-scroll { height: 100%; /* make document scrollable */ @@ -18,7 +24,10 @@ } #doc-end { - height: 200px; + flex: 1; + text-align: center; + padding: 32px; + color: #888888; } #doc-side { @@ -157,3 +166,8 @@ padding: 4px 0 4px 4px; word-break: break-word; } + +.doc-preface-block { + padding: 4px 0px 4px 8px; + box-sizing: border-box; +} diff --git a/web-client/src/ui/doc/DocController.ts b/web-client/src/ui/doc/DocController.ts index c774dd1e..e2344336 100644 --- a/web-client/src/ui/doc/DocController.ts +++ b/web-client/src/ui/doc/DocController.ts @@ -17,6 +17,7 @@ import { Debouncer } from "low/utils"; import { GameCoord } from "low/compiler.g"; import { + DocContainerId, DocLog, DocScrollId, findLineByIndex, @@ -146,7 +147,7 @@ export class DocController { needUpdateCurrentLine = true; } else { const { scrollTop, scrollBottom } = scrollView; - const containerOffsetY = getScrollContainerOffsetY(); + const containerOffsetY = getScrollContainerOffsetY(DocContainerId); const { scrollTop: currentLineTop, scrollBottom: currentLineBottom, @@ -251,7 +252,7 @@ export class DocController { // Scroll the current line to visible const { scrollTop, scrollBottom } = scrollView; - const containerOffsetY = getScrollContainerOffsetY(); + const containerOffsetY = getScrollContainerOffsetY(DocContainerId); const { scrollTop: currentLineTop, scrollBottom: currentLineBottom } = getLineScrollView(newCurrentLine, containerOffsetY); diff --git a/web-client/src/ui/doc/DocLine.tsx b/web-client/src/ui/doc/DocLine.tsx index 73158d2e..26f96426 100644 --- a/web-client/src/ui/doc/DocLine.tsx +++ b/web-client/src/ui/doc/DocLine.tsx @@ -9,8 +9,9 @@ import { DocDiagnostic } from "low/compiler.g"; import { useActions } from "low/store"; import { Rich } from "./Rich"; -import { DocLineContainerClass } from "./utils"; +import { DocLineContainerClass, findLineByIndex } from "./utils"; import { Poor } from "./Poor"; +import { updateNotePositions } from "./updateNotePositions"; /// One line in the document type DocLineProps = { @@ -63,6 +64,10 @@ export const DocLine: React.FC = ({ section: sectionIndex, line: lineIndex, }); + const line = findLineByIndex(sectionIndex, lineIndex); + if (line) { + updateNotePositions(line); + } }} > {counterText && ( diff --git a/web-client/src/ui/doc/DocRoot.tsx b/web-client/src/ui/doc/DocRoot.tsx index 844bf25e..5cda7345 100644 --- a/web-client/src/ui/doc/DocRoot.tsx +++ b/web-client/src/ui/doc/DocRoot.tsx @@ -11,6 +11,7 @@ import { DocLine } from "./DocLine"; import { DocSection } from "./DocSection"; import { DocContainerId, + DocContentContainerId, DocLog, DocScrollId, resolveTag, @@ -19,6 +20,7 @@ import { import { DocNoteBlock, DocNoteBlockProps } from "./DocNoteBlock"; import { DocNoteContainerId } from "./updateNotePositions"; import { DocController, initDocController } from "./DocController"; +import { Poor } from "./Poor"; export const DocRoot: React.FC = () => { const { isEditingLayout } = useSelector(viewSelector); @@ -91,49 +93,64 @@ const DocInternal: React.FC = ({ document, controller }) => { }} >
-
- {document.route.map(({ name, lines }, i) => ( - - {lines.map((line, j) => ( - - ))} - +
+ {document.preface.map((text, i) => ( +
+ +
))} -
- You have reached the end of the document :)) +
+
+
+ {document.route.map(({ name, lines }, i) => ( + + {lines.map((line, j) => ( + + ))} + + ))} +
+
+ {flatNotes.map((props, i) => ( + + ))}
-
- {flatNotes.map((props, i) => ( - - ))} +
+ There's nothing more to see past this point.
diff --git a/web-client/src/ui/doc/findVisibleLines.ts b/web-client/src/ui/doc/findVisibleLines.ts index 5ceea87a..e600174c 100644 --- a/web-client/src/ui/doc/findVisibleLines.ts +++ b/web-client/src/ui/doc/findVisibleLines.ts @@ -24,7 +24,7 @@ export const findVisibleLines = (): HTMLElement[] => { if (!containerElement) { return []; } - const containerOffsetY = getScrollContainerOffsetY(); + const containerOffsetY = getScrollContainerOffsetY(DocContainerId); // get all lines // This is always in the right order because querySelectorAll uses pre-order traversal // Therefore we can optimize the search diff --git a/web-client/src/ui/doc/updateNotePositions.ts b/web-client/src/ui/doc/updateNotePositions.ts index 90efeb86..89787a05 100644 --- a/web-client/src/ui/doc/updateNotePositions.ts +++ b/web-client/src/ui/doc/updateNotePositions.ts @@ -9,6 +9,7 @@ import { getLineLocationFromElement, getScrollContainerOffsetY, findLineByIndex, + DocContentContainerId, } from "./utils"; /// The id of the note panel @@ -38,7 +39,7 @@ export const updateNotePositions = (baseLine: HTMLElement): void => { } // Cancel the previous async updates updateNotesSerial += 1; - const containerOffsetY = getScrollContainerOffsetY(); + const containerOffsetY = getScrollContainerOffsetY(DocContentContainerId); // Layout the base note const baseNoteBlock = noteContainer.children[baseIndex] as HTMLElement; diff --git a/web-client/src/ui/doc/utils.ts b/web-client/src/ui/doc/utils.ts index 3d76a067..d03013db 100644 --- a/web-client/src/ui/doc/utils.ts +++ b/web-client/src/ui/doc/utils.ts @@ -12,6 +12,8 @@ export const DocLog = new Logger("doc"); export const DocScrollId = "doc-scroll"; /// The id of the container of doc view export const DocContainerId = "doc-container"; +/// The id of the container of main doc content (excluding preface) +export const DocContentContainerId = "doc-content-container"; /// Class for the doc line container export const DocLineContainerClass = "docline-container"; @@ -78,11 +80,14 @@ export const getLineLocationFromElement = ( return [sectionIndex, lineIndex]; }; -/// Get the offset of the scroll container +/// Get the offset of the scroll container relative to baseElementId +/// +/// use DocContainerId for relative to the entire document +/// use DocContentContainerId for relative to the main content /// /// line.getBoundingClientRect().y - containerOffsetY = line position relative to container -export const getScrollContainerOffsetY = (): number => { - const containerElement = document.getElementById(DocContainerId); +export const getScrollContainerOffsetY = (baseElementId: string): number => { + const containerElement = document.getElementById(baseElementId); if (!containerElement) { return 0; } diff --git a/web-themes/src/default.css b/web-themes/src/default.css index 48747624..b74f6c86 100644 --- a/web-themes/src/default.css +++ b/web-themes/src/default.css @@ -10,6 +10,22 @@ #doc-container { color: white; } +@media (prefers-color-scheme: light) { + #doc-container a { + color: #8888ff; + } +} + +#doc-preface-container { + background-color: #a2c4c4; + color: black; +} +#doc-preface-container a { + color: #0000ff !important; +} +.doc-preface-block { + border-bottom: 3px solid #446666; +} /* Section banner */ .docsection-head { @@ -75,7 +91,7 @@ background-color: #ff6666; } .docline-diagnostic-body.docline-diagnostic-error a { - color: #0000ff; + color: #0000ff !important; } /* Warning */ .docline-diagnostic-head.docline-diagnostic-warn { @@ -104,8 +120,3 @@ background-color: #bbbbbb !important; } } - -/* Ending block */ -#doc-end { - background-color: #001a00; -} diff --git a/web-themes/src/granatus.css b/web-themes/src/granatus.css index a2f68de5..943dd2c0 100644 --- a/web-themes/src/granatus.css +++ b/web-themes/src/granatus.css @@ -5,6 +5,16 @@ #doc-container { color: black; } +#doc-container a { + color: #0000ff !important; +} + +#doc-preface-container { + background-color: #a2c4c4; +} +.doc-preface-block { + border-top: 3px solid #446666; +} .docsection-head { background-color: #3388ff; @@ -64,9 +74,6 @@ .docline-diagnostic-body.docline-diagnostic-error { background-color: #ff6666; } -.docline-diagnostic-body.docline-diagnostic-error a { - color: #0000ff; -} /* Warning */ .docline-diagnostic-head.docline-diagnostic-warn { background-color: #883300;