Skip to content

Commit 5c70cc3

Browse files
authored
Merge pull request #305 from adhocteam/main
Display My Alerts, ContextMenu, and Print styles
2 parents 598ba0f + 54cff22 commit 5c70cc3

File tree

32 files changed

+1025
-160
lines changed

32 files changed

+1025
-160
lines changed

frontend/src/App.css

+122
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,125 @@ body {
3939
opacity: 0.7;
4040
}
4141

42+
/* ========== Print Styles ========== */
43+
44+
/* This is for elements that in the DOM that should appear only when printing */
45+
.print-only {
46+
display: none;
47+
}
48+
49+
@media print {
50+
51+
* {
52+
color: #000 !important;
53+
box-shadow: none !important;
54+
font-size: 12pt;
55+
}
56+
57+
body {
58+
background: #fff !important;
59+
font-size: 12pt;
60+
}
61+
62+
@page {
63+
margin: 0.5in;
64+
}
65+
66+
.grid-container {
67+
max-width: unset;
68+
width: 100%;
69+
}
70+
71+
.usa-header {
72+
background: #fff !important;
73+
}
74+
75+
.usa-nav-container {
76+
padding: 0 !important;
77+
margin: 0 0.125in !important;
78+
}
79+
80+
.print-only {
81+
display: unset;
82+
}
83+
84+
/* Hide things that don't need to be printed
85+
* ':empty' doesn't work on <textarea>, so we need to check values and set 'no-print' if empty
86+
* */
87+
.usa-nav,
88+
.usa-menu-btn,
89+
.no-print,
90+
input:empty,
91+
button[type="submit"]
92+
{
93+
display: none !important;
94+
}
95+
96+
.usa-alert {
97+
background: none;
98+
border: 1px solid #adadad;
99+
}
100+
/* .usa-alert uses a :before to create the left border, which we want to remove */
101+
.usa-alert::before {
102+
display: none;
103+
}
104+
105+
.smart-hub-review-section--empty {
106+
margin-bottom: 1in;
107+
}
108+
109+
/* Show content that is hidden, e.g. collapsed accordions */
110+
[hidden] {
111+
display: unset;
112+
}
113+
114+
.usa-section,
115+
.usa-section > div
116+
{
117+
margin: 0;
118+
padding: 0;
119+
}
120+
121+
.new-activity-report {
122+
font-size: 36pt;
123+
margin: 0.25in 0;
124+
}
125+
126+
.smart-hub-status-label {
127+
background: none;
128+
border: 1px solid #adadad;
129+
}
130+
131+
.smart-hub-navigator-wrapper {
132+
width: 100%;
133+
padding-left: 0;
134+
padding-right: 0;
135+
}
136+
137+
.smart-hub-review > div {
138+
padding: 0 !important;
139+
}
140+
141+
.usa-accordion__button {
142+
background: none !important;
143+
}
144+
145+
.usa-accordion__heading {
146+
break-before: auto;
147+
break-after: avoid-page;
148+
}
149+
150+
.usa-accordion__heading .usa-accordion__button {
151+
color: #454545 !important;
152+
padding: 0;
153+
}
154+
155+
.usa-accordion__content {
156+
break-before: avoid-page;
157+
break-after: auto;
158+
display: block;
159+
margin-bottom: 0.5in;
160+
padding: 0;
161+
}
162+
163+
}

frontend/src/App.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ function App() {
122122
)}
123123
<UserContext.Provider value={{ user, authenticated, logout }}>
124124
<Header authenticated={authenticated} admin={admin} />
125-
<div className="background-stripe" />
125+
<div className="background-stripe no-print" />
126126
<section className="usa-section">
127127

