Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(example app): add modals page example 204 #250

Merged
merged 11 commits into from
Jun 15, 2020
5 changes: 5 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/react-redux": "^7.1.9",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1",
"redux": "^4.0.5",
"typescript": "~3.7.2"
},
"scripts": {
Expand All @@ -37,6 +41,7 @@
]
},
"devDependencies": {
"@types/react-router-dom": "^5.1.5",
"customize-cra": "^0.9.1",
"react-app-rewired": "^2.1.6"
},
Expand Down
38 changes: 0 additions & 38 deletions example/src/App.css
Original file line number Diff line number Diff line change
@@ -1,38 +0,0 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
10 changes: 5 additions & 5 deletions example/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import { render } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
// TODO Add additional app testing
test('renders the app without error', () => {
const { getByText } = render(<App />)
expect(getByText('Modals')).toBeInTheDocument()
})
107 changes: 88 additions & 19 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,98 @@
import React from 'react'
import React, { useState } from 'react'
import {
BrowserRouter as Router,
Switch,
Route,
NavLink,
Link,
} from 'react-router-dom'

import '@trussworks/react-uswds/lib/uswds.css'
import { GovBanner } from '@trussworks/react-uswds'
import '@trussworks/react-uswds/lib/index.css'

import {
GovBanner,
Header,
Title,
NavMenuButton,
PrimaryNav,
GridContainer,
} from '@trussworks/react-uswds'

import HomePage from './pages/Home'
import ExamplePage from './pages/Example'
import ModalsPage from './pages/Modals'

import logo from './logo.svg'
import './App.css'

function App() {
/* Routes */
const routes = {
HOME_PAGE: '/',
EXAMPLES_PAGE: '/examples',
MODALS_PAGE: '/modals',
}

const App = () => {
const [mobileNavOpen, setMobileNavOpen] = useState(false)
const { HOME_PAGE, EXAMPLES_PAGE, MODALS_PAGE } = routes

const toggleMobileNav = (): void => {
setMobileNavOpen((prevOpen) => !prevOpen)
}

const navItems = [
<NavLink to={HOME_PAGE} activeClassName="usa-current" exact>
Home
</NavLink>,
<NavLink to={EXAMPLES_PAGE} activeClassName="usa-current">
Examples
</NavLink>,
<NavLink to={MODALS_PAGE} activeClassName="usa-current">
Modals
</NavLink>,
]

return (
<div className="App">
<Router>
<GovBanner />
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer">
Learn React
</a>
</header>
</div>
<Header basic>
<div className="usa-nav-container">
<div className="usa-navbar">
<Title>
<Link to={HOME_PAGE}>Example Application</Link>
</Title>
<NavMenuButton
label="Menu"
onClick={toggleMobileNav}
className="usa-menu-btn"
/>
</div>

<PrimaryNav
aria-label="Primary navigation"
items={navItems}
onToggleMobileNav={toggleMobileNav}
mobileExpanded={mobileNavOpen}
/>
</div>
</Header>

<section className="usa-section">
<GridContainer>
<Switch>
<Route path={EXAMPLES_PAGE}>
<ExamplePage />
</Route>
<Route path={MODALS_PAGE}>
<ModalsPage />
</Route>
<Route path={HOME_PAGE}>
<HomePage />
</Route>
</Switch>
</GridContainer>
</section>
</Router>
)
}

Expand Down
14 changes: 11 additions & 3 deletions example/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { createStore } from 'redux';
import { Provider } from 'react-redux';

import { rootReducer } from './redux/reducers'

const store = createStore(rootReducer)

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
<Provider store={store}>
<React.StrictMode>
<App />
</React.StrictMode>
</Provider>,
document.getElementById('root')
);

Expand Down
24 changes: 24 additions & 0 deletions example/src/pages/Example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react'

