diff --git a/admin_toolbar.info.yml b/admin_toolbar.info.yml
index 8f846d2..d4e0528 100644
--- a/admin_toolbar.info.yml
+++ b/admin_toolbar.info.yml
@@ -3,5 +3,6 @@ core: 8.x
 description: Provides a drop-down menu interface to the core Drupal Toolbar.
 package: Administration
 type: module
+configure: admin_toolbar.settings
 dependencies:
   - toolbar
diff --git a/admin_toolbar.install b/admin_toolbar.install
new file mode 100644
index 0000000..bd9447c
--- /dev/null
+++ b/admin_toolbar.install
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * Add admin toolbar config if not present.
+ */
+function admin_toolbar_update_8001() {
+  $config_factory = \Drupal::configFactory();
+  if ($config_factory->get('admin_toolbar.settings')->isNew()) {
+    // Save config.
+    $config_factory->getEditable('admin_toolbar.settings')
+      ->setData([
+        'enable_hover_intent' => FALSE,
+        'delay' => 1000,
+      ])->save();
+  }
+}
\ No newline at end of file
diff --git a/admin_toolbar.libraries.yml b/admin_toolbar.libraries.yml
index a5a1913..3cfdbc7 100644
--- a/admin_toolbar.libraries.yml
+++ b/admin_toolbar.libraries.yml
@@ -6,3 +6,19 @@ toolbar.tree:
     js/admin_toolbar.js: {}
   dependencies:
     - core/jquery
+toolbar.hover.css:
+  css:
+    theme:
+      css/admin.toolbar.hover.css: {}
+  dependencies:
+    - admin_toolbar/toolbar.tree
+toolbar.hover.intent:
+  css:
+    theme:
+      css/admin.toolbar.hover-intent.css: {}
+  js:
+    js/jquery.hoverIntent.js: {}
+    js/admin_toolbar_hoverIntent.js: {}
+  dependencies:
+    - admin_toolbar/toolbar.tree
+    - core/drupalSettings
\ No newline at end of file
diff --git a/admin_toolbar.links.menu.yml b/admin_toolbar.links.menu.yml
new file mode 100644
index 0000000..8e7f82b
--- /dev/null
+++ b/admin_toolbar.links.menu.yml
@@ -0,0 +1,5 @@
+admin_toolbar.settings:
+  title: 'Admin toolbar settings'
+  description: 'Configure admin toolbar.'
+  route_name: admin_toolbar.settings
+  parent: 'system.admin_config_ui'
\ No newline at end of file
diff --git a/admin_toolbar.module b/admin_toolbar.module
index 988d173..954371d 100644
--- a/admin_toolbar.module
+++ b/admin_toolbar.module
@@ -13,8 +13,18 @@ use Drupal\Core\Url;
  * Implements hook_toolbar_alter().
  */
 function admin_toolbar_toolbar_alter(&$items) {
+  $config = \Drupal::configFactory()->get('admin_toolbar.settings');
   $items['administration']['tray']['toolbar_administration']['#pre_render'] = ['admin_toolbar_prerender_toolbar_administration_tray'];
   $items['administration']['#attached']['library'][] = 'admin_toolbar/toolbar.tree';
+  if ($config->get('enable_hover_intent')) {
+    // Add hover intent support.
+    $items['administration']['#attached']['library'][] = 'admin_toolbar/toolbar.hover.intent';
+    $items['administration']['#attached']['drupalSettings']['adminToolbar']['hoverIntentDelay'] = (int) $config->get('delay');
+  }
+  else {
+    // Hovers are applied through css.
+    $items['administration']['#attached']['library'][] = 'admin_toolbar/toolbar.hover.css';
+  }
 }
 
 /**
diff --git a/admin_toolbar.routing.yml b/admin_toolbar.routing.yml
new file mode 100644
index 0000000..6df05fa
--- /dev/null
+++ b/admin_toolbar.routing.yml
@@ -0,0 +1,7 @@
+admin_toolbar.settings:
+  path: '/admin/config/user-interface/admin-toolbar'
+  defaults:
+    _form: '\Drupal\admin_toolbar\Form\AdminToolbarConfigForm'
+    _title: 'Admin toolbar settings'
+  requirements:
+    _permission: 'administer site configuration'
\ No newline at end of file
diff --git a/config/install/admin_toolbar.settings.yml b/config/install/admin_toolbar.settings.yml
new file mode 100644
index 0000000..875025c
--- /dev/null
+++ b/config/install/admin_toolbar.settings.yml
@@ -0,0 +1,2 @@
+enable_hover_intent: TRUE
+delay: 1000
diff --git a/config/schema/admin_toolbar.schema.yml b/config/schema/admin_toolbar.schema.yml
new file mode 100644
index 0000000..cd395f7
--- /dev/null
+++ b/config/schema/admin_toolbar.schema.yml
@@ -0,0 +1,10 @@
+admin_toolbar.settings:
+  type: config_object
+  label: 'Admin toolbar settings'
+  mapping:
+    enable_hover_intent:
+      type: boolean
+      label: 'Enable hover intent'
+    delay:
+      type: integer
+      label: 'Delay'
\ No newline at end of file
diff --git a/css/admin.toolbar.css b/css/admin.toolbar.css
index 9e32e1a..86045f8 100644
--- a/css/admin.toolbar.css
+++ b/css/admin.toolbar.css
@@ -33,37 +33,11 @@
   border-top: 1px solid #dddddd;
 }
 
-.toolbar-tray-horizontal li.menu-item--expanded:hover ul ul,
-.toolbar-tray-horizontal li.menu-item--expanded:hover ul ul ul,
-.toolbar-tray-horizontal li.menu-item--expanded:hover ul ul ul ul,
-.toolbar-tray-horizontal li.menu-item--expanded:hover ul ul ul ul ul {
-  display: none;
-  left: -999em; /* LTR */
-}
-
-/* Lists nested under hovered list items */
-.toolbar-tray-horizontal li.menu-item--expanded:hover ul,
-.toolbar-tray-horizontal li li.menu-item--expanded:hover ul,
-.toolbar-tray-horizontal li li li.menu-item--expanded:hover ul,
-.toolbar-tray-horizontal li li li li.menu-item--expanded:hover ul,
-.toolbar-tray-horizontal li li li li li.menu-item--expanded:hover ul {
-  display: block;
-  left: auto; /* LTR */
-}
-
 .toolbar-tray-horizontal .menu ul li a,
 .toolbar-tray-horizontal .menu ul .toolbar-icon {
   padding: 12px 15px 12px 12px;
 }
 