128128
{!authenticated && (
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
.smart-hub--context-menu-button {
2+
display: block;
3+
text-decoration: none;
4+
width: 100%;
5+
height: 100%;
6+
color: black;
7+
}
8+
9+
.smart-hub--context-menu-button:hover {
10+
text-decoration: none;
11+
color: black;
12+
}
13+
14+
.smart-hub--context-menu {
15+
position: absolute;
16+
z-index: 1;
17+
}
18+
19+
.smart-hub--context-menu__left {
20+
transform:translateX(-75%);
21+
}
22+
23+
.smart-hub--context-menu-item-label {
24+
padding: 12px 24px 12px 12px;
25+
}
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
Context menu shows a list of actions the user can select to perform actions. The actions
3+
are hidden until the user opens the menu (the three dot icon). The menu is automatically
4+
closed on blur. Pass this component an array of objects with the label and action to tie
5+
to that label. Be sure to pass in a description of the menu in the `label` prop. This prop
6+
is used as ellipsis' aria-label.
7+
*/
8+
import React, { useState, useEffect, useCallback } from 'react';
9+
import PropTypes from 'prop-types';
10+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
11+
import { faEllipsisH } from '@fortawesome/free-solid-svg-icons';
12+
import { Button } from '@trussworks/react-uswds';
13+
14+
import './ContextMenu.css';
15+
16+
const ESCAPE_KEY_CODE = 27;
17+
18+
function ContextMenu({
19+
label, menuItems, backgroundColor, left,
20+
}) {
21+
const [shown, updateShown] = useState(false);
22+
const defaultClass = 'smart-hub--context-menu';
23+
const menuClass = left ? `${defaultClass} smart-hub--context-menu__left` : defaultClass;
24+
25+
const onEscape = useCallback((event) => {
26+
if (event.keyCode === ESCAPE_KEY_CODE) {
27+
updateShown(false);
28+
}
29+
}, [updateShown]);
30+
31+
useEffect(() => {
32+
document.addEventListener('keydown', onEscape, false);
33+
return () => {
34+
document.removeEventListener('keydown', onEscape, false);
35+
};
36+
}, [onEscape]);
37+
38+
const onBlur = (e) => {
39+
const { currentTarget } = e;
40+
41+
setTimeout(() => {
42+
if (!currentTarget.contains(document.activeElement) && shown) {
43+
updateShown(false);
44+
}
45+
}, 0);
46+
};
47+
48+
return (
49+
<div
50+
onBlur={onBlur}
51+
>
52+
<Button
53+
className="smart-hub--context-menu-button smart-hub--button__no-margin"
54+
unstyled
55+
aria-haspopup
56+
onClick={() => updateShown((previous) => !previous)}
57+
aria-label={label}
58+
>
59+
<FontAwesomeIcon color="black" icon={faEllipsisH} />
60+
</Button>
61+
{shown
62+
&& (
63+
<div className={menuClass} style={{ backgroundColor }}>
64+
<ul className="usa-list usa-list--unstyled" role="menu">
65+
{menuItems.map((item) => (
66+
<li key={item.label} role="menuitem">
67+
<Button type="button" onClick={item.onClick} unstyled className="smart-hub--context-menu-button smart-hub--button__no-margin">
68+
<div className="smart-hub--context-menu-item-label">
69+
{item.label}
70+
</div>
71+
</Button>
72+
</li>
73+
))}
74+
</ul>
75+
</div>
76+
)}
77+
</div>
78+
);
79+
}
80+
81+
ContextMenu.propTypes = {
82+
label: PropTypes.string.isRequired,
83+
menuItems: PropTypes.arrayOf(PropTypes.shape({
84+
label: PropTypes.string,
85+
onClick: PropTypes.func,
86+
})).isRequired,
87+
backgroundColor: PropTypes.string,
88+
left: PropTypes.bool,
89+
};
90+
91+
ContextMenu.defaultProps = {
92+
backgroundColor: 'white',
93+
left: true,
94+
};
95+
96+
export default ContextMenu;

frontend/src/components/Navigator/components/SideNav.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function SideNav({
6464
));
6565

6666
return (
67-
<Sticky top={50} enabled={!isMobile}>
67+
<Sticky className="smart-hub-sidenav" top={50} enabled={!isMobile}>
6868
<Container padding={0}>
6969
<a className="smart-hub--navigator-skip-link" href={`#${skipTo}`}>{skipToMessage}</a>
7070
<ul className="smart-hub--navigator-list">

frontend/src/components/Navigator/index.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ function Navigator({
3434
autoSaveInterval,
3535
approvingManager,
3636
reportId,
37+
reportCreator,
3738
}) {
3839
const [errorMessage, updateErrorMessage] = useState();
3940
const [lastSaveTime, updateLastSaveTime] = useState(initialLastUpdated);
@@ -115,7 +116,7 @@ function Navigator({
115116

116117
return (
117118
<Grid row gap>
118-
<Grid col={12} tablet={{ col: 6 }} desktop={{ col: 4 }}>
119+
<Grid className="smart-hub-sidenav-wrapper no-print" col={12} tablet={{ col: 6 }} desktop={{ col: 4 }}>
119120
<SideNav
120121
skipTo="navigator-form"
121122
skipToMessage="Skip to report content"
@@ -124,7 +125,7 @@ function Navigator({
124125
errorMessage={errorMessage}
125126
/>
126127
</Grid>
127-
<Grid col={12} tablet={{ col: 6 }} desktop={{ col: 8 }}>
128+
<Grid className="smart-hub-navigator-wrapper" col={12} tablet={{ col: 6 }} desktop={{ col: 8 }}>
128129
<FormProvider {...hookForm}>
129130
<div id="navigator-form">
130131
{page.review
@@ -135,6 +136,7 @@ function Navigator({
135136
additionalData,
136137
onReview,
137138
approvingManager,
139+
reportCreator,
138140
)}
139141
{!page.review
140142
&& (
@@ -182,12 +184,20 @@ Navigator.propTypes = {
182184
autoSaveInterval: PropTypes.number,
183185
additionalData: PropTypes.shape({}),
184186
reportId: PropTypes.node.isRequired,
187+
reportCreator: PropTypes.shape({
188+
name: PropTypes.string,
189+
role: PropTypes.string,
190+
}),
185191
};
186192

187193
Navigator.defaultProps = {
188194
additionalData: {},
189195
autoSaveInterval: 1000 * 60 * 2,
190196
initialLastUpdated: null,
197+
reportCreator: {
198+
name: null,
199+
role: null,
200+
},
191201
};
192202

193203
export default Navigator;

0 commit comments

Comments
 (0)