Skip to content

Commit c616129

Browse files
authored
Merge pull request #137 from USACE-RMC/feature/draft-status-strip
Replace draft watermark with document status strip
2 parents f8c4c6f + 940a8f8 commit c616129

6 files changed

Lines changed: 264 additions & 43 deletions

File tree

‎src/components/DraftNotice.js‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { useLocation } from '@docusaurus/router';
2+
import latestVersions from '@site/static/versions/latestVersions.json';
3+
import { draftDocs } from '../draftDocs';
4+
5+
/**
6+
* Draft status marking for documents flagged `draft: true` in docConfig.js.
7+
*
8+
* Two surfaces, one message:
9+
* - DraftStatusStrip — a slim strip at the top of the content column that sticks
10+
* below the site header, so the status stays visible regardless of scroll
11+
* position or deep-link entry point. It is deliberately bounded by the content
12+
* column rather than the viewport: a full-bleed bar reads as site-wide chrome,
13+
* while a column-width bar reads as status for this document.
14+
* - DraftPrintFrame — wraps the document body in a table whose thead/tfoot the
15+
* browser repeats on every printed sheet, marking each physical page.
16+
*
17+
* The strip is hidden in print and the frame is inert on screen (display: contents),
18+
* so each surface only renders in the medium it is meant for.
19+
*/
20+
21+
export const DRAFT_STATUS_TEXT = 'This document is pending final approval by the RMC Director.';
22+
23+
function getDocInfo(pathname) {
24+
const stripped = pathname
25+
.replace(/^\/RMC-Software-Documentation\/docs\//, '')
26+
.replace(/^\/docs\//, '')
27+
.replace(/^docs\//, '');
28+
const match = stripped.match(/^(.+?)\/(v\d+\.\d+(?:\.\d+)?)(?:\/|$)/);
29+
if (!match) return null;
30+
return { docBasePath: match[1], version: match[2] };
31+
}
32+
33+
function isDraftPath(pathname) {
34+
const info = getDocInfo(pathname);
35+
if (!info) return false;
36+
const isFlagged = draftDocs.some((base) => info.docBasePath === base || info.docBasePath.startsWith(base + '/'));
37+
if (!isFlagged) return false;
38+
const latest = latestVersions[info.docBasePath];
39+
if (!latest) return true;
40+
return info.version === latest;
41+
}
42+
43+
/** True when the current route is the latest version of a doc flagged `draft: true`. */
44+
export function useIsDraftDoc() {
45+
const location = useLocation();
46+
return isDraftPath(location.pathname);
47+
}
48+
49+
/**
50+
* Slim status strip at the top of the content column.
51+
*
52+
* Renders nothing unless the current route is a draft doc, so it can be dropped
53+
* into the layout unconditionally.
54+
*
55+
* The outer anchor is the sticky element and carries an opaque page-coloured
56+
* band, so the gap between the header and the strip is preserved while scrolling
57+
* without document text showing through it.
58+
*/
59+
export const DraftStatusStrip = () => {
60+
const isDraft = useIsDraftDoc();
61+
if (!isDraft) return null;
62+
63+
return (
64+
<div className="draft-strip-anchor">
65+
<div className="draft-strip" role="note" aria-label="Document status">
66+
{DRAFT_STATUS_TEXT}
67+
</div>
68+
</div>
69+
);
70+
};
71+
72+
/**
73+
* Repeats the draft band at the top and bottom of every printed page.
74+
*
75+
* Browsers repeat `thead` and `tfoot` across page breaks, which is the only
76+
* cross-browser way to get a running header/footer — `@page` margin boxes are
77+
* unsupported in Chrome and Firefox. On screen the whole table collapses via
78+
* `display: contents`, so it generates no boxes and leaves layout untouched.
79+
*/
80+
export const DraftPrintFrame = ({ children }) => {
81+
const isDraft = useIsDraftDoc();
82+
if (!isDraft) return <>{children}</>;
83+
84+
return (
85+
<table className="draft-print-frame">
86+
<thead>
87+
<tr>
88+
<td>
89+
<div className="draft-print-frame__band" aria-hidden="true">
90+
{DRAFT_STATUS_TEXT}
91+
</div>
92+
</td>
93+
</tr>
94+
</thead>
95+
<tbody>
96+
<tr>
97+
<td>{children}</td>
98+
</tr>
99+
</tbody>
100+
<tfoot>
101+
<tr>
102+
<td>
103+
<div className="draft-print-frame__band draft-print-frame__band--foot" aria-hidden="true">
104+
{DRAFT_STATUS_TEXT}
105+
</div>
106+
</td>
107+
</tr>
108+
</tfoot>
109+
</table>
110+
);
111+
};
112+
113+
export default DraftStatusStrip;

‎src/css/custom.css‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@import '../../node_modules/@usace/groundwork/dist/style.css';
66
@import './schema.css';
77
@import './print.css';
8+
@import './draft-notice.css';
89
@import './responsive.css';
910

1011
@font-face {

‎src/css/draft-notice.css‎

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/* ===== Draft Status Marking ===== */
2+
/* Screen: a slim strip at the top of the content column that sticks below the
3+
site header as the document scrolls.
4+
Print: a band repeated at the top and bottom of every printed sheet.
5+
See src/components/DraftNotice.js. */
6+
7+
/* ── Screen: document status strip ── */
8+
/* Bounded by the content column, not the viewport: a full-bleed bar reads as
9+
site-wide chrome, a column-width bar reads as status for this document. */
10+
/* The anchor is the sticky element. It carries an opaque, page-coloured band so
11+
the gap above the strip is preserved as the document scrolls without text
12+
showing through it — the site header itself has a transparent background. */
13+
.draft-strip-anchor {
14+
position: sticky;
15+
top: var(--ifm-navbar-height, 0px);
16+
z-index: 5;
17+
18+
/* Holds the gap open as the document scrolls under it. Uses an explicit token
19+
rather than --ifm-background-color, which resolves to #0000 in light mode. */
20+
padding-top: 1rem;
21+
padding-bottom: 0.35rem;
22+
/* Cancels the container's top spacing so the strip sits at its stuck position
23+
from first paint — it locks in place instead of shifting up on first scroll. */
24+
margin-top: -1rem;
25+
margin-bottom: 0.7rem;
26+
background-color: var(--draft-strip-band);
27+
}
28+
29+
.draft-strip {
30+
display: flex;
31+
align-items: baseline;
32+
justify-content: center;
33+
flex-wrap: wrap;
34+
gap: 0.45rem;
35+
36+
padding: 0.4rem 0.9rem;
37+
border: 1px solid var(--draft-strip-border);
38+
border-radius: var(--ifm-global-radius);
39+
background-color: var(--draft-strip-bg);
40+
41+
color: var(--draft-strip-fg);
42+
font-size: 0.8125rem;
43+
line-height: 1.3;
44+
text-align: center;
45+
}
46+
47+
/* Light mode — lighter red */
48+
:root {
49+
--draft-strip-bg: #fdf3e0;
50+
--draft-strip-border: #eed9ab;
51+
--draft-strip-fg: #6f4a08;
52+
--draft-strip-band: #f7f8fa;
53+
}
54+
55+
/* Dark mode — darker red */
56+
html[data-theme='dark'] {
57+
--draft-strip-bg: #33280f;
58+
--draft-strip-border: #6a5423;
59+
--draft-strip-fg: #f2e0be;
60+
--draft-strip-band: #1b1b1b;
61+
}
62+
63+
@media (max-width: 480px) {
64+
.draft-strip {
65+
font-size: 0.75rem;
66+
padding: 0.35rem 0.7rem;
67+
}
68+
}
69+
70+
/* ── Print frame: inert on screen ── */
71+
/* display: contents makes the wrapper generate no boxes, so the document lays
72+
out exactly as it would without the table. */
73+
.draft-print-frame,
74+
.draft-print-frame > thead,
75+
.draft-print-frame > tbody,
76+
.draft-print-frame > tfoot,
77+
.draft-print-frame > * > tr,
78+
.draft-print-frame > * > tr > td {
79+
display: contents;
80+
}
81+
82+
.draft-print-frame__band {
83+
display: none;
84+
}
85+
86+
/* ── Print ── */
87+
@media print {
88+
/* The viewport strip is a screen affordance; the repeating band replaces it. */
89+
.draft-strip-anchor {
90+
display: none !important;
91+
}
92+
93+
.draft-print-frame {
94+
display: table !important;
95+
width: 100% !important;
96+
border-collapse: collapse !important;
97+
}
98+
99+
/* thead/tfoot repeat across page breaks — this is what marks every sheet. */
100+
.draft-print-frame > thead {
101+
display: table-header-group !important;
102+
}
103+
104+
.draft-print-frame > tfoot {
105+
display: table-footer-group !important;
106+
}
107+
108+
.draft-print-frame > tbody {
109+
display: table-row-group !important;
110+
}
111+
112+
.draft-print-frame > * > tr {
113+
display: table-row !important;
114+
}
115+
116+
.draft-print-frame > * > tr > td {
117+
display: table-cell !important;
118+
border: 0 !important;
119+
padding: 0 !important;
120+
}
121+
122+
/* Class specificity beats the `* { color: #000 !important }` reset in print.css. */
123+
.draft-print-frame__band {
124+
display: block !important;
125+
margin: 0 0 8pt !important;
126+
padding: 3pt 0 !important;
127+
border-top: 1pt solid #8a5a00 !important;
128+
border-bottom: 1pt solid #8a5a00 !important;
129+
color: #8a5a00 !important;
130+
font-size: 8.5pt !important;
131+
font-weight: 700 !important;
132+
letter-spacing: 0.06em;
133+
text-align: center;
134+
-webkit-print-color-adjust: exact;
135+
print-color-adjust: exact;
136+
}
137+
138+
.draft-print-frame__band--foot {
139+
margin: 8pt 0 0 !important;
140+
}
141+
}

‎src/docConfig.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const docs = [
7878
{
7979
category: 'desktop-applications',
8080
software: 'rmc-totalrisk',
81+
doc_location: 'desktop-applications/rmc-totalrisk/verification-report',
8182
doc_name: 'RMC TotalRisk Verification Report',
8283
active: true,
8384
draft: true,

‎src/theme/DocItem/Layout/index.js‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
* - Added FloatingNav FAB + bottom-sheet drawer so users can reach
88
* the same navigation without scrolling to the top when the
99
* viewport is narrow (< 1080 px).
10+
* - Added DraftStatusStrip at the top of the content column and wrapped the
11+
* content in DraftPrintFrame, so draft documents carry a sticky status
12+
* strip on screen and a repeating DRAFT band on every printed page.
1013
*/
1114
import React from 'react';
1215
import clsx from 'clsx';
@@ -21,6 +24,7 @@ import DocItemContent from '@theme/DocItem/Content';
2124
import DocBreadcrumbs from '@theme/DocBreadcrumbs';
2225
import ContentVisibility from '@theme/ContentVisibility';
2326
import FloatingNav, { InlineNav } from '@site/src/components/FloatingNav';
27+
import { DraftPrintFrame, DraftStatusStrip } from '@site/src/components/DraftNotice';
2428
import styles from './styles.module.css';
2529

2630
function useDocTOC() {
@@ -41,11 +45,14 @@ export default function DocItemLayout({ children }) {
4145
<ContentVisibility metadata={metadata} />
4246
<DocVersionBanner />
4347
<div className={styles.docItemContainer}>
48+
<DraftStatusStrip />
4449
<article>
4550
<DocBreadcrumbs />
4651
<DocVersionBadge />
4752
<InlineNav />
48-
<DocItemContent>{children}</DocItemContent>
53+
<DraftPrintFrame>
54+
<DocItemContent>{children}</DocItemContent>
55+
</DraftPrintFrame>
4956
<DocItemFooter />
5057
</article>
5158
<DocItemPaginator />

‎src/theme/DocItem/index.js‎

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)