-.toolbar-tray-horizontal ul li.menu-item--expanded:hover ul {
-  display: block;
-  position: absolute;
-  width: 200px;
-  box-shadow: 2px 2px 3px hsla(0, 0%, 0%, 0.4);
-  z-index: 1;
-}
-
 .toolbar-tray-horizontal ul li.menu-item--expanded .menu-item > ul {
   display: none;
 }
@@ -74,15 +48,6 @@
   background-repeat: no-repeat;
 }
 
-.toolbar-tray-horizontal ul li.menu-item--expanded .menu-item:hover ul {
-  display: block;
-  margin: -40px 0 0 197px;
-}
-
-.toolbar-tray-horizontal li:hover ul li {
-  float: none;
-}
-
 .toolbar-tray-horizontal .toolbar .level-2 > ul {
   position: absolute;
   padding-top: 0;
diff --git a/css/admin.toolbar.hover-intent.css b/css/admin.toolbar.hover-intent.css
new file mode 100644
index 0000000..147d546
--- /dev/null
+++ b/css/admin.toolbar.hover-intent.css
@@ -0,0 +1,34 @@
+.toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul,
+.toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul ul,
+.toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul ul ul,
+.toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul ul ul ul {
+    display: none;
+    left: -999em; /* LTR */
+}
+
+/* Lists nested under hovered list items */
+.toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul,
+.toolbar-tray-horizontal li li.menu-item--expanded.hover-intent ul,
+.toolbar-tray-horizontal li li li.menu-item--expanded.hover-intent ul,
+.toolbar-tray-horizontal li li li li.menu-item--expanded.hover-intent ul,
+.toolbar-tray-horizontal li li li li li.menu-item--expanded.hover-intent ul {
+    display: block;
+    left: auto; /* LTR */
+}
+
+.toolbar-tray-horizontal ul li.menu-item--expanded.hover-intent ul {
+    display: block;
+    position: absolute;
+    width: 200px;
+    box-shadow: 2px 2px 3px hsla(0, 0%, 0%, 0.4);
+    z-index: 1;
+}
+
+.toolbar-tray-horizontal ul li.menu-item--expanded .menu-item.hover-intent ul {
+    display: block;
+    margin: -40px 0 0 197px;
+}
+
+.toolbar-tray-horizontal li.hover-intent ul li {
+    float: none;
+}
diff --git a/css/admin.toolbar.hover.css b/css/admin.toolbar.hover.css
new file mode 100644
index 0000000..c3d683f
--- /dev/null
+++ b/css/admin.toolbar.hover.css
@@ -0,0 +1,34 @@
+.toolbar-tray-horizontal li.menu-item--expanded:hover ul ul,
+.toolbar-tray-horizontal li.menu-item--expanded:hover ul ul ul,
+.toolbar-tray-horizontal li.menu-item--expanded:hover ul ul ul ul,
+.toolbar-tray-horizontal li.menu-item--expanded:hover ul ul ul ul ul {
+    display: none;
+    left: -999em; /* LTR */
+}
+
+/* Lists nested under hovered list items */
+.toolbar-tray-horizontal li.menu-item--expanded:hover ul,
+.toolbar-tray-horizontal li li.menu-item--expanded:hover ul,
+.toolbar-tray-horizontal li li li.menu-item--expanded:hover ul,
+.toolbar-tray-horizontal li li li li.menu-item--expanded:hover ul,
+.toolbar-tray-horizontal li li li li li.menu-item--expanded:hover ul {
+    display: block;
+    left: auto; /* LTR */
+}
+
+.toolbar-tray-horizontal ul li.menu-item--expanded:hover ul {
+    display: block;
+    position: absolute;
+    width: 200px;
+    box-shadow: 2px 2px 3px hsla(0, 0%, 0%, 0.4);
+    z-index: 1;
+}
+
+.toolbar-tray-horizontal ul li.menu-item--expanded .menu-item:hover ul {
+    display: block;
+    margin: -40px 0 0 197px;
+}
+
+.toolbar-tray-horizontal li:hover ul li {
+    float: none;
+}
diff --git a/js/admin_toolbar_hoverIntent.js b/js/admin_toolbar_hoverIntent.js
new file mode 100644
index 0000000..04908c9
--- /dev/null
+++ b/js/admin_toolbar_hoverIntent.js
@@ -0,0 +1,19 @@
+(function ($, drupalSettings) {
+  $(document).ready(function () {
+    console.log(drupalSettings);
+    // Add hoverIntent logic.
+    $(".toolbar-tray-horizontal li.menu-item--expanded, .toolbar-tray-horizontal ul li.menu-item--expanded .menu-item").hoverIntent({
+      over: function () {
+        // At the current depth, we should delete all "hover-intent" classes.
+        // Other wise we get unwanted behaviour where menu items are expanded while already in hovering other ones.
+        $(this).parent().find('li').removeClass('hover-intent');
+        $(this).addClass('hover-intent');
+      },
+      out: function () {
+        $(this).removeClass('hover-intent');
+      },
+      timeout: drupalSettings.adminToolbar.hoverIntentDelay
+    });
+  });
+})(jQuery, drupalSettings);
+
diff --git a/js/jquery.hoverIntent.js b/js/jquery.hoverIntent.js
new file mode 100644
index 0000000..5167de8
--- /dev/null
+++ b/js/jquery.hoverIntent.js
@@ -0,0 +1,158 @@
+/*!
+ * hoverIntent v1.8.1 // 2014.08.11 // jQuery v1.9.1+
+ * http://briancherne.github.io/jquery-hoverIntent/
+ *
+ * You may use hoverIntent under the terms of the MIT license. Basically that
+ * means you are free to use hoverIntent as long as this header is left intact.
+ * Copyright 2007, 2014 Brian Cherne
+ */
+
+/* hoverIntent is similar to jQuery's built-in "hover" method except that
+ * instead of firing the handlerIn function immediately, hoverIntent checks
+ * to see if the user's mouse has slowed down (beneath the sensitivity
+ * threshold) before firing the event. The handlerOut function is only
+ * called after a matching handlerIn.
+ *
+ * // basic usage ... just like .hover()
+ * .hoverIntent( handlerIn, handlerOut )
+ * .hoverIntent( handlerInOut )
+ *
+ * // basic usage ... with event delegation!
+ * .hoverIntent( handlerIn, handlerOut, selector )
+ * .hoverIntent( handlerInOut, selector )
+ *
+ * // using a basic configuration object
+ * .hoverIntent( config )
+ *
+ * @param  handlerIn   function OR configuration object
+ * @param  handlerOut  function OR selector for delegation OR undefined
+ * @param  selector    selector OR undefined
+ * @author Brian Cherne <brian(at)cherne(dot)net>
+ */
+
+;(function(factory) {
+    'use strict';
+    if (typeof define === 'function' && define.amd) {
+        define(['jquery'], factory);
+    } else if (jQuery && !jQuery.fn.hoverIntent) {
+        factory(jQuery);
+    }
+})(function($) {
+    'use strict';
+
+    // default configuration values
+    var _cfg = {
+        interval: 100,
+        sensitivity: 6,
+        timeout: 0
+    };
+
+    // counter used to generate an ID for each instance
+    var INSTANCE_COUNT = 0;
+
+    // current X and Y position of mouse, updated during mousemove tracking (shared across instances)
+    var cX, cY;
+
+    // saves the current pointer position coordinates based on the given mousemove event
+    var track = function(ev) {
+        cX = ev.pageX;
+        cY = ev.pageY;
+    };
+
+    // compares current and previous mouse positions
+    var compare = function(ev,$el,s,cfg) {
+        // compare mouse positions to see if pointer has slowed enough to trigger `over` function
+        if ( Math.sqrt( (s.pX-cX)*(s.pX-cX) + (s.pY-cY)*(s.pY-cY) ) < cfg.sensitivity ) {
+            $el.off(s.event,track);
+            delete s.timeoutId;
+            // set hoverIntent state as active for this element (permits `out` handler to trigger)
+            s.isActive = true;
+            // overwrite old mouseenter event coordinates with most recent pointer position
+            ev.pageX = cX; ev.pageY = cY;
+            // clear coordinate data from state object
+            delete s.pX; delete s.pY;
+            return cfg.over.apply($el[0],[ev]);
+        } else {
+            // set previous coordinates for next comparison
+            s.pX = cX; s.pY = cY;
+            // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
+            s.timeoutId = setTimeout( function(){compare(ev, $el, s, cfg);} , cfg.interval );
+        }
+    };
+
+    // triggers given `out` function at configured `timeout` after a mouseleave and clears state
+    var delay = function(ev,$el,s,out) {
+        delete $el.data('hoverIntent')[s.id];
+        return out.apply($el[0],[ev]);
+    };
+
+    $.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
+        // instance ID, used as a key to store and retrieve state information on an element
+        var instanceId = INSTANCE_COUNT++;
+
+        // extend the default configuration and parse parameters
+        var cfg = $.extend({}, _cfg);
+        if ( $.isPlainObject(handlerIn) ) {
+            cfg = $.extend(cfg, handlerIn);
+            if ( !$.isFunction(cfg.out) ) {
+                cfg.out = cfg.over;
+            }
+        } else if ( $.isFunction(handlerOut) ) {
+            cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
+        } else {
+            cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
+        }
+
+        // A private function for handling mouse 'hovering'
+        var handleHover = function(e) {
+            // cloned event to pass to handlers (copy required for event object to be passed in IE)
+            var ev = $.extend({},e);
+
+            // the current target of the mouse event, wrapped in a jQuery object
+            var $el = $(this);
+
+            // read hoverIntent data from element (or initialize if not present)
+            var hoverIntentData = $el.data('hoverIntent');
+            if (!hoverIntentData) { $el.data('hoverIntent', (hoverIntentData = {})); }
+
+            // read per-instance state from element (or initialize if not present)
+            var state = hoverIntentData[instanceId];
+            if (!state) { hoverIntentData[instanceId] = state = { id: instanceId }; }
+
+            // state properties:
+            // id = instance ID, used to clean up data
+            // timeoutId = timeout ID, reused for tracking mouse position and delaying "out" handler
+            // isActive = plugin state, true after `over` is called just until `out` is called
+            // pX, pY = previously-measured pointer coordinates, updated at each polling interval
+            // event = string representing the namespaced event used for mouse tracking
+
+            // clear any existing timeout
+            if (state.timeoutId) { state.timeoutId = clearTimeout(state.timeoutId); }
+
+            // namespaced event used to register and unregister mousemove tracking
+            var mousemove = state.event = 'mousemove.hoverIntent.hoverIntent'+instanceId;
+
+            // handle the event, based on its type
+            if (e.type === 'mouseenter') {
+                // do nothing if already active
+                if (state.isActive) { return; }
+                // set "previous" X and Y position based on initial entry point
+                state.pX = ev.pageX; state.pY = ev.pageY;
+                // update "current" X and Y position based on mousemove
+                $el.off(mousemove,track).on(mousemove,track);
+                // start polling interval (self-calling timeout) to compare mouse coordinates over time
+                state.timeoutId = setTimeout( function(){compare(ev,$el,state,cfg);} , cfg.interval );
+            } else { // "mouseleave"
+                // do nothing if not already active
+                if (!state.isActive) { return; }
+                // unbind expensive mousemove event
+                $el.off(mousemove,track);
+                // if hoverIntent state is true, then call the mouseOut function after the specified delay
+                state.timeoutId = setTimeout( function(){delay(ev,$el,state,cfg.out);} , cfg.timeout );
+            }
+        };
+
+        // listen for mouseenter and mouseleave
+        return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
+    };
+});
diff --git a/src/Form/AdminToolbarConfigForm.php b/src/Form/AdminToolbarConfigForm.php
new file mode 100644
index 0000000..1a2ef8a
--- /dev/null
+++ b/src/Form/AdminToolbarConfigForm.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Drupal\admin_toolbar\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Class AdminToolbarConfigForm
+ * @package Drupal\admin_toolbar\Form
+ */
+class AdminToolbarConfigForm extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'admin_toolbar_config_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getEditableConfigNames() {
+    return ['admin_toolbar.settings'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $config = $this->config('admin_toolbar.settings');
+
+    $form['enable_hover_intent'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Enable hover intent'),
+      '#description' => $this->t('This will set a delay on showing and hiding the admin menu.'),
+      '#default_value' => $config->get('enable_hover_intent'),
+    ];
+
+    $form['delay'] = [
+      '#type' => 'number',
+      '#title' => $this->t('Delay (ms)'),
+      '#step' => 1,
+      '#description' => $this->t('The delay in milliseconds.'),
+      '#default_value' => $config->get('delay'),
+      '#states' => [
+        'visible' => [
+          ':input[name="enable_hover_intent"]' => ['checked' => TRUE],
+        ],
+      ],
+    ];
+
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    if ($form_state->getValue('enable_hover_intent') && empty($form_state->getValue('delay'))) {
+      $form_state->setErrorByName('delay', $this->t('Please fill out a delay.'));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $config = $this->config('admin_toolbar.settings');
+    $config->set('enable_hover_intent', $form_state->getValue('enable_hover_intent'))
+      ->set('delay', $form_state->getValue('delay'))->save();
+    parent::submitForm($form, $form_state);
+  }
+
+}
\ No newline at end of file