const ExamplePage = (): React.ReactElement => (
<section>
<h1>Examples</h1>

<p className="usa-intro">
Right now there are no examples! Things that we could add include...
</p>

<ul className="usa-list">
<li>Modals</li>
<li>
Form libraries
<ul className="usa-list">
<li>Formik</li>
<li>React-hook-form</li>
</ul>
</li>
</ul>
</section>
)

export default ExamplePage
14 changes: 14 additions & 0 deletions example/src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'

const HomePage = (): React.ReactElement => (
<main>
<h1>ReactUSWDS Example App</h1>

<p className="usa-intro">
This is an example application that can be used to demonstrate and test
ReactUSWDS functionality.
</p>
</main>
)

export default HomePage
114 changes: 114 additions & 0 deletions example/src/pages/Modals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React from 'react'
import {
Modal,
Button,
connectModal,
ConnectedModalProps,
useModal
} from '@trussworks/react-uswds'
import { connect, ConnectedProps } from 'react-redux'

import { openModalAction, closeModalAction } from './../redux/actions'
import { AppState, ModalState } from './../redux/types'

/** Example of Modal Component Using Redux */
eamahanna marked this conversation as resolved.
Show resolved Hide resolved
interface TestModalProps extends ConnectedModalProps {
modalKey: string
}

const TestModal = ({ onClose }: TestModalProps): React.ReactElement => (
eamahanna marked this conversation as resolved.
Show resolved Hide resolved
<Modal
title={<h2>Test Modal</h2>}
actions={
<>
<Button type="button" outline onClick={onClose}>
Cancel
</Button>
<Button type="button" onClick={onClose}>
Close
</Button>
</>
}>
<p>This is a test modal that uses redux!</p>
</Modal>
)

const ConnectedTestModal = connectModal(TestModal)
eamahanna marked this conversation as resolved.
Show resolved Hide resolved

const mapStateToProps = (state: AppState): ModalState => ({
openModalKey: state.modalState.openModalKey,
})

const mapDispatchToProps = {
openModalAction: openModalAction,
closeModalAction: closeModalAction,
}

const connector = connect(mapStateToProps, mapDispatchToProps)

/** End of Example of Modal Component Using Redux */

const ExamplePage = ({
openModalKey,
openModalAction,
closeModalAction,
}: ConnectedProps<typeof connector>): React.ReactElement => {

/** Example of Modal Component Using Hooks */
const { isOpen, openModal, closeModal } = useModal()

const HookTestModal = (): React.ReactElement => (
eamahanna marked this conversation as resolved.
Show resolved Hide resolved
<Modal
title={<h2>Test Modal</h2>}
actions={
<>
<Button type="button" outline onClick={closeModal}>
Cancel
</Button>
<Button type="button" onClick={closeModal}>
Close
</Button>
</>
}>
<p>This is a test modal that uses hooks!</p>
</Modal>
)

const ConnectedHookTestModal = connectModal(HookTestModal)
/** End of Example of Modal Component Using Hooks */

return (
<section>
<h1>Modals</h1>

<p className="usa-intro">
This page provides examples of how modals may be used within an
application.
</p>

<div style={{ margin: '8px'}}>
<Button type="button" onClick={() => openModalAction('testModal')}>
Click me!
</Button>
<ConnectedTestModal
eamahanna marked this conversation as resolved.
Show resolved Hide resolved
modalKey="testModal"
isOpen={'testModal' === openModalKey}
onClose={() => closeModalAction('testModal')}
/>
</div>
<div style={{ margin: '8px'}}>
<Button type="button" onClick={openModal}>
Click me!
</Button>
<ConnectedHookTestModal isOpen={isOpen} onClose={closeModal} />
</div>
</section>
)
}

const ConnectedExamplePage = connect(
mapStateToProps,
mapDispatchToProps
)(ExamplePage)
eamahanna marked this conversation as resolved.
Show resolved Hide resolved

export default ConnectedExamplePage
Loading