diff --git a/index.html b/index.html
index fd12104746..1034cd506e 100644
--- a/index.html
+++ b/index.html
@@ -34,8 +34,8 @@
     <body>
     </body>
     <script>
-        const FIVE_MINUTES = 5 * 60 * 1000;
-        const THIRTY_MINUTES = 30 * 60 * 1000;
+        const THIRTY_SECONDS = 30 * 1000;
+        const THIRTY_MINUTES = THIRTY_SECONDS * 60;
 
         [
             'example/eventGenerator'
@@ -63,7 +63,39 @@
                     bounds: {
                         start: Date.now() - THIRTY_MINUTES,
                         end: Date.now()
-                    }
+                    },
+                    // commonly used bounds can be stored in history
+                    // bounds (start and end) can accept either a milliseconds number
+                    // or a callback function returning a milliseconds number
+                    // a function is useful for invoking Date.now() at exact moment of preset selection
+                    presets: [
+                        {
+                            label: 'Last Day',
+                            bounds: {
+                                start: () => Date.now() - 1000 * 60 * 60 * 24,
+                                end: () => Date.now()
+                            }
+                        },
+                        {
+                            label: 'Last 2 hours',
+                            bounds: {
+                                start: () => Date.now() - 1000 * 60 * 60 * 2,
+                                end: () => Date.now()
+                            }
+                        },
+                        {
+                            label: 'Last hour',
+                            bounds: {
+                                start: () => Date.now() - 1000 * 60 * 60,
+                                end: () => Date.now()
+                            }
+                        }
+                    ],
+                    // maximum recent bounds to retain in conductor history
+                    records: 10,
+                    // maximum duration between start and end bounds
+                    // for utc-based time systems this is in milliseconds
+                    limit: 1000 * 60 * 60 * 24
                 },
                 {
                     name: "Realtime",
@@ -71,7 +103,7 @@
                     clock: 'local',
                     clockOffsets: {
                         start: - THIRTY_MINUTES,
-                        end: FIVE_MINUTES
+                        end: THIRTY_SECONDS
                     }
                 }
             ]
diff --git a/src/plugins/localTimeSystem/LocalTimeSystem.js b/src/plugins/localTimeSystem/LocalTimeSystem.js
index fd37b334df..3f08d07fe4 100644
--- a/src/plugins/localTimeSystem/LocalTimeSystem.js
+++ b/src/plugins/localTimeSystem/LocalTimeSystem.js
@@ -41,7 +41,7 @@ define([], function () {
         this.timeFormat = 'local-format';
         this.durationFormat = 'duration';
 
-        this.isUTCBased = false;
+        this.isUTCBased = true;
     }
 
     return LocalTimeSystem;
diff --git a/src/plugins/timeConductor/Conductor.vue b/src/plugins/timeConductor/Conductor.vue
index 63c3ced731..eaa9ce3d9b 100644
--- a/src/plugins/timeConductor/Conductor.vue
+++ b/src/plugins/timeConductor/Conductor.vue
@@ -22,7 +22,12 @@
 <template>
 <div
     class="c-conductor"
-    :class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode']"
+    :class="[
+        { 'is-zooming': isZooming },
+        { 'is-panning': isPanning },
+        { 'alt-pressed': altPressed },
+        isFixed ? 'is-fixed-mode' : 'is-realtime-mode'
+    ]"
 >
     <form
         ref="conductorForm"
@@ -52,7 +57,7 @@
                     type="text"
                     autocorrect="off"
                     spellcheck="false"
-                    @change="validateAllBounds(); submitForm()"
+                    @change="validateAllBounds('startDate'); submitForm()"
                 >
                 <date-picker
                     v-if="isFixed && isUTCBased"
@@ -92,7 +97,7 @@
                     autocorrect="off"
                     spellcheck="false"
                     :disabled="!isFixed"
-                    @change="validateAllBounds(); submitForm()"
+                    @change="validateAllBounds('endDate'); submitForm()"
                 >
                 <date-picker
                     v-if="isFixed && isUTCBased"
@@ -122,14 +127,25 @@
 
             <conductor-axis
                 class="c-conductor__ticks"
-                :bounds="rawBounds"
-                @panAxis="setViewFromBounds"
+                :view-bounds="viewBounds"
+                :is-fixed="isFixed"
+                :alt-pressed="altPressed"
+                @endPan="endPan"
+                @endZoom="endZoom"
+                @panAxis="pan"
+                @zoomAxis="zoom"
             />
+
         </div>
         <div class="c-conductor__controls">
-            <!-- Mode, time system menu buttons and duration slider -->
             <ConductorMode class="c-conductor__mode-select" />
             <ConductorTimeSystem class="c-conductor__time-system-select" />
+            <ConductorHistory
+                v-if="isFixed"
+                class="c-conductor__history-select"
+                :bounds="openmct.time.bounds()"
+                :time-system="timeSystem"
+            />
         </div>
         <input
             type="submit"
@@ -145,6 +161,7 @@ import ConductorTimeSystem from './ConductorTimeSystem.vue';
 import DatePicker from './DatePicker.vue';
 import ConductorAxis from './ConductorAxis.vue';
 import ConductorModeIcon from './ConductorModeIcon.vue';
+import ConductorHistory from './ConductorHistory.vue'
 
 const DEFAULT_DURATION_FORMATTER = 'duration';
 
@@ -155,7 +172,8 @@ export default {
         ConductorTimeSystem,
         DatePicker,
         ConductorAxis,
-        ConductorModeIcon
+        ConductorModeIcon,
+        ConductorHistory
     },
     data() {
         let bounds = this.openmct.time.bounds();
@@ -165,6 +183,7 @@ export default {
         let durationFormatter = this.getFormatter(timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
 
         return {
+            timeSystem: timeSystem,
             timeFormatter: timeFormatter,
             durationFormatter: durationFormatter,
             offsets: {
@@ -175,29 +194,68 @@ export default {
                 start: timeFormatter.format(bounds.start),
                 end: timeFormatter.format(bounds.end)
             },
-            rawBounds: {
+            viewBounds: {
                 start: bounds.start,
                 end: bounds.end
             },
             isFixed: this.openmct.time.clock() === undefined,
             isUTCBased: timeSystem.isUTCBased,
-            showDatePicker: false
+            showDatePicker: false,
+            altPressed: false,
+            isPanning: false,
+            isZooming: false
         }
     },
     mounted() {
+        document.addEventListener('keydown', this.handleKeyDown);
+        document.addEventListener('keyup', this.handleKeyUp);
         this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));
-
         this.openmct.time.on('bounds', this.setViewFromBounds);
         this.openmct.time.on('timeSystem', this.setTimeSystem);
         this.openmct.time.on('clock', this.setViewFromClock);
         this.openmct.time.on('clockOffsets', this.setViewFromOffsets)
     },
+    beforeDestroy() {
+        document.removeEventListener('keydown', this.handleKeyDown);
+        document.removeEventListener('keyup', this.handleKeyUp);
+    },
     methods: {
+        handleKeyDown(event) {
+            if (event.key === 'Alt') {
+                this.altPressed = true;
+            }
+        },
+        handleKeyUp(event) {
+            if (event.key === 'Alt') {
+                this.altPressed = false;
+            }
+        },
+        pan(bounds) {
+            this.isPanning = true;
+            this.setViewFromBounds(bounds);
+        },
+        endPan(bounds) {
+            this.isPanning = false;
+            if (bounds) {
+                this.openmct.time.bounds(bounds);
+            }
+        },
+        zoom(bounds) {
+            this.isZooming = true;
+            this.formattedBounds.start = this.timeFormatter.format(bounds.start);
+            this.formattedBounds.end = this.timeFormatter.format(bounds.end);
+        },
+        endZoom(bounds) {
+            const _bounds = bounds ? bounds : this.openmct.time.bounds();
+            this.isZooming = false;
+
+            this.openmct.time.bounds(_bounds);
+        },
         setTimeSystem(timeSystem) {
+            this.timeSystem = timeSystem
             this.timeFormatter = this.getFormatter(timeSystem.timeFormat);
             this.durationFormatter = this.getFormatter(
                 timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
-
             this.isUTCBased = timeSystem.isUTCBased;
         },
         setOffsetsFromView($event) {
@@ -237,8 +295,8 @@ export default {
         setViewFromBounds(bounds) {
             this.formattedBounds.start = this.timeFormatter.format(bounds.start);
             this.formattedBounds.end = this.timeFormatter.format(bounds.end);
-            this.rawBounds.start = bounds.start;
-            this.rawBounds.end = bounds.end;
+            this.viewBounds.start = bounds.start;
+            this.viewBounds.end = bounds.end;
         },
         setViewFromOffsets(offsets) {
             this.offsets.start = this.durationFormatter.format(Math.abs(offsets.start));
@@ -251,6 +309,15 @@ export default {
                 this.setOffsetsFromView();
             }
         },
+        getBoundsLimit() {
+            const configuration = this.configuration.menuOptions
+                .filter(option => option.timeSystem ===  this.timeSystem.key)
+                .find(option => option.limit);
+
+            const limit = configuration ? configuration.limit : undefined;
+
+            return limit;
+        },
         clearAllValidation() {
             if (this.isFixed) {
                 [this.$refs.startDate, this.$refs.endDate].forEach(this.clearValidationForInput);
@@ -262,36 +329,52 @@ export default {
             input.setCustomValidity('');
             input.title = '';
         },
-        validateAllBounds() {
-            return [this.$refs.startDate, this.$refs.endDate].every((input) => {
-                let validationResult = true;
-                let formattedDate;
+        validateAllBounds(ref) {
+            if (!this.areBoundsFormatsValid()) {
+                return false;
+            }
 
-                if (input === this.$refs.startDate) {
-                    formattedDate = this.formattedBounds.start;
+            let validationResult = true;
+            const currentInput = this.$refs[ref];
+
+            return [this.$refs.startDate, this.$refs.endDate].every((input) => {
+                let boundsValues = {
+                    start: this.timeFormatter.parse(this.formattedBounds.start),
+                    end: this.timeFormatter.parse(this.formattedBounds.end)
+                };
+                const limit = this.getBoundsLimit();
+
+                if (
+                    this.timeSystem.isUTCBased
+                    && limit
+                    && boundsValues.end - boundsValues.start > limit
+                ) {
+                    if (input === currentInput) {
+                        validationResult = "Start and end difference exceeds allowable limit";
+                    }
                 } else {
-                    formattedDate = this.formattedBounds.end;
+                    if (input === currentInput) {
+                        validationResult = this.openmct.time.validateBounds(boundsValues);
+                    }
                 }
 
+                return this.handleValidationResults(input, validationResult);
+            });
+        },
+        areBoundsFormatsValid() {
+            let validationResult = true;
+
+            return [this.$refs.startDate, this.$refs.endDate].every((input) => {
+                const formattedDate = input === this.$refs.startDate
+                    ? this.formattedBounds.start
+                    : this.formattedBounds.end
+                ;
+
                 if (!this.timeFormatter.validate(formattedDate)) {
                     validationResult = 'Invalid date';
-                } else {
-                    let boundsValues = {
-                        start: this.timeFormatter.parse(this.formattedBounds.start),
-                        end: this.timeFormatter.parse(this.formattedBounds.end)
-                    };
-                    validationResult = this.openmct.time.validateBounds(boundsValues);
                 }
 
-                if (validationResult !== true) {
-                    input.setCustomValidity(validationResult);
-                    input.title = validationResult;
-                    return false;
-                } else {
-                    input.setCustomValidity('');
-                    input.title = '';
-                    return true;
-                }
+                return this.handleValidationResults(input, validationResult);
             });
         },
         validateAllOffsets(event) {
@@ -315,17 +398,20 @@ export default {
                     validationResult = this.openmct.time.validateOffsets(offsetValues);
                 }
 
-                if (validationResult !== true) {
-                    input.setCustomValidity(validationResult);
-                    input.title = validationResult;
-                    return false;
-                } else {
-                    input.setCustomValidity('');
-                    input.title = '';
-                    return true;
-                }
+                return this.handleValidationResults(input, validationResult);
             });
         },
+        handleValidationResults(input, validationResult) {
+            if (validationResult !== true) {
+                input.setCustomValidity(validationResult);
+                input.title = validationResult;
+                return false;
+            } else {
+                input.setCustomValidity('');
+                input.title = '';
+                return true;
+            }
+        },
         submitForm() {
             // Allow Vue model to catch up to user input.
             // Submitting form will cause validation messages to display (but only if triggered by button click)
@@ -338,12 +424,12 @@ export default {
         },
         startDateSelected(date) {
             this.formattedBounds.start = this.timeFormatter.format(date);
-            this.validateAllBounds();
+            this.validateAllBounds('startDate');
             this.submitForm();
         },
         endDateSelected(date) {
             this.formattedBounds.end = this.timeFormatter.format(date);
-            this.validateAllBounds();
+            this.validateAllBounds('endDate');
             this.submitForm();
         }
     }
diff --git a/src/plugins/timeConductor/ConductorAxis.vue b/src/plugins/timeConductor/ConductorAxis.vue
index da7871b045..afe14d6bc5 100644
--- a/src/plugins/timeConductor/ConductorAxis.vue
+++ b/src/plugins/timeConductor/ConductorAxis.vue
@@ -24,7 +24,12 @@
     ref="axisHolder"
     class="c-conductor-axis"
     @mousedown="dragStart($event)"
-></div>
+>
+    <div
+        class="c-conductor-axis__zoom-indicator"
+        :style="zoomStyle"
+    ></div>
+</div>
 </template>
 
 <script>
@@ -43,52 +48,81 @@ const PIXELS_PER_TICK_WIDE = 200;
 export default {
     inject: ['openmct'],
     props: {
-        bounds: {
+        viewBounds: {
             type: Object,
             required: true
+        },
+        isFixed: {
+            type: Boolean,
+            required: true
+        },
+        altPressed: {
+            type: Boolean,
+            required: true
+        }
+    },
+    data() {
+        return {
+            inPanMode: false,
+            dragStartX: undefined,
+            dragX: undefined,
+            zoomStyle: {}
+        }
+    },
+    computed: {
+        inZoomMode() {
+            return !this.inPanMode;
         }
     },
     watch: {
-        bounds: {
-            handler(bounds) {
+        viewBounds: {
+            handler() {
                 this.setScale();
             },
             deep: true
         }
     },
     mounted() {
-        let axisHolder = this.$refs.axisHolder;
-        let height = axisHolder.offsetHeight;
-        let vis = d3Selection.select(axisHolder)
-            .append("svg:svg")
-            .attr("width", "100%")
-            .attr("height", height);
+        let vis = d3Selection.select(this.$refs.axisHolder).append("svg:svg");
 
-        this.width = this.$refs.axisHolder.clientWidth;
         this.xAxis = d3Axis.axisTop();
         this.dragging = false;
 
         // draw x axis with labels. CSS is used to position them.
-        this.axisElement = vis.append("g");
+        this.axisElement = vis.append("g")
+            .attr("class", "axis");
 
         this.setViewFromTimeSystem(this.openmct.time.timeSystem());
+        this.setAxisDimensions();
         this.setScale();
 
         //Respond to changes in conductor
         this.openmct.time.on("timeSystem", this.setViewFromTimeSystem);
         setInterval(this.resize, RESIZE_POLL_INTERVAL);
     },
-    destroyed() {
-    },
     methods: {
+        setAxisDimensions() {
+            const axisHolder = this.$refs.axisHolder;
+            const rect = axisHolder.getBoundingClientRect();
+
+            this.left = Math.round(rect.left);
+            this.width = axisHolder.clientWidth;
+        },
         setScale() {
+            if (!this.width) {
+                return;
+            }
+
             let timeSystem = this.openmct.time.timeSystem();
-            let bounds = this.bounds;
 
             if (timeSystem.isUTCBased) {
-                this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]);
+                this.xScale.domain(
+                    [new Date(this.viewBounds.start), new Date(this.viewBounds.end)]
+                );
             } else {
-                this.xScale.domain([bounds.start, bounds.end]);
+                this.xScale.domain(
+                    [this.viewBounds.start, this.viewBounds.end]
+                );
             }
 
             this.xAxis.scale(this.xScale);
@@ -102,7 +136,7 @@ export default {
                 this.xAxis.ticks(this.width / PIXELS_PER_TICK);
             }
 
-            this.msPerPixel = (bounds.end - bounds.start) / this.width;
+            this.msPerPixel = (this.viewBounds.end - this.viewBounds.start) / this.width;
         },
         setViewFromTimeSystem(timeSystem) {
             //The D3 scale used depends on the type of time system as d3
@@ -120,9 +154,8 @@ export default {
         },
         getActiveFormatter() {
             let timeSystem = this.openmct.time.timeSystem();
-            let isFixed = this.openmct.time.clock() === undefined;
 
-            if (isFixed) {
+            if (this.isFixed) {
                 return this.getFormatter(timeSystem.timeFormat);
             } else {
                 return this.getFormatter(timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
@@ -134,45 +167,131 @@ export default {
             }).formatter;
         },
         dragStart($event) {
-            let isFixed = this.openmct.time.clock() === undefined;
-            if (isFixed) {
+            if (this.isFixed) {
                 this.dragStartX = $event.clientX;
 
+                if (this.altPressed) {
+                    this.inPanMode = true;
+                }
+
                 document.addEventListener('mousemove', this.drag);
                 document.addEventListener('mouseup', this.dragEnd, {
                     once: true
                 });
+
+                if (this.inZoomMode) {
+                    this.startZoom();
+                }
             }
         },
         drag($event) {
             if (!this.dragging) {
                 this.dragging = true;
-                requestAnimationFrame(()=>{
-                    let deltaX = $event.clientX - this.dragStartX;
-                    let percX = deltaX / this.width;
-                    let bounds = this.openmct.time.bounds();
-                    let deltaTime = bounds.end - bounds.start;
-                    let newStart = bounds.start - percX * deltaTime;
-                    this.$emit('panAxis',{
-                        start: newStart,
-                        end: newStart + deltaTime
-                    });
+
+                requestAnimationFrame(() => {
+                    this.dragX = $event.clientX;
+                    this.inPanMode ? this.pan() : this.zoom();
                     this.dragging = false;
-                })
-            } else {
-                console.log('Rejected drag due to RAF cap');
+                });
             }
         },
         dragEnd() {
+            this.inPanMode ? this.endPan() : this.endZoom();
+
             document.removeEventListener('mousemove', this.drag);
-            this.openmct.time.bounds({
-                start: this.bounds.start,
-                end: this.bounds.end
+            this.dragStartX = undefined;
+            this.dragX = undefined;
+        },
+        pan() {
+            const panBounds = this.getPanBounds();
+            this.$emit('panAxis', panBounds);
+        },
+        endPan() {
+            const panBounds = this.dragStartX && this.dragX && this.dragStartX !== this.dragX
+                ? this.getPanBounds()
+                : undefined;
+            this.$emit('endPan', panBounds);
+            this.inPanMode = false;
+        },
+        getPanBounds() {
+            const bounds = this.openmct.time.bounds();
+            const deltaTime = bounds.end - bounds.start;
+            const deltaX = this.dragX - this.dragStartX;
+            const percX = deltaX / this.width;
+            const panStart = bounds.start - percX * deltaTime;
+
+            return {
+                start: panStart,
+                end: panStart + deltaTime
+            };
+        },
+        startZoom() {
+            const x = this.scaleToBounds(this.dragStartX);
+
+            this.zoomStyle = {
+                left: `${this.dragStartX - this.left}px`
+            };
+
+            this.$emit('zoomAxis', {
+                start: x,
+                end: x
             });
         },
+        zoom() {
+            const zoomRange = this.getZoomRange();
+
+            this.zoomStyle = {
+                left: `${zoomRange.start - this.left}px`,
+                width: `${zoomRange.end - zoomRange.start}px`
+            };
+
+            this.$emit('zoomAxis', {
+                start: this.scaleToBounds(zoomRange.start),
+                end: this.scaleToBounds(zoomRange.end)
+            });
+        },
+        endZoom() {
+            const zoomRange = this.dragStartX && this.dragX && this.dragStartX !== this.dragX
+                ? this.getZoomRange()
+                : undefined;
+
+            const zoomBounds = zoomRange
+                ? {
+                    start: this.scaleToBounds(zoomRange.start),
+                    end: this.scaleToBounds(zoomRange.end)
+                }
+                : this.openmct.time.bounds();
+
+            this.zoomStyle = {};
+            this.$emit('endZoom', zoomBounds);
+        },
+        getZoomRange() {
+            const leftBound = this.left;
+            const rightBound = this.left + this.width;
+
+            const zoomStart = this.dragX < leftBound
+                ? leftBound
+                : Math.min(this.dragX, this.dragStartX);
+
+            const zoomEnd = this.dragX > rightBound
+                ? rightBound
+                : Math.max(this.dragX, this.dragStartX);
+
+            return {
+                start: zoomStart,
+                end: zoomEnd
+            };
+        },
+        scaleToBounds(value) {
+            const bounds = this.openmct.time.bounds();
+            const timeDelta = bounds.end - bounds.start;
+            const valueDelta = value - this.left;
+            const offset = valueDelta / this.width * timeDelta;
+            return bounds.start + offset;
+        },
         resize() {
             if (this.$refs.axisHolder.clientWidth !== this.width) {
-                this.width = this.$refs.axisHolder.clientWidth;
+                this.setAxisDimensions();
                 this.setScale();
             }
         }
diff --git a/src/plugins/timeConductor/ConductorHistory.vue b/src/plugins/timeConductor/ConductorHistory.vue
new file mode 100644
index 0000000000..bcebf9dd5e
--- /dev/null
+++ b/src/plugins/timeConductor/ConductorHistory.vue
@@ -0,0 +1,200 @@
+/*****************************************************************************
+ * Open MCT Web, Copyright (c) 2014-2018, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT Web is licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ * Open MCT Web includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+<template>
+<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up">
+    <button class="c-button--menu c-history-button icon-history"
+            @click.prevent="toggle"
+    >
+        <span class="c-button__label">History</span>
+    </button>
+    <div v-if="open"
+         class="c-menu c-conductor__history-menu"
+    >
+        <ul v-if="hasHistoryPresets">
+            <li
+                v-for="preset in presets"
+                :key="preset.label"
+                class="icon-clock"
+                @click="selectPresetBounds(preset.bounds)"
+            >
+                {{ preset.label }}
+            </li>
+        </ul>
+
+        <div
+            v-if="hasHistoryPresets"
+            class="c-menu__section-separator"
+        ></div>
+
+        <div class="c-menu__section-hint">
+            Past timeframes, ordered by latest first
+        </div>
+
+        <ul>
+            <li
+                v-for="(timespan, index) in historyForCurrentTimeSystem"
+                :key="index"
+                class="icon-history"
+                @click="selectTimespan(timespan)"
+            >
+                {{ formatTime(timespan.start) }} - {{ formatTime(timespan.end) }}
+            </li>
+        </ul>
+    </div>
+</div>
+</template>
+
+<script>
+import toggleMixin from '../../ui/mixins/toggle-mixin';
+
+const LOCAL_STORAGE_HISTORY_KEY = 'tcHistory';
+const DEFAULT_RECORDS = 10;
+
+export default {
+    inject: ['openmct', 'configuration'],
+    mixins: [toggleMixin],
+    props: {
+        bounds: {
+            type: Object,
+            required: true
+        },
+        timeSystem: {
+            type: Object,
+            required: true
+        }
+    },
+    data() {
+        return {
+            history: {}, // contains arrays of timespans {start, end}, array key is time system key
+            presets: []
+        }
+    },
+    computed: {
+        hasHistoryPresets() {
+            return this.timeSystem.isUTCBased && this.presets.length;
+        },
+        historyForCurrentTimeSystem() {
+            const history = this.history[this.timeSystem.key];
+
+            return history;
+        }
+    },
+    watch: {
+        bounds: {
+            handler() {
+                this.addTimespan();
+            },
+            deep: true
+        },
+        timeSystem: {
+            handler() {
+                this.loadConfiguration();
+                this.addTimespan();
+            },
+            deep: true
+        },
+        history: {
+            handler() {
+                this.persistHistoryToLocalStorage();
+            },
+            deep: true
+        }
+    },
+    mounted() {
+        this.getHistoryFromLocalStorage();
+    },
+    methods: {
+        getHistoryFromLocalStorage() {
+            if (localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY)) {
+                this.history = JSON.parse(localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY))
+            } else {
+                this.history = {};
+                this.persistHistoryToLocalStorage();
+            }
+        },
+        persistHistoryToLocalStorage() {
+            localStorage.setItem(LOCAL_STORAGE_HISTORY_KEY, JSON.stringify(this.history));
+        },
+        addTimespan() {
+            const key = this.timeSystem.key;
+            let [...currentHistory] = this.history[key] || [];
+            const timespan = {
+                start: this.bounds.start,
+                end: this.bounds.end
+            };
+
+            const isNotEqual = function (entry) {
+                const start = entry.start !== this.start;
+                const end = entry.end !== this.end;
+
+                return start || end;
+            };
+            currentHistory = currentHistory.filter(isNotEqual, timespan);
+
+            while (currentHistory.length >= this.records) {
+                currentHistory.pop();
+            }
+
+            currentHistory.unshift(timespan);
+            this.history[key] = currentHistory;
+        },
+        selectTimespan(timespan) {
+            this.openmct.time.bounds(timespan);
+        },
+        selectPresetBounds(bounds) {
+            const start = typeof bounds.start === 'function' ? bounds.start() : bounds.start;
+            const end = typeof bounds.end === 'function' ? bounds.end() : bounds.end;
+
+            this.selectTimespan({
+                start: start,
+                end: end
+            });
+        },
+        loadConfiguration() {
+            const configurations = this.configuration.menuOptions
+                .filter(option => option.timeSystem ===  this.timeSystem.key);
+
+            this.presets = this.loadPresets(configurations);
+            this.records = this.loadRecords(configurations);
+        },
+        loadPresets(configurations) {
+            const configuration = configurations.find(option => option.presets);
+            const presets = configuration ? configuration.presets : [];
+
+            return presets;
+        },
+        loadRecords(configurations) {
+            const configuration = configurations.find(option => option.records);
+            const records = configuration ? configuration.records : DEFAULT_RECORDS;
+
+            return records;
+        },
+        formatTime(time) {
+            const formatter = this.openmct.telemetry.getValueFormatter({
+                format: this.timeSystem.timeFormat
+            }).formatter;
+
+            return formatter.format(time);
+        }
+    }
+}
+</script>
diff --git a/src/plugins/timeConductor/ConductorMode.vue b/src/plugins/timeConductor/ConductorMode.vue
index 070a711cc5..20d8d30c53 100644
--- a/src/plugins/timeConductor/ConductorMode.vue
+++ b/src/plugins/timeConductor/ConductorMode.vue
@@ -110,7 +110,7 @@ export default {
             if (clock === undefined) {
                 return {
                     key: 'fixed',
-                    name: 'Fixed Timespan Mode',
+                    name: 'Fixed Timespan',
                     description: 'Query and explore data that falls between two fixed datetimes.',
                     cssClass: 'icon-tabular'
                 }
diff --git a/src/plugins/timeConductor/conductor-axis.scss b/src/plugins/timeConductor/conductor-axis.scss
index 23ded63eaf..b16a58f718 100644
--- a/src/plugins/timeConductor/conductor-axis.scss
+++ b/src/plugins/timeConductor/conductor-axis.scss
@@ -13,7 +13,7 @@
         text-rendering: geometricPrecision;
         width: 100%;
         height: 100%;
-        > g {
+        > g.axis {
             // Overall Tick holder
             transform: translateY($tickYPos);
             path {
@@ -44,7 +44,6 @@
     }
 
     body.desktop .is-fixed-mode & {
-        @include cursorGrab();
         background-size: 3px 30%;
         background-color: $colorBodyBgSubtle;
         box-shadow: inset rgba(black, 0.4) 0 1px 1px;
@@ -55,17 +54,6 @@
             stroke: $colorBodyBgSubtle;
             transition: $transOut;
         }
-
-        &:hover,
-        &:active {
-            $c: $colorKeySubtle;
-            background-color: $c;
-            transition: $transIn;
-            svg text {
-                stroke: $c;
-                transition: $transIn;
-            }
-        }
     }
 
     .is-realtime-mode & {
diff --git a/src/plugins/timeConductor/conductor.scss b/src/plugins/timeConductor/conductor.scss
index dc5c308477..4ecba9e3f2 100644
--- a/src/plugins/timeConductor/conductor.scss
+++ b/src/plugins/timeConductor/conductor.scss
@@ -57,6 +57,65 @@
         }
     }
 
+    &.is-fixed-mode {
+        .c-conductor-axis {
+            &__zoom-indicator {
+                border: 1px solid transparent;
+                display: none; // Hidden by default
+            }
+        }
+
+        &:not(.is-panning),
+        &:not(.is-zooming) {
+            .c-conductor-axis {
+                &:hover,
+                &:active {
+                    cursor: col-resize;
+                    filter: $timeConductorAxisHoverFilter;
+                }
+            }
+        }
+
+        &.is-panning,
+        &.is-zooming {
+            .c-conductor-input input {
+                // Styles for inputs while zooming or panning
+                background: rgba($timeConductorActiveBg, 0.4);
+            }
+        }
+
+        &.alt-pressed {
+            .c-conductor-axis:hover {
+                // When alt is being pressed and user is hovering over the axis, set the cursor
+                @include cursorGrab();
+            }
+        }
+
+        &.is-panning {
+            .c-conductor-axis {
+                @include cursorGrab();
+                background-color: $timeConductorActivePanBg;
+                transition: $transIn;
+
+                svg text {
+                    stroke: $timeConductorActivePanBg;
+                    transition: $transIn;
+                }
+            }
+        }
+
+        &.is-zooming {
+            .c-conductor-axis__zoom-indicator {
+                display: block;
+                position: absolute;
+                background: rgba($timeConductorActiveBg, 0.4);
+                border-left-color: $timeConductorActiveBg;
+                border-right-color: $timeConductorActiveBg;
+                top: 0; bottom: 0;
+            }
+        }
+    }
+
     &.is-realtime-mode {
         .c-conductor__time-bounds {
             grid-template-columns: 20px auto 1fr auto auto;
diff --git a/src/styles/_constants-espresso.scss b/src/styles/_constants-espresso.scss
index 1ea130b891..3e3bbaf2db 100644
--- a/src/styles/_constants-espresso.scss
+++ b/src/styles/_constants-espresso.scss
@@ -142,6 +142,9 @@ $colorTimeHov: pullForward($colorTime, 10%);
 $colorTimeSubtle: pushBack($colorTime, 20%);
 $colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
 $colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
+$timeConductorAxisHoverFilter: brightness(1.2);
+$timeConductorActiveBg: $colorKey;
+$timeConductorActivePanBg: #226074;
 
 /************************************************** BROWSING */
 $browseFrameColor: pullForward($colorBodyBg, 10%);
diff --git a/src/styles/_constants-maelstrom.scss b/src/styles/_constants-maelstrom.scss
index 81a9cf3eae..d72abb7f8e 100644
--- a/src/styles/_constants-maelstrom.scss
+++ b/src/styles/_constants-maelstrom.scss
@@ -146,6 +146,9 @@ $colorTimeHov: pullForward($colorTime, 10%);
 $colorTimeSubtle: pushBack($colorTime, 20%);
 $colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
 $colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
+$timeConductorAxisHoverFilter: brightness(1.2);
+$timeConductorActiveBg: $colorKey;
+$timeConductorActivePanBg: #226074;
 
 /************************************************** BROWSING */
 $browseFrameColor: pullForward($colorBodyBg, 10%);
diff --git a/src/styles/_constants-snow.scss b/src/styles/_constants-snow.scss
index dcc4998f1a..7f44128019 100644
--- a/src/styles/_constants-snow.scss
+++ b/src/styles/_constants-snow.scss
@@ -132,7 +132,7 @@ $colorPausedFg: #fff;
 // Base variations
 $colorBodyBgSubtle: pullForward($colorBodyBg, 5%);
 $colorBodyBgSubtleHov: pushBack($colorKey, 50%);
-$colorKeySubtle: pushBack($colorKey, 10%);
+$colorKeySubtle: pushBack($colorKey, 20%);
 
 // Time Colors
 $colorTime: #618cff;
@@ -142,6 +142,9 @@ $colorTimeHov: pushBack($colorTime, 5%);
 $colorTimeSubtle: pushBack($colorTime, 20%);
 $colorTOI: $colorBodyFg; // was $timeControllerToiLineColor
 $colorTOIHov: $colorTime; // was $timeControllerToiLineColorHov
+$timeConductorAxisHoverFilter: brightness(0.8);
+$timeConductorActiveBg: $colorKey;
+$timeConductorActivePanBg: #A0CDE1;
 
 /************************************************** BROWSING */
 $browseFrameColor: pullForward($colorBodyBg, 10%);
diff --git a/src/styles/_controls.scss b/src/styles/_controls.scss
index 22a6497c05..565295d6dd 100644
--- a/src/styles/_controls.scss
+++ b/src/styles/_controls.scss
@@ -462,9 +462,17 @@ select {
     text-shadow: $shdwMenuText;
     padding: $interiorMarginSm;
     box-shadow: $shdwMenu;
-    display: block;
+    display: flex;
+    flex-direction: column;
     position: absolute;
     z-index: 100;
+
+    > * {
+        flex: 0 0 auto;
+        //+ * {
+        //    margin-top: $interiorMarginSm;
+        //}
+    }
 }
 
 @mixin menuInner() {
@@ -502,6 +510,23 @@ select {
 .c-menu {
     @include menuOuter();
     @include menuInner();
+
+    &__section-hint {
+        $m: $interiorMargin;
+        margin: $m 0;
+        padding: $m nth($menuItemPad, 2) 0 nth($menuItemPad, 2);
+
+        opacity: 0.6;
+        font-size: 0.9em;
+        font-style: italic;
+    }
+
+    &__section-separator {
+        $m: $interiorMargin;
+        border-top: 1px solid $colorInteriorBorder;
+        margin: $m 0;
+        padding: $m nth($menuItemPad, 2) 0 nth($menuItemPad, 2);
+    }
 }
 
 .c-super-menu {