diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac360a15c9be1e12a9fe07e9440b6c673634bea9..972c7e6fea6b93af5f89ee4b2301fb36c59dba36 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,8 +5,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
 and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased](https://github.com/usgs/waterdataui/compare/waterdataui-1.2.0...master)
+### Added
+- Daily statistical data will now appear under the parameter selection list.
+
 ### Changed
-- Refactored the parameter selection table component to use Vue.
+- Data download component was converted to Vue.
+- Parameter selection table component was converted to Vue.
+
 
 ## [1.2.0](https://github.com/usgs/waterdataui/compare/waterdataui-1.1.0...waterdataui-1.2.0) - 2022-06-10
 ### Added
@@ -16,6 +21,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 ### Changed
 - Links related to NLDI and Flood mapper now use more descriptive wording.
 - When fetching active sites, precision was dropped to 3 from 4 on the bounding box to all the cached response to be returned with small movements on the map.
+- Data download component was converted to Vue.
+- Graph controls compone was converted to Vue.
 
 ## [1.1.0](https://github.com/usgs/waterdataui/compare/waterdataui-1.0.0...waterdataui-1.1.0) - 2022-06-06
 ### Added
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/DataTablesApp.vue b/assets/src/scripts/monitoring-location/components/hydrograph/DataTablesApp.vue
index 10c84cd289ef5a1068ea34ef8089d7101374bad2..01371fcbc9178b123635f9187208a20ea5f20a23 100644
--- a/assets/src/scripts/monitoring-location/components/hydrograph/DataTablesApp.vue
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/DataTablesApp.vue
@@ -1,7 +1,5 @@
 <template>
-  <div class="data-table-container">
-    <DataTable />
-  </div>
+  <DataTable />
 </template>
 
 <script>
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/DownloadDataApp.vue b/assets/src/scripts/monitoring-location/components/hydrograph/DownloadDataApp.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2c2b004e6a55ef0f0e7bfba78baac76a78d7aeef
--- /dev/null
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/DownloadDataApp.vue
@@ -0,0 +1,14 @@
+<template>
+  <DownloadData />
+</template>
+
+<script>
+import DownloadData from './vue-components/download-data.vue';
+
+export default {
+  name: 'DownloadDataApp',
+  components: {
+    DownloadData
+  }
+};
+</script>
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/data-table.js b/assets/src/scripts/monitoring-location/components/hydrograph/data-table.js
deleted file mode 100644
index 9a1473f0afcaeefd0f3ecf5d42eab3e93b1bece5..0000000000000000000000000000000000000000
--- a/assets/src/scripts/monitoring-location/components/hydrograph/data-table.js
+++ /dev/null
@@ -1,58 +0,0 @@
-
-import {bindActionCreators} from 'redux';
-import ReduxConnectVue from 'redux-connect-vue';
-import {createStructuredSelector} from 'reselect';
-import {createApp} from 'vue';
-
-import config from 'ui/config.js';
-
-import DataTablesApp from './DataTablesApp.vue';
-import {drawDownloadForm} from './download-data';
-
-/*
- * Create the hydrograph data tables section which will update when the data
- * displayed on the hydrograph changes. The section includes a button where the user
- * can request that the data be downloaded
- * @param {D3 selection} elem
- * @param {Redux store} store
- * @param {String} siteno
- * @param {String} agencyCd
- */
-export const drawDataTables = function(elem, store, siteno, agencyCd) {
-    const dataTablesApp = createApp(DataTablesApp, {});
-
-    elem.append('div')
-        .attr('id', 'iv-hydrograph-data-table-container');
-    dataTablesApp.use(ReduxConnectVue, {
-        store,
-        mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
-        mapStateToPropsFactory: createStructuredSelector
-    });
-    dataTablesApp.provide('store', store);
-    dataTablesApp.mount('#iv-hydrograph-data-table-container');
-
-    var button = elem.append('button')
-        .attr('id', 'download-graph-data-container-data-table-toggle')
-        .attr('class', 'usa-button')
-        .attr('aria-controls', 'download-graph-data-container-data-table')
-        .attr('ga-on', 'click')
-        .attr('ga-event-category', 'select-action')
-        .attr('ga-event-action', 'download-graph-data-container-data-table-toggle')
-        .on('click', function() {
-            const downloadContainer = elem.select('#download-graph-data-container-data-table');
-            downloadContainer.attr('hidden', downloadContainer.attr('hidden') ? null : true);
-        });
-    button.append('svg')
-            .attr('class', 'usa-icon')
-            .attr('aria-hidden', 'true')
-            .attr('role', 'img')
-            .html(`<use xlink:href="${config.STATIC_URL}img/sprite.svg#file_download"></use>`);
-    button.append('span').html('Retrieve data');
-
-    elem.append('div')
-        .attr('id', 'download-graph-data-container-data-table')
-        .attr('class', 'download-graph-data-container')
-        .attr('hidden', 'true')
-        .call(drawDownloadForm, store, siteno, agencyCd, 'data-table');
-
-};
\ No newline at end of file
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/data-table.test.js b/assets/src/scripts/monitoring-location/components/hydrograph/data-table.test.js
deleted file mode 100644
index 1fec9a09a3d6d48c06db340ee9d10154454f2140..0000000000000000000000000000000000000000
--- a/assets/src/scripts/monitoring-location/components/hydrograph/data-table.test.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import {select} from 'd3-selection';
-
-import config from 'ui/config';
-
-import {configureStore} from 'ml/store';
-
-import {drawDataTables} from './data-table';
-import {TEST_PRIMARY_IV_DATA, TEST_GW_LEVELS} from './mock-hydrograph-state';
-
-describe('monitoring-location/components/hydrograph/data-table', () => {
-    let testDiv;
-    let store;
-
-    config.locationTimeZone = 'America/Chicago';
-
-    beforeEach(() => {
-        testDiv = select('body').append('div');
-    });
-
-    afterEach(() => {
-        testDiv.remove();
-    });
-
-    it('Shows table with expected data and download section', () => {
-        store = configureStore({
-            hydrographData: {
-                currentTimeRange: {
-                    start: 1582560000000,
-                    end: 1600620000000
-                },
-                primaryIVData: TEST_PRIMARY_IV_DATA
-            },
-            groundwaterLevelData: {
-                all: [TEST_GW_LEVELS]
-            },
-            hydrographState: {
-                selectedParameterCode: '72019',
-                selectedIVMethodID: '90649'
-            }
-        });
-        drawDataTables(testDiv, store, '11112222', 'USGS');
-
-        const ivTable = testDiv.select('#iv-table-container').select('table');
-        expect(ivTable.select('caption').text()).toBe('Instantaneous value data');
-        expect(ivTable.selectAll('tr').size()).toBe(10);
-        const gwTable = testDiv.select('#gw-table-container').select('table');
-        expect(gwTable.select('caption').text()).toBe('Field visit data');
-        expect(gwTable.selectAll('tr').size()).toBe(5);
-        const downloadSection = testDiv.select('#download-graph-data-container-data-table');
-        expect(downloadSection.selectAll('input[type="radio"]').size()).toBe(3);
-    });
-
-    it('Shows single IV table if no GW levels', () => {
-        store = configureStore({
-            hydrographData: {
-                currentTimeRange: {
-                    start: 1582560900000,
-                    end: 1600619400000
-                },
-                primaryIVData: TEST_PRIMARY_IV_DATA
-            },
-            groundwaterLevelData: {
-                all: []
-            },
-            hydrographState: {
-                selectedParameterCode: '72019',
-                selectedIVMethodID: '90649'
-            }
-        });
-        drawDataTables(testDiv, store);
-
-        expect(testDiv.select('#iv-table-container').style('display')).not.toBe('none');
-        expect(testDiv.select('#gw-table-container').style('display')).toBe('none');
-    });
-
-    it('Shows single GW table if no IV data', () => {
-        store = configureStore({
-            hydrographData: {
-                currentTimeRange: {
-                    start: 1582560900000,
-                    end: 1600619400000
-                }
-            },
-            groundwaterLevelData: {
-                all: [TEST_GW_LEVELS]
-            },
-            hydrographState: {
-                selectedParameterCode: '72019'
-            }
-        });
-        drawDataTables(testDiv, store);
-
-        expect(testDiv.select('#iv-table-container').style('display')).toBe('none');
-        expect(testDiv.select('#gw-table-container').style('display')).not.toBe('none');
-    });
-
-    it('Clicking the download button shows the download container', () => {
-        store = configureStore({
-            hydrographData: {
-                currentTimeRange: {
-                    start: 1582560000000,
-                    end: 1600620000000
-                },
-                primaryIVData: TEST_PRIMARY_IV_DATA
-            },
-            groundwaterLevelData: {
-                all: [TEST_GW_LEVELS]
-            },
-            hydrographState: {
-                selectedParameterCode: '72019',
-                selectedIVMethodID: '90649'
-            }
-        });
-        drawDataTables(testDiv, store, '11112222', 'USGS');
-
-        const downloadButton = testDiv.select('#download-graph-data-container-data-table-toggle');
-        expect(downloadButton.size()).toBe(1);
-
-        downloadButton.dispatch('click');
-        expect(testDiv.select('#download-graph-data-container-data-table').attr('hidden')).toBeNull();
-    });
-
-    it('Clicking the download button twice hides the download container', () => {
-        store = configureStore({
-            hydrographData: {
-                currentTimeRange: {
-                    start: 1582560000000,
-                    end: 1600620000000
-                },
-                primaryIVData: TEST_PRIMARY_IV_DATA
-            },
-            groundwaterLevelData: {
-                all: [TEST_GW_LEVELS]
-            },
-            hydrographState: {
-                selectedParameterCode: '72019',
-                selectedIVMethodID: '90649'
-            }
-        });
-        drawDataTables(testDiv, store, '11112222', 'USGS');
-
-        const downloadButton = testDiv.select('#download-graph-data-container-data-table-toggle');
-        downloadButton.dispatch('click');
-        downloadButton.dispatch('click');
-
-        expect(testDiv.select('#download-graph-data-container-data-table').attr('hidden')).not.toBeNull();
-    });
-});
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/download-data.js b/assets/src/scripts/monitoring-location/components/hydrograph/download-data.js
deleted file mode 100644
index 3c25953bad81b749ff480c98d1766e951ac5ae5f..0000000000000000000000000000000000000000
--- a/assets/src/scripts/monitoring-location/components/hydrograph/download-data.js
+++ /dev/null
@@ -1,219 +0,0 @@
-/**
- *  Module with functions for processing and structuring download link URLs
- */
-
-import {DateTime} from 'luxon';
-import {createStructuredSelector} from 'reselect';
-
-import config from 'ui/config.js';
-import {link}  from 'ui/lib/d3-redux';
-
-import {getIVServiceURL, getSiteMetaDataServiceURL} from 'ui/web-services/instantaneous-values';
-import {getStatisticsServiceURL} from 'ui/web-services/statistics-data';
-import {getGroundwaterServiceURL} from 'ui/web-services/groundwater-levels';
-
-import {drawErrorAlert} from 'd3render/alerts';
-
-import {isCalculatedTemperature} from 'ml/parameter-code-utils';
-import {getTimeRange} from 'ml/selectors/hydrograph-data-selector';
-
-import {hasVisibleIVData, hasVisibleMedianStatisticsData, hasVisibleGroundwaterLevels, getPrimaryParameter} from './selectors/time-series-data';
-
-const INFO_TEXT = `
-<div>
-<div>
-    A separate tab will open with the requested data.
-</div>
-<div>
-    All data is in 
-    <a href="https://waterdata.usgs.gov/nwis/?tab_delimited_format_info" target="_blank">RDB</a> format.
-</div>
-<div>
-    Data is retrieved from <a href="https://waterservices.usgs.gov"  target="_blank">USGS Water Data Services.</a>
-</div>
-<div>
- If you are an R user, use the 
- <a href="https://usgs-r.github.io/dataRetrieval/" target="_blank">USGS dataRetrieval package</a> to
- download, analyze and plot your data
-</div>  
-</div>  
-`;
-
-/*
- * Helper function to return a ISO formated string in the location's time zone for the epoch time, inMillis
- */
-const toISO = function(inMillis) {
-    return DateTime.fromMillis(inMillis, {zone: config.locationTimeZone}).toISO();
-};
-
-/*
- * Helper functions to return the appropriate service URL using information in the Redux store
- */
-const getIVDataURL =  function(store, siteno, timeRangeKind) {
-    const currentState = store.getState();
-    const timeRange = getTimeRange(timeRangeKind)(currentState);
-
-    return getIVServiceURL({
-        siteno,
-        parameterCode: getPrimaryParameter(currentState).parameterCode,
-        startTime: toISO(timeRange.start),
-        endTime: toISO(timeRange.end),
-        format: 'rdb'
-    });
-};
-const getMedianDataURL = function(store, siteno) {
-    return getStatisticsServiceURL({
-        siteno,
-        parameterCode: getPrimaryParameter(store.getState()).parameterCode,
-        statType: 'median',
-        format: 'rdb'
-    });
-};
-const getGroundwaterLevelURL = function(siteno, agencyCd) {
-    return getGroundwaterServiceURL({
-        siteno,
-        agencyCd,
-        format: 'json'
-    });
-};
-const getSiteMetaDataURL = function(siteno) {
-    return getSiteMetaDataServiceURL({
-        siteno,
-        isExpanded: true
-    });
-};
-
-/*
- * Helper function to render a single checkbox in container.
- */
-const drawRadioButton = function(container, inputID, label, value, nameSuffix) {
-    const radioContainer = container.append('div')
-        .attr('class', 'usa-radio');
-    radioContainer.append('input')
-        .attr('class', 'usa-radio__input')
-        .attr('id', inputID)
-        .attr('type', 'radio')
-        .attr('name', `retrieve-value-${nameSuffix}`)
-        .attr('value', value);
-    radioContainer.append('label')
-        .attr('class', 'usa-radio__label')
-        .attr('for', inputID)
-        .text(label);
-};
-
-/*
- * Helper function to remove existing checkboxes and then render the checkboxes for the visible data.
- */
-const drawRadioButtons = function(container, {
-    hasVisiblePrimaryIVData,
-    hasVisibleCompareIVData,
-    hasVisibleMedianData,
-    hasVisibleGroundwaterLevels,
-    primaryParameter,
-    uniqueId
-}) {
-    container.select('.download-radio-container').remove();
-    const radioContainer = container.append('div')
-        .attr('class', 'download-radio-container');
-    if (primaryParameter && !isCalculatedTemperature(primaryParameter.parameterCode)) {
-        if (hasVisiblePrimaryIVData) {
-            radioContainer.call(drawRadioButton, `download-primary-iv-data-${uniqueId}`, 'Current time-series data', 'primary', uniqueId);
-        }
-        if (hasVisibleCompareIVData) {
-            radioContainer.call(drawRadioButton, `download-compare-iv-data-${uniqueId}`, 'Prior year time-series data', 'compare', uniqueId);
-        }
-        if (hasVisibleMedianData) {
-            radioContainer.call(drawRadioButton, `download-median-data-${uniqueId}`, 'Median', 'median', uniqueId);
-        }
-        if (hasVisibleGroundwaterLevels) {
-            radioContainer.call(drawRadioButton, `download-field-visits-${uniqueId}`, 'Field visits', 'groundwater-levels', uniqueId);
-        }
-    }
-    radioContainer.call(drawRadioButton, `download-site-meta-data-${uniqueId}`, 'About this location', 'site', uniqueId);
-};
-
-/*
- * Render the download form and set up all appropriate even handlers. The checkboxes drawn are tied to what data is currently
- * visible on the hydrograph.
- * @param {D3 selection} container
- * @param {Redux store} store
- * @param {String} siteno
- * @param {String} agencyCd
- * @param {String} uniqueId
- */
-export const drawDownloadForm = function(container, store, siteno, agencyCd, uniqueId) {
-    const downloadContainer = container.append('div');
-    const formContainer = downloadContainer.append('div')
-        .attr('class', 'usa-form')
-        .append('fieldset')
-            .attr('class', 'usa-fieldset');
-    formContainer.append('legend')
-        .attr('class', 'usa-legend')
-        .text('Select data to be downloaded');
-    formContainer.append('div')
-        .attr('class', 'select-data-input-container')
-        .call(link(store, drawRadioButtons, createStructuredSelector({
-            hasVisiblePrimaryIVData: hasVisibleIVData('primary'),
-            hasVisibleCompareIVData: hasVisibleIVData('compare'),
-            hasVisibleMedianData: hasVisibleMedianStatisticsData,
-            hasVisibleGroundwaterLevels: hasVisibleGroundwaterLevels,
-            primaryParameter: getPrimaryParameter,
-            uniqueId: () => {
-                return uniqueId;
-            }
-        })));
-
-    const downloadButton = formContainer.append('button')
-        .attr('class', 'usa-button download-selected-data')
-        .attr('ga-on', 'click')
-        .attr('ga-event-category', 'download-selected-data')
-        .attr('ga-event-action', 'download')
-        .on('click', function() {
-            formContainer.selectAll('.alert-error-container').remove();
-            const radioInput = formContainer.select('input[type="radio"]:checked');
-            if (radioInput.size()) {
-                let downloadUrl;
-                let dataType = radioInput.attr('value');
-                switch (dataType) {
-                    case 'primary':
-                        downloadUrl = getIVDataURL(store, siteno, 'current');
-                        break;
-                    case 'compare':
-                        downloadUrl = getIVDataURL(store, siteno, 'prioryear');
-                        break;
-                    case 'median':
-                        downloadUrl = getMedianDataURL(store, siteno);
-                        break;
-                    case 'groundwater-levels':
-                        downloadUrl = getGroundwaterLevelURL(siteno, agencyCd);
-                        break;
-                    case 'site':
-                        downloadUrl = getSiteMetaDataURL(siteno);
-                        break;
-                    default:
-                        console.log(`Unhandled value for downloading data: ${dataType}`);
-                }
-                if (downloadUrl) {
-                    window.open(downloadUrl, '_blank');
-                }
-
-            } else {
-                formContainer.insert('div', 'button')
-                    .attr('class', 'alert-error-container')
-                    .call(drawErrorAlert, {
-                        body:'Please select one of the radio buttons',
-                        useSlim: true
-                    });
-            }
-        });
-    downloadButton.append('svg')
-        .attr('class', 'usa-icon')
-        .attr('aria-hidden', true)
-        .attr('role', 'img')
-        .html(`<use xlink:href="${config.STATIC_URL}img/sprite.svg#file_download"></use>`);
-    downloadButton.append('span').text('Retrieve');
-
-    downloadContainer.append('div')
-        .attr('class', 'download-info')
-        .html(INFO_TEXT);
-};
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/download-data.test.js b/assets/src/scripts/monitoring-location/components/hydrograph/download-data.test.js
deleted file mode 100644
index d67a0eb6f78b3843d45b37b3358e80b1c029565d..0000000000000000000000000000000000000000
--- a/assets/src/scripts/monitoring-location/components/hydrograph/download-data.test.js
+++ /dev/null
@@ -1,180 +0,0 @@
-import {select} from 'd3-selection';
-
-import config from 'ui/config';
-
-import {configureStore} from 'ml/store';
-import {setCompareDataVisibility, setMedianDataVisibility} from 'ml/store/hydrograph-state';
-
-import {drawDownloadForm} from './download-data';
-import {TEST_CURRENT_TIME_RANGE, TEST_PRIMARY_IV_DATA, TEST_STATS_DATA, TEST_GW_LEVELS} from './mock-hydrograph-state';
-
-
-describe('monitoring-location/components/hydrograph/download-data', () => {
-    config.SITE_DATA_ENDPOINT = 'https://fakeserviceroot.com/nwis/site';
-    config.IV_DATA_ENDPOINT = 'https://fakeserviceroot.com/nwis/iv';
-    config.HISTORICAL_IV_DATA_ENDPOINT = 'https://fakeserviceroot-more-than-120-days.com/nwis/iv';
-    config.STATISTICS_ENDPOINT = 'https://fakeserviceroot.com/nwis/stat';
-    config.GROUNDWATER_LEVELS_ENDPOINT = 'https://fakegroundwater.org/gwlevels/';
-    config.locationTimeZone = 'America/Chicago';
-
-    const TEST_STATE = {
-        hydrographData: {
-            currentTimeRange: TEST_CURRENT_TIME_RANGE,
-            prioryearTimeRange: TEST_CURRENT_TIME_RANGE,
-            primaryIVData: TEST_PRIMARY_IV_DATA,
-            compareIVData: TEST_PRIMARY_IV_DATA,
-            statisticsData: TEST_STATS_DATA
-        },
-        groundwaterLevelData: {
-            all: [TEST_GW_LEVELS]
-        },
-        hydrographState: {
-            showCompareIVData: false,
-            showMedianData: false,
-            selectedIVMethodID: '90649',
-            selectedParameterCode: '72019'
-        }
-    };
-
-    describe('drawDownloadForm', () => {
-        let div;
-        let store;
-        let windowSpy;
-
-        beforeEach(() => {
-            div = select('body').append('div');
-            store = configureStore(TEST_STATE);
-            windowSpy = jest.spyOn(window, 'open').mockImplementation(() => null);
-            drawDownloadForm(div, store, '11112222', 'USGS');
-        });
-
-        afterEach(() => {
-            div.remove();
-        });
-
-        it('Renders form with the appropriate radio buttons and download button', () => {
-            expect(div.selectAll('input[type="radio"]').size()).toBe(3);
-            expect(div.selectAll('input[value="primary"]').size()).toBe(1);
-            expect(div.selectAll('input[value="groundwater-levels"]').size()).toBe(1);
-            expect(div.selectAll('input[value="site"]').size()).toBe(1);
-            expect(div.selectAll('button.download-selected-data').size()).toBe(1);
-        });
-
-        it('Rerenders the radio buttons if data visibility changes', () => {
-            store.dispatch(setCompareDataVisibility(true));
-            store.dispatch(setMedianDataVisibility(true));
-            return new Promise(resolve => {
-                window.requestAnimationFrame(() => {
-                    expect(div.selectAll('input[type="radio"]').size()).toBe(5);
-                    expect(div.selectAll('input[value="compare"]').size()).toBe(1);
-                    expect(div.selectAll('input[value="median"]').size()).toBe(1);
-                    resolve();
-                });
-            });
-        });
-
-        it('Shows an error message if the download button is clicked with no radio buttons checked', () => {
-            const downloadButton = div.select('button.download-selected-data');
-            downloadButton.dispatch('click');
-            expect(div.select('.usa-alert--error').size()).toBe(1);
-        });
-
-        it('Opens a window with the URL for the selected data', () => {
-            const downloadButton = div.select('button.download-selected-data');
-            div.select('input[value="site"]').property('checked', true);
-            downloadButton.dispatch('click');
-
-            expect(div.select('.usa-alert--error').size()).toBe(0);
-            expect(windowSpy.mock.calls).toHaveLength(1);
-            expect(windowSpy.mock.calls[0][0]).toContain('/site/');
-            expect(windowSpy.mock.calls[0][0]).toContain('sites=11112222');
-        });
-
-        it('Opens a window for each selected data', () => {
-            const downloadButton = div.select('button.download-selected-data');
-            store.dispatch(setMedianDataVisibility(true));
-            return new Promise(resolve => {
-                window.requestAnimationFrame(() => {
-                    div.select('input[value="primary"]').property('checked', true);
-                    downloadButton.dispatch('click');
-                    expect(windowSpy.mock.calls[0][0]).toContain('/iv/');
-                    expect(windowSpy.mock.calls[0][0]).toContain('sites=11112222');
-                    expect(windowSpy.mock.calls[0][0]).toContain('parameterCd=72019');
-                    expect(windowSpy.mock.calls[0][0]).toContain('startDT=2020-02-24T10:15:00.000-06:00');
-                    expect(windowSpy.mock.calls[0][0]).toContain('endDT=2020-09-20T11:45:00.000-05:00');
-
-                    div.select('input[value="median"]').property('checked', true);
-                    downloadButton.dispatch('click');
-                    expect(windowSpy.mock.calls[1][0]).toContain('/stat/');
-                    expect(windowSpy.mock.calls[1][0]).toContain('statTypeCd=median');
-                    expect(windowSpy.mock.calls[1][0]).toContain('parameterCd=72019');
-
-                    div.select('input[value="groundwater-levels"]').property('checked', true);
-                    downloadButton.dispatch('click');
-                    expect(windowSpy.mock.calls[2][0]).toContain('/gwlevels/');
-                    expect(windowSpy.mock.calls[2][0]).toContain('featureId=USGS-11112222');
-
-                    resolve();
-                });
-            });
-        });
-
-        it('Expects the error alert to disappear once a user checks a box and clicks download', () => {
-            const downloadButton = div.select('button.download-selected-data');
-            downloadButton.dispatch('click');
-            div.select('input[value="site"]').property('checked', true);
-            downloadButton.dispatch('click');
-
-            expect(div.select('.usa-alert--error').size()).toBe(0);
-        });
-    });
-
-    describe('Tests for calculated primary parameter', () => {
-        const TEST_STATE_TWO = {
-            hydrographData: {
-                currentTimeRange: TEST_CURRENT_TIME_RANGE,
-                primaryIVData: {
-                    parameter: {
-                        parameterCode: '00010F'
-                    },
-                    values: {
-                        '11111': {
-                            points: [{value: '26.0', qualifiers: ['A'], dateTime: 1582560900000}],
-                            method: {
-                                methodID: '11111'
-                            }
-                        }
-                    }
-                }
-            },
-            groundwaterLevelData: {
-                all: []
-            },
-            hydrographState: {
-                showCompareIVData: false,
-                showMedianData: false,
-                selectedMethodID: '1111',
-                selectedParameterCode: '72019'
-            }
-        };
-
-        let div;
-        let store;
-        beforeEach(() => {
-            div = select('body').append('div');
-            store = configureStore(TEST_STATE_TWO);
-            drawDownloadForm(div, store, '11112222');
-        });
-
-        afterEach(() => {
-            div.remove();
-        });
-
-        it('Expect to render only the site radio button', () => {
-            expect(div.selectAll('input[type="radio"]').size()).toBe(1);
-            expect(div.selectAll('input[value="primary"]').size()).toBe(0);
-            expect(div.selectAll('input[value="groundwater-levels"]').size()).toBe(0);
-            expect(div.selectAll('input[value="site"]').size()).toBe(1);
-        });
-    });
-});
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/index.js b/assets/src/scripts/monitoring-location/components/hydrograph/index.js
index c29eadeff61749628062cf6644cb92e5033d59b2..30682c253aadc794214563c6b1c512ccc4420c19 100644
--- a/assets/src/scripts/monitoring-location/components/hydrograph/index.js
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/index.js
@@ -31,7 +31,6 @@ import {latestSelectedParameterValue} from 'ml/selectors/hydrograph-parameters-s
 import {getDailyStatistics} from 'ml/components/hydrograph/selectors/statistics';
 
 import {showDataIndicators} from './data-indicator';
-import {drawDataTables} from './data-table';
 import {initializeGraphBrush, drawGraphBrush} from './graph-brush';
 import {drawTimeSeriesLegend} from './legend';
 import {drawSelectActions} from './select-actions';
@@ -40,6 +39,7 @@ import {drawTimeSpanShortcutButtons} from './time-span-shortcuts';
 import {initializeTimeSeriesGraph, drawTimeSeriesGraphData} from './time-series-graph';
 import {initializeTooltipCursorSlider, drawTooltipCursorSlider} from './tooltip';
 
+import DataTablesApp from './DataTablesApp.vue';
 import GraphControlsApp from './GraphControlsApp.vue';
 import ParameterSelectionApp from './ParameterSelectionApp.vue';
 
@@ -136,6 +136,7 @@ export const attachToNode = function(store,
     const legendControlsContainer = graphContainer.append('div')
         .classed('ts-legend-controls-container', true);
     if (!showOnlyGraph) {
+        // eslint-disable-next-line vue/one-component-per-file
         const graphControlsApp = createApp(GraphControlsApp, {});
         graphControlsApp.use(ReduxConnectVue, {
             store,
@@ -176,8 +177,21 @@ export const attachToNode = function(store,
         legendControlsContainer.call(drawTimeSeriesLegend, store);
 
         if (!thisShowOnlyGraph) {
-            nodeElem.select('#iv-data-table-container')
-                .call(drawDataTables, store, siteno, agencyCd);
+            // eslint-disable-next-line vue/one-component-per-file
+            const dataTablesApp = createApp(DataTablesApp, {});
+            dataTablesApp.use(ReduxConnectVue, {
+                store,
+                mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
+                mapStateToPropsFactory: createStructuredSelector
+            });
+            dataTablesApp.provide('store', store);
+            // data for DownLoadData component
+            dataTablesApp.provide('siteno', siteno);
+            dataTablesApp.provide('agencyCd', agencyCd);
+            dataTablesApp.provide('buttonSetName', 'data-tables-set');
+
+            dataTablesApp.mount('#iv-data-table-container');
+
 
             renderTimeSeriesUrlParams(store);
             nodeElem.select('.daily-statistical-data')
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/index.test.js b/assets/src/scripts/monitoring-location/components/hydrograph/index.test.js
index d3596593fa721383ec5999fcc207f36cfc5ae91d..a53d2ab7985827987a692f60ee62d2c102c301ec 100644
--- a/assets/src/scripts/monitoring-location/components/hydrograph/index.test.js
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/index.test.js
@@ -363,9 +363,8 @@ describe('monitoring-location/components/hydrograph module', () => {
             expect(selectAll('#change-time-span-container').size()).toBe(1);
         });
 
-        it('should have two download data forms', () => {
+        it('should have one download container added with d3 (the vue component will not show in test)', () => {
             expect(selectAll('#download-graph-data-container-select-actions').size()).toBe(1);
-            expect(selectAll('#download-graph-data-container-data-table').size()).toBe(1);
         });
 
         it('should have method select element', () => {
@@ -492,8 +491,8 @@ describe('monitoring-location/components/hydrograph module', () => {
         });
 
         it('should not have data tables for hydrograph data', () => {
-            expect(select('#iv-hydrograph-data-table-container').size()).toBe(0);
-            expect(select('#gw-hydrograph-data-table-container').size()).toBe(0);
+            expect(select('#iv-table-container').size()).toBe(0);
+            expect(select('#gw-table-container').size()).toBe(0);
         });
 
         it('expects to not create a d3redux link for the daily statistics section', () => {
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/mock-hydrograph-state.js b/assets/src/scripts/monitoring-location/components/hydrograph/mock-hydrograph-state.js
index a733205635be5898623339219ecfd7d361df6a51..56dca08b4810cf16ddbb89eeaaeb049346635e33 100644
--- a/assets/src/scripts/monitoring-location/components/hydrograph/mock-hydrograph-state.js
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/mock-hydrograph-state.js
@@ -2,6 +2,12 @@ export const TEST_CURRENT_TIME_RANGE = {
     start: 1582560900000,
     end: 1600620300000
 };
+
+export const TEST_COMPARE_TIME_RANGE = {
+    start: 1339621064000,
+    end: 1371157064000
+};
+
 export const TEST_PRIMARY_IV_DATA = {
     parameter: {
         parameterCode: '72019',
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/select-actions.js b/assets/src/scripts/monitoring-location/components/hydrograph/select-actions.js
index effb745b40be2b17c0c7017d442cce7fb7b62a91..9d32fa493abc7b7387824200da7c21ba71b7c47d 100644
--- a/assets/src/scripts/monitoring-location/components/hydrograph/select-actions.js
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/select-actions.js
@@ -1,9 +1,17 @@
+
+import {bindActionCreators} from 'redux';
+import ReduxConnectVue from 'redux-connect-vue';
 import {select} from 'd3-selection';
+import {createStructuredSelector} from 'reselect';
+
+import {createApp} from 'vue';
 
 import config from 'ui/config.js';
 
 import {drawTimeSpanControls} from './time-span-controls';
-import {drawDownloadForm} from './download-data';
+
+import DownloadDataApp from './DownloadDataApp.vue';
+
 
 /*
  * Helper function to render a select action button on listContainer
@@ -56,6 +64,20 @@ const appendButton = function(listContainer, {uswdsIcon, buttonLabel, idOfDivToC
  * @param {String} siteno
  */
 export const drawSelectActions = function(container, store, siteno, agencyCode) {
+    const addDownloadContainer = function() {
+        const downloadDataApp = createApp(DownloadDataApp, {});
+        downloadDataApp.use(ReduxConnectVue, {
+            store,
+            mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
+            mapStateToPropsFactory: createStructuredSelector
+        });
+        downloadDataApp.provide('store', store);
+        downloadDataApp.provide('siteno', siteno);
+        downloadDataApp.provide('agencyCd', agencyCode);
+        downloadDataApp.provide('buttonSetName', 'select-actions-set');
+        downloadDataApp.mount('#download-graph-data-container-select-actions');
+    };
+
     const listContainer = container.append('ul')
         .attr('class', 'select-actions-button-group usa-button-group');
     if (config.ivPeriodOfRecord || config.gwPeriodOfRecord) {
@@ -79,5 +101,5 @@ export const drawSelectActions = function(container, store, siteno, agencyCode)
         .attr('id', 'download-graph-data-container-select-actions')
         .attr('class', 'download-graph-data-container')
         .attr('hidden', true)
-        .call(drawDownloadForm, store, siteno, agencyCode, 'hydrograph');
+        .call(addDownloadContainer);
 };
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/data-table.test.js b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/data-table.test.js
index d9b5e9c6a5506f6a468b71a0fb42801f57e09f45..9a18e0ad2aff9411631b9e10af47a6460b7428a9 100644
--- a/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/data-table.test.js
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/data-table.test.js
@@ -10,6 +10,7 @@ import {configureStore} from 'ml/store';
 import {TEST_PRIMARY_IV_DATA, TEST_GW_LEVELS} from '../mock-hydrograph-state';
 
 import DataTable from './data-table.vue';
+import DownloadData from './download-data.vue';
 
 describe('monitoring-location/components/hydrograph/components/data-table.vue', () => {
     let store;
@@ -126,4 +127,49 @@ describe('monitoring-location/components/hydrograph/components/data-table.vue',
         expect(wrapper.find('#iv-table-container').isVisible()).toBe(false);
         expect(wrapper.find('#gw-table-container').isVisible()).toBe(true);
     });
+
+    it('Shows only data retrieve button and download container', async() => {
+        store = configureStore({
+            hydrographData: {
+                currentTimeRange: {
+                    start: 1582560000000,
+                    end: 1600620000000
+                },
+                primaryIVData: TEST_PRIMARY_IV_DATA
+            },
+            groundwaterLevelData: {
+                all: []
+            },
+            hydrographState: {
+                selectedParameterCode: '72019',
+                selectedIVMethodID: '90649'
+            }
+        });
+
+        wrapper = mount(DataTable, {
+            global: {
+                plugins: [
+                    [ReduxConnectVue, {
+                        store,
+                        mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
+                        mapStateToPropsFactory: createStructuredSelector
+                    }]
+                ],
+                provide: {
+                    store: store,
+                    siteno: '11112222',
+                    agencyCd: 'USGS',
+                    buttonSetName: 'test-buttons'
+                }
+            }
+        });
+
+        expect(wrapper.findAll('button')).toHaveLength(1);
+        expect(wrapper.find('button').text()).toBe('Retrieve data');
+        expect(wrapper.findAllComponents(DownloadData)).toHaveLength(0);
+        await wrapper.find('button').trigger('click');
+        expect(wrapper.findAllComponents(DownloadData)).toHaveLength(1);
+        await wrapper.find('button').trigger('click');
+        expect(wrapper.findAllComponents(DownloadData)).toHaveLength(0);
+    });
 });
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/data-table.vue b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/data-table.vue
index 240f3b9d8221a8107802f76352596889c4fad7d8..4281e6f5fa6ee4dffcdb1e4edcf63767a1e3b502 100644
--- a/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/data-table.vue
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/data-table.vue
@@ -1,5 +1,5 @@
 <template>
-  <div>
+  <div id="iv-hydrograph-data-table-container">
     <div
       v-show="currentIVData.length"
       id="iv-table-container"
@@ -42,6 +42,34 @@
       </table>
       <ul class="pagination" />
     </div>
+
+    <button
+      id="download-graph-data-container-data-table-toggle"
+      class="usa-button"
+      aria-controls="download-graph-data-container-data-table"
+      ga-on="click"
+      ga-event-category="data-table"
+      ga-event-action="download-graph-data-container-data-table-toggle"
+      @click="toggleDownloadContainer"
+    >
+      <svg
+        class="usa-icon"
+        aria-hidden="true"
+        role="img"
+      >
+        <use
+          :xlink:href="downloadIcon"
+        />
+      </svg><span>Retrieve data</span>
+    </button>
+
+    <div
+      v-if="showDownloadContainer"
+      id="download-graph-data-container-data-table"
+      class="download-graph-data-container"
+    >
+      <DownloadData />
+    </div>
   </div>
 </template>
 
@@ -49,16 +77,25 @@
 import Pagination from 'list.js/src/pagination.js'; /* eslint no-unused-vars: off */
 import List from 'list.js';
 import {useState} from 'redux-connect-vue';
-import {inject, onMounted} from 'vue';
+import {ref, inject, onMounted} from 'vue';
 
 import {listen} from 'ui/lib/d3-redux';
 
+import config from 'ui/config.js';
+
 import {getIVTableData} from '../selectors/iv-data';
 import {getGroundwaterLevelsTableData} from '../selectors/discrete-data';
 
+import DownloadData from './download-data.vue';
+
 export default {
   name: 'DataTable',
+  components: {
+    DownloadData
+  },
   setup() {
+    const downloadIcon = `${config.STATIC_URL}img/sprite.svg#file_download`;
+    const showDownloadContainer = ref(false);
     const CONTAINER_ID = {
       iv: 'iv-table-container',
       gw: 'gw-table-container'
@@ -121,12 +158,18 @@ export default {
       listen(reduxStore, getGroundwaterLevelsTableData, updateGWDataTable);
     });
 
+    const toggleDownloadContainer = function() {
+      showDownloadContainer.value = !showDownloadContainer.value;
+    };
+
     return {
       ...state,
+      downloadIcon,
+      showDownloadContainer,
+      toggleDownloadContainer,
       ivColumnHeadings: COLUMN_HEADINGS.iv,
       gwColumnHeadings: COLUMN_HEADINGS.gw
     };
   }
-
 };
 </script>
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/download-data.test.js b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/download-data.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..322cd5d8ea39e700110c6d5704464d4ba7083438
--- /dev/null
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/download-data.test.js
@@ -0,0 +1,209 @@
+
+import config from 'ui/config';
+
+import {configureStore} from 'ml/store';
+import {setCompareDataVisibility, setMedianDataVisibility} from 'ml/store/hydrograph-state';
+
+import {
+    TEST_CURRENT_TIME_RANGE,
+    TEST_COMPARE_TIME_RANGE,
+    TEST_PRIMARY_IV_DATA,
+    TEST_STATS_DATA,
+    TEST_GW_LEVELS
+} from '../mock-hydrograph-state';
+import {mount} from '@vue/test-utils';
+
+import ReduxConnectVue from 'redux-connect-vue';
+import {createStructuredSelector} from 'reselect';
+import DownloadData from './download-data.vue';
+import USWDSAlert from 'ui/uswds-components/alert.vue';
+
+describe('monitoring-location/components/hydrograph/vue-components/download-data', () => {
+    config.SITE_DATA_ENDPOINT = 'https://fakeserviceroot.com/nwis/site';
+    config.IV_DATA_ENDPOINT = 'https://fakeserviceroot.com/nwis/iv';
+    config.HISTORICAL_IV_DATA_ENDPOINT = 'https://fakeserviceroot-more-than-120-days.com/nwis/iv';
+    config.STATISTICS_ENDPOINT = 'https://fakeserviceroot.com/nwis/stat';
+    config.GROUNDWATER_LEVELS_ENDPOINT = 'https://fakegroundwater.org/gwlevels/';
+    config.locationTimeZone = 'America/Chicago';
+
+    const TEST_STATE = {
+        hydrographData: {
+            currentTimeRange: TEST_CURRENT_TIME_RANGE,
+            prioryearTimeRange: TEST_COMPARE_TIME_RANGE,
+            primaryIVData: TEST_PRIMARY_IV_DATA,
+            compareIVData: TEST_PRIMARY_IV_DATA,
+            statisticsData: TEST_STATS_DATA
+        },
+        groundwaterLevelData: {
+            all: [TEST_GW_LEVELS]
+        },
+        hydrographState: {
+            showCompareIVData: false,
+            showMedianData: false,
+            selectedIVMethodID: '90649',
+            selectedParameterCode: '72019'
+        }
+    };
+
+    describe('tests for download data component', () => {
+        let store;
+        let windowSpy;
+        let wrapper;
+
+        beforeEach(() => {
+            windowSpy = jest.spyOn(window, 'open').mockImplementation(() => null);
+            store = configureStore(TEST_STATE);
+            wrapper = mount(DownloadData, {
+                global: {
+                    plugins: [
+                        [ReduxConnectVue, {
+                            store,
+                            mapStateToPropsFactory: createStructuredSelector
+                        }]
+                    ],
+                    provide: {
+                        store: store,
+                        siteno: '11112222',
+                        agencyCd: 'USGS',
+                        buttonSetName: 'test-buttons'
+                    }
+                }
+            });
+        });
+
+        it('Renders form with the appropriate radio buttons and download button', () => {
+            expect(wrapper.findAll('input[type="radio"]')).toHaveLength(3);
+            expect(wrapper.findAll('#test-buttons-primary-data-download-button')).toHaveLength(1);
+            expect(wrapper.findAll('#test-buttons-groundwater-levels-data-download-button')).toHaveLength(1);
+            expect(wrapper.findAll('#test-buttons-site-data-download-button')).toHaveLength(1);
+        });
+
+        it('Rerenders the radio buttons if data visibility changes', async() => {
+            expect(wrapper.findAll('input[type="radio"]')).toHaveLength(3);
+            await store.dispatch(setCompareDataVisibility(true));
+            expect(wrapper.findAll('input[type="radio"]')).toHaveLength(4);
+            await store.dispatch(setMedianDataVisibility(true));  
+            expect(wrapper.findAll('input[type="radio"]')).toHaveLength(5);
+        });
+
+        it('Shows an error message if the download button is clicked with no radio buttons checked', async() => {
+            const downloadButton = wrapper.find('button.download-selected-data');
+            await downloadButton.trigger('click');
+            expect(wrapper.findAllComponents(USWDSAlert)).toHaveLength(1);
+        });
+
+        it('Opens a window with the URL for the selected data', async() => {
+            const downloadButton = wrapper.find('button.download-selected-data');
+            const siteDataButton = wrapper.find('#test-buttons-site-data-download-button');
+            await siteDataButton.trigger('click');
+            await downloadButton.trigger('click');
+
+            expect(wrapper.findAllComponents(USWDSAlert)).toHaveLength(0);
+            expect(windowSpy.mock.calls).toHaveLength(1);
+            expect(windowSpy.mock.calls[0][0]).toContain('/site/');
+            expect(windowSpy.mock.calls[0][0]).toContain('sites=11112222');
+        });
+
+        it('Opens window with correct data for data type selected and downloaded', async() => {
+            const downloadButton = wrapper.find('button.download-selected-data');
+            await store.dispatch(setMedianDataVisibility(true));
+
+            const primaryDataButton = wrapper.find('#test-buttons-primary-data-download-button');
+            await primaryDataButton.trigger('click');
+            await downloadButton.trigger('click');
+            expect(windowSpy.mock.calls[0][0]).toContain('/iv/');
+            expect(windowSpy.mock.calls[0][0]).toContain('sites=11112222');
+            expect(windowSpy.mock.calls[0][0]).toContain('parameterCd=72019');
+            expect(windowSpy.mock.calls[0][0]).toContain('startDT=2020-02-24T10:15:00.000-06:00');
+            expect(windowSpy.mock.calls[0][0]).toContain('endDT=2020-09-20T11:45:00.000-05:00');
+
+
+            const medianDataButton = wrapper.find('#test-buttons-median-data-download-button');
+            await medianDataButton.trigger('click');
+            await downloadButton.trigger('click');
+            expect(windowSpy.mock.calls[1][0]).toContain('/stat/');
+            expect(windowSpy.mock.calls[1][0]).toContain('statTypeCd=median');
+            expect(windowSpy.mock.calls[1][0]).toContain('parameterCd=72019');
+
+
+            const groundWaterButton = wrapper.find('#test-buttons-groundwater-levels-data-download-button');
+            await groundWaterButton.trigger('click');
+            await downloadButton.trigger('click');
+            expect(windowSpy.mock.calls[2][0]).toContain('/gwlevels/');
+            expect(windowSpy.mock.calls[2][0]).toContain('featureId=USGS-11112222');
+        });
+
+        it('Opens window for compare data when selected and downloaded', async() => {
+            const downloadButton = wrapper.find('button.download-selected-data');
+            await store.dispatch(setCompareDataVisibility(true));
+
+            const compareDataButton = wrapper.find('#test-buttons-compare-data-download-button');
+            await compareDataButton.trigger('click');
+            await downloadButton.trigger('click');
+            expect(windowSpy.mock.calls[0][0]).toContain('/iv/');
+            expect(windowSpy.mock.calls[0][0]).toContain('sites=11112222');
+            expect(windowSpy.mock.calls[0][0]).toContain('parameterCd=72019');
+            expect(windowSpy.mock.calls[0][0]).toContain('startDT=2012-06-13T15:57:44.000-05:00');
+            expect(windowSpy.mock.calls[0][0]).toContain('endDT=2013-06-13T15:57:44.000-05:00');
+        });
+
+        it('Expects the error alert to disappear once a user selects a radio', async() => {
+            const downloadButton = wrapper.find('button.download-selected-data');
+            await downloadButton.trigger('click');
+            expect(wrapper.findAllComponents(USWDSAlert)).toHaveLength(1);
+
+            const siteDataButton = wrapper.find('#test-buttons-site-data-download-button');
+            await siteDataButton.trigger('click');
+            expect(wrapper.findAllComponents(USWDSAlert)).toHaveLength(0);
+        });
+    });
+
+    it('expects only the site button will show for calculated parameter 00010F', () => {
+        const TEST_STATE_CALCULATED_F = {
+            hydrographData: {
+                currentTimeRange: TEST_CURRENT_TIME_RANGE,
+                prioryearTimeRange: TEST_COMPARE_TIME_RANGE,
+                primaryIVData: {
+                    ...TEST_PRIMARY_IV_DATA,
+                    parameter: {
+                        parameterCode: '00010F',
+                        name: 'Calculated Temp',
+                        description: 'F (Calculated)',
+                        unit: 'F'
+                    }
+                },
+                compareIVData: TEST_PRIMARY_IV_DATA,
+                statisticsData: TEST_STATS_DATA
+            },
+            groundwaterLevelData: {
+                all: [TEST_GW_LEVELS]
+            },
+            hydrographState: {
+                showCompareIVData: true,
+                showMedianData: true,
+                selectedIVMethodID: '',
+                selectedParameterCode: '00010F'
+            }
+        };
+        const store = configureStore(TEST_STATE_CALCULATED_F);
+        const wrapper = mount(DownloadData, {
+            global: {
+                plugins: [
+                    [ReduxConnectVue, {
+                        store,
+                        mapStateToPropsFactory: createStructuredSelector
+                    }]
+                ],
+                provide: {
+                    store: store,
+                    siteno: '11112222',
+                    agencyCd: 'USGS',
+                    buttonSetName: 'test-buttons'
+                }
+            }
+        });
+
+        expect(wrapper.findAll('input[type="radio"]')).toHaveLength(1);
+        expect(wrapper.findAll('#test-buttons-site-data-download-button')).toHaveLength(1);
+    });
+});
diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/download-data.vue b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/download-data.vue
new file mode 100644
index 0000000000000000000000000000000000000000..075fec0f4645648d0a3a907d4cb550ae66400382
--- /dev/null
+++ b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/download-data.vue
@@ -0,0 +1,288 @@
+<template>
+  <div class="download-data-component">
+    <fieldset class="usa-fieldset">
+      <legend class="usa-legend">
+        Select data to retrieve
+      </legend>
+
+      <div v-if="hasVisiblePrimaryIVData && !isCalculatedParameter">
+        <input
+          :id="`${buttonSetName}-primary-data-download-button`"
+          class="usa-radio__input"
+          type="radio"
+          :name="buttonSetName"
+          @click="createDownloadUrl('primary')"
+        >
+        <label
+          class="usa-radio__label"
+          :for="`${buttonSetName}-primary-data-download-button`"
+        >
+          Current time series
+        </label>
+      </div>
+
+      <div v-if="hasVisibleCompareIVData && !isCalculatedParameter">
+        <input
+          :id="`${buttonSetName}-compare-data-download-button`"
+          class="usa-radio__input"
+          type="radio"
+          :name="buttonSetName"
+          @click="createDownloadUrl('compare')"
+        >
+        <label
+          class="usa-radio__label"
+          :for="`${buttonSetName}-compare-data-download-button`"
+        >
+          Prior year time series
+        </label>
+      </div>
+
+      <div v-if="hasVisibleMedianData && !isCalculatedParameter">
+        <input
+          :id="`${buttonSetName}-median-data-download-button`"
+          class="usa-radio__input"
+          type="radio"
+          :name="buttonSetName"
+          @click="createDownloadUrl('median')"
+        >
+        <label
+          class="usa-radio__label"
+          :for="`${buttonSetName}-median-data-download-button`"
+        >
+          Median
+        </label>
+      </div>
+
+      <div v-if="hasVisibleGroundwaterLevels">
+        <input
+          :id="`${buttonSetName}-groundwater-levels-data-download-button`"
+          class="usa-radio__input"
+          type="radio"
+          name="buttonSetName"
+          @click="createDownloadUrl('groundwater-levels')"
+        >
+        <label
+          class="usa-radio__label"
+          :for="`${buttonSetName}-groundwater-levels-data-download-button`"
+        >
+          Field visits
+        </label>
+      </div>
+
+      <div>
+        <input
+          :id="`${buttonSetName}-site-data-download-button`"
+          class="usa-radio__input"
+          type="radio"
+          :name="buttonSetName"
+          @click="createDownloadUrl('site')"
+        >
+        <label
+          class="usa-radio__label"
+          :for="`${buttonSetName}-site-data-download-button`"
+        >
+          About this location
+        </label>
+      </div>
+
+      <div>
+        <USWDSAlert
+          v-if="showErrorMessage"
+          alert-type="error"
+          slim-alert
+          :static-root="staticRoot"
+        >
+          <template #default>
+            <p class="usa-alert__text">
+              You must select one of the choices above.
+            </p>
+          </template>
+        </USWDSAlert>
+
+        <button
+          class="usa-button download-selected-data"
+          ga-on="click"
+          ga-event-category="download-selected-data"
+          ga-event-action="download"
+          @click="retrieveData"
+        >
+          <svg
+            class="usa-icon"
+            aria-hidden="true"
+            role="img"
+          >
+            <use
+              :xlink:href="downloadIcon"
+            />
+          </svg>
+          Retrieve
+        </button>
+      </div>
+    </fieldset>
+
+    <div class="download-info">
+      <div>
+        <div>
+          A separate tab will open with the requested data.
+        </div>
+        <div>
+          All data is in
+          <a
+            href="https://waterdata.usgs.gov/nwis/?tab_delimited_format_info"
+            target="_blank"
+          >RDB</a> format.
+        </div>
+        <div>
+          Data is retrieved from <a
+            href="https://waterservices.usgs.gov"
+            target="_blank"
+          >USGS Water Data
+            Services.</a>
+        </div>
+        <div>
+          If you are an R user, use the
+          <a
+            href="https://usgs-r.github.io/dataRetrieval/"
+            target="_blank"
+          >USGS dataRetrieval package</a> to
+          download, analyze and plot your data
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import {useState} from 'redux-connect-vue';
+import {computed, ref, inject} from 'vue';
+
+import {DateTime} from 'luxon';
+import config from 'ui/config.js';
+import USWDSAlert from 'ui/uswds-components/alert.vue';
+
+import {getTimeRange} from 'ml/selectors/hydrograph-data-selector';
+import {getIVServiceURL, getSiteMetaDataServiceURL} from 'ui/web-services/instantaneous-values';
+import {getStatisticsServiceURL} from 'ui/web-services/statistics-data';
+import {getGroundwaterServiceURL} from 'ui/web-services/groundwater-levels';
+import {getPrimaryParameter} from 'ml/components/hydrograph/selectors/time-series-data';
+
+import {isCalculatedTemperature} from 'ml/parameter-code-utils';
+import {
+  hasVisibleGroundwaterLevels,
+  hasVisibleIVData,
+  hasVisibleMedianStatisticsData
+} from '../selectors/time-series-data';
+
+export default {
+  name: 'DownloadData',
+  components: {
+    USWDSAlert
+  },
+  setup() {
+    const downloadUrl = ref('');
+    const showErrorMessage = ref(false);
+    const state =  useState({
+      hasVisiblePrimaryIVData: hasVisibleIVData('primary'),
+      hasVisibleCompareIVData: hasVisibleIVData('compare'),
+      hasVisibleMedianData: hasVisibleMedianStatisticsData,
+      hasVisibleGroundwaterLevels: hasVisibleGroundwaterLevels,
+      primaryParameter: getPrimaryParameter
+    });
+
+    const reduxStore = inject('store');
+    const siteno = inject('siteno');
+    const agencyCd = inject('agencyCd');
+    const buttonSetName = inject('buttonSetName');
+
+    const isCalculatedParameter = computed(() => {
+        return state.primaryParameter.value ? isCalculatedTemperature(state.primaryParameter.value['parameterCode']) : false;
+    });
+
+    const staticRoot = config.STATIC_URL;
+    const downloadIcon = `${config.STATIC_URL}img/sprite.svg#file_download`;
+
+    const toISO = function(inMillis) {
+      return DateTime.fromMillis(inMillis, {zone: config.locationTimeZone}).toISO();
+    };
+
+    const getIVDataURL =  function(reduxStore, siteno, timeRangeKind) {
+      const currentState = reduxStore.getState();
+      const timeRange = getTimeRange(timeRangeKind)(currentState);
+
+      return getIVServiceURL({
+        siteno,
+        parameterCode: getPrimaryParameter(currentState).parameterCode,
+        startTime: toISO(timeRange.start),
+        endTime: toISO(timeRange.end),
+        format: 'rdb'
+      });
+    };
+
+    const getMedianDataURL = function(store, siteno) {
+      return getStatisticsServiceURL({
+        siteno,
+        parameterCode: getPrimaryParameter(store.getState()).parameterCode,
+        statType: 'median',
+        format: 'rdb'
+      });
+    };
+
+    const getGroundwaterLevelURL = function(siteno, agencyCd) {
+      return getGroundwaterServiceURL({
+        siteno,
+        agencyCd,
+        format: 'json'
+      });
+    };
+
+    const getSiteMetaDataURL = function(siteno) {
+      return getSiteMetaDataServiceURL({
+        siteno,
+        isExpanded: true
+      });
+    };
+
+    const createDownloadUrl = (buttonSelected) => {
+      showErrorMessage.value = false;
+      switch (buttonSelected) {
+        case 'primary':
+          downloadUrl.value = getIVDataURL(reduxStore, siteno, 'current');
+          break;
+        case 'compare':
+          downloadUrl.value = getIVDataURL(reduxStore, siteno, 'prioryear');
+          break;
+        case 'median':
+          downloadUrl.value = getMedianDataURL(reduxStore, siteno);
+          break;
+        case 'groundwater-levels':
+          downloadUrl.value = getGroundwaterLevelURL(siteno, agencyCd);
+          break;
+        case 'site':
+          downloadUrl.value = getSiteMetaDataURL(siteno);
+          break;
+      }
+    };
+
+  const retrieveData = () => {
+    if (downloadUrl.value) {
+      showErrorMessage.value = false;
+      window.open(downloadUrl.value, '_blank');
+    } else {
+      showErrorMessage.value = true;
+    }
+  };
+
+    return {
+      ...state,
+      buttonSetName,
+      createDownloadUrl,
+      downloadIcon,
+      isCalculatedParameter,
+      retrieveData,
+      showErrorMessage,
+      staticRoot
+    };
+  }
+};
+</script>
+
diff --git a/assets/src/scripts/uswds-components/alert.test.js b/assets/src/scripts/uswds-components/alert.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..802310d4dff5b9e0d508d2395ae35c474bfebc77
--- /dev/null
+++ b/assets/src/scripts/uswds-components/alert.test.js
@@ -0,0 +1,119 @@
+import {mount} from '@vue/test-utils';
+
+import USWDSAlert from './alert.vue';
+
+
+describe('components/uswds/alert', () => {
+    it('expects a success message', () => {
+        const wrapper = mount(USWDSAlert, {
+            slots: {
+                default: '<p class="usa-alert__text">content</p>'
+            },
+            propsData: {
+                alertType: 'success',
+                alertTitle: 'This Alert'
+            }
+        });
+        const wrapperClasses = wrapper.classes();
+        expect(wrapper.find('.usa-alert__body').exists()).toBe(true);
+        expect(wrapper.find('.usa-alert__heading').text()).toContain('This Alert');
+        expect(wrapperClasses).toContain('usa-alert--success');
+        expect(wrapperClasses).not.toContain('usa-alert--slim');
+        expect(wrapperClasses).not.toContain('usa-alert--no-icon');
+        expect(wrapper.find('.usa-alert__text').text()).toBe('content');
+    });
+
+    it('expects a error message with no alert icon', () => {
+        const wrapper = mount(USWDSAlert, {
+            slots: {
+                default: '<p>content</p>'
+            },
+            props: {
+                alertType: 'error',
+                showAlertIcon: false
+            }
+        });
+
+
+        expect(wrapper.find('.usa-alert__body').exists()).toBe(true);
+        expect(wrapper.find('.usa-alert__heading').exists()).toBe(false);
+        const wrapperClasses = wrapper.classes();
+        expect(wrapperClasses).toContain('usa-alert--error');
+        expect(wrapperClasses).toContain('usa-alert--no-icon');
+    });
+
+    it('expects a info message', () => {
+        const wrapper = mount(USWDSAlert, {
+            slots: {
+                default: '<p>content</p>'
+            },
+            props: {
+                alertType: 'info',
+                alertTitle: 'Notice'
+            }
+        });
+
+        expect(wrapper.find('.usa-alert__body').exists()).toBe(true);
+        expect(wrapper.find('.usa-alert__body').text()).toContain('Notice');
+        expect(wrapper.classes()).toContain('usa-alert--info');
+    });
+
+    it('expects that the alert component will be slim', () => {
+        const wrapper = mount(USWDSAlert, {
+            slots: {
+                default: '<p>content</p>'
+            },
+            props: {
+                alertType: 'info',
+                slimAlert: true
+            }
+        });
+
+        const wrapperClasses = wrapper.classes();
+        expect(wrapperClasses).toContain('usa-alert--info');
+        expect(wrapperClasses).toContain('usa-alert--slim');
+    });
+
+    it('expects no close button', () => {
+        const wrapper = mount(USWDSAlert, {
+            slots: {
+                default: '<p>content</p>'
+            },
+            props: {
+                alertType: 'info'
+            }
+        });
+
+        expect(wrapper.findAll('button')).toHaveLength(0);
+    });
+
+    it('expects a close icon', () => {
+        const wrapper = mount(USWDSAlert, {
+            slots: {
+                default: '<p>content</p>'
+            },
+            props: {
+                alertType: 'info',
+                showClose: true,
+                staticRoot: '/fake/'
+            }
+        });
+        expect(wrapper.findAll('.message-close')).toHaveLength(1);
+        expect(wrapper.find('.message-close').html()).toContain('/fake/');
+    });
+
+    it('expects a click on the close button to emit event', async() => {
+        const wrapper = mount(USWDSAlert, {
+            slots: {
+                default: '<p>content</p>'
+            },
+            props: {
+                alertType: 'info',
+                showClose: true
+            }
+        });
+        expect(wrapper.findAll('.message-close')).toHaveLength(1);
+        await wrapper.find('.message-close').trigger('click');
+        expect(wrapper.emitted().closeAlert).toHaveLength(1);
+    });
+});
diff --git a/assets/src/scripts/uswds-components/alert.vue b/assets/src/scripts/uswds-components/alert.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0a27e72f9c4ac283804af0ce185154412951220b
--- /dev/null
+++ b/assets/src/scripts/uswds-components/alert.vue
@@ -0,0 +1,77 @@
+<template>
+  <div
+    class="usa-alert"
+    :class="`usa-alert--${alertType}${slimAlert ? ' usa-alert--slim' : ''} ${showAlertIcon ? '' : 'usa-alert--no-icon'}`"
+  >
+    <div class="usa-alert__body">
+      <h4
+        v-if="alertTitle"
+        class="usa-alert__heading"
+      >
+        {{ alertTitle }}
+      </h4>
+      <!-- @slot markup should start with tag with the class set to usa-alert__text -->
+      <slot />
+      <svg
+        v-if="showClose"
+        class="usa-icon message-close"
+        aria-label="close-icon"
+        role="img"
+        @click="$emit('closeAlert', $event)"
+      >
+        <use :xlink:href="closeIcon" />
+      </svg>
+    </div>
+  </div>
+</template>
+
+<script>
+/**
+ * @vue-prop {String} - alertType, A USWDS Alert message type (info, warning, error, or success)
+ * @vue-prop {Boolean} - slimAlert - set to true if the alert should be shown without the icon, defaults to false
+ * @vue-prop {Boolean} - showAlertIcon - Set to false if the alert icon should not be shown, defaults to true and will
+ *    be ignored if slimAlert is set to true.
+ * @vue-prop {Boolean} - showClose, show or hide the close button
+ * @vue-prop {String} - alertTitle, main title for the alert
+ * @vue-prop {String} - staticRoot - path to the root of the static assets, defaults to the empty string
+ * @vue-computed {String} - closeIcon, URL for the close 'X' icon
+ * @vue-event closeAlert - event emitted when alert close is clicked
+ */
+export default {
+  name: 'USWDSAlert',
+  props: {
+    alertType: {
+      type: String,
+      default: 'error',
+      validator: function(value) {
+        return ['info', 'success', 'warning', 'error'].includes(value);
+      }
+    },
+    slimAlert: {
+      type: Boolean,
+      default: false
+    },
+    showAlertIcon: {
+      type: Boolean,
+      default: true
+    },
+    showClose: {
+      type: Boolean,
+      default: false
+    },
+    alertTitle: {
+      type: String,
+      default: ''
+    },
+    staticRoot: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    closeIcon() {
+      return `${this.staticRoot}img/sprite.svg#close`;
+    }
+  }
+};
+</script>
diff --git a/assets/src/styles/components/hydrograph/_app.scss b/assets/src/styles/components/hydrograph/_app.scss
index c8505aa8747ff606bd02ac7e31eea36cf8beedaf..fd1565c91f08707ee19cd0d840a0ad9a755efc05 100644
--- a/assets/src/styles/components/hydrograph/_app.scss
+++ b/assets/src/styles/components/hydrograph/_app.scss
@@ -94,11 +94,12 @@
         }
       }
 
-      .alert-error-container {
+      .usa-alert {
         @include uswds.u-margin-top(2);
       }
 
       .download-selected-data {
+        @include uswds.u-margin-top(2);
         @include uswds.u-display('flex');
         @include uswds.u-flex('row');
         @include uswds.u-flex('align-center');
diff --git a/assets/src/styles/partials/_base.scss b/assets/src/styles/partials/_base.scss
index 065f031837ca5c8c801531c7baa3bb0649a7fde3..a2c0bfc90038ff8dda4c3f4bf1cb426b1b541bb8 100644
--- a/assets/src/styles/partials/_base.scss
+++ b/assets/src/styles/partials/_base.scss
@@ -5,7 +5,7 @@
 );
 @use 'wdfnviz';
 
-
+@forward 'usa-alert';
 @forward 'usa-prose';
 
 @use 'banner_notifications';
@@ -36,3 +36,19 @@
     @include uswds.u-padding-right(2);
   }
 }
+
+.usa-alert {
+  @include uswds.u-position('relative');
+  @include uswds.u-margin-bottom(1);
+
+  .message-close {
+    @include uswds.u-position('absolute');
+    @include uswds.u-top(2px);
+    @include uswds.u-right(1);
+    @include uswds.u-font('body', 'md');
+  }
+
+  .message-close:hover {
+    cursor: pointer;
+  }
+}
diff --git a/assets/vite.config.js b/assets/vite.config.js
index 171659ce5e54369879f4ed26908115e9cee2dff1..53195f9b40785c1dfbe3d73e0ca7c49513b7f282 100644
--- a/assets/vite.config.js
+++ b/assets/vite.config.js
@@ -24,7 +24,7 @@ const entries = [
 
 export default defineConfig(({command, mode}) => {
     return {
-        base: '/static/',
+        base: '/dist/',
         plugins: [
             vue({
                 isProduction: true,