diff --git modules/block.skinr.inc modules/block.skinr.inc
index 3392fa0..979ae56 100644
--- modules/block.skinr.inc
+++ modules/block.skinr.inc
@@ -44,6 +44,44 @@ function block_skinr_config_info() {
 }
 
 /**
+ * Implements hook_skinr_ui_element_options().
+ */
+function block_skinr_ui_element_options($theme_name = NULL) {
+  $themes = array();
+  if ($theme_name) {
+    // Only process the given theme.
+    $themes[] = $theme_name;
+  }
+  else {
+    // Process all enabled themes.
+    $options = array();
+    foreach (list_themes() as $theme) {
+      if (!$theme->status) {
+        continue;
+      }
+      $themes[] = $theme->name;
+    }
+  }
+
+  // Load all enabled blocks.
+  foreach ($themes as $theme) {
+    $blocks = _block_rehash($theme);
+    foreach ($blocks as $block) {
+      // @todo Should we only return enabled blocks, or should we return
+      //   them all?
+      if (!$block['status']) {
+        continue;
+      }
+      $name = $block['module'] . '__' . $block['delta'];
+      $options['block'][$name] = $block['info'];
+    }
+  }
+  asort($options['block']);
+
+  return $options;
+}
+
+/**
  * Skinr form index handler.
  *
  * @param $op
@@ -63,10 +101,10 @@ function block_skinr_config_info() {
 function block_skinr_form_index_handler($op, &$form, $form_state) {
   switch ($op) {
     case 'form':
-      return $form['module']['#value'] . '-' . $form['delta']['#value'];
+      return $form['module']['#value'] . '__' . $form['delta']['#value'];
 
     case 'submit':
-      return $form_state['values']['module'] . '-' . $form_state['values']['delta'];
+      return $form_state['values']['module'] . '__' . $form_state['values']['delta'];
   }
 }
 
@@ -85,10 +123,13 @@ function block_skinr_preprocess_hook_callback(&$form, $form_state) {
   $preprocess_hooks = array();
 
   if (empty($form['module']['#value']) && !empty($form['skinr']['element']['#value'])) {
+    list($module, $delta) = explode('__', $form['skinr']['element']['#value'], 2);
+
     $result = db_select('block', 'b')
       ->fields('b')
       ->distinct()
-      ->where('CONCAT(b.module, \'-\', b.delta) = :identifier', array(':identifier' => $form['skinr']['element']['#value']))
+      ->condition('b.module', $module)
+      ->condition('b.delta', $delta)
       ->range(0, 1)
       ->execute();
     foreach ($result as $block) {
@@ -115,7 +156,7 @@ function block_skinr_preprocess_hook_callback(&$form, $form_state) {
  *   structure and merge the returned classes.
  */
 function block_skinr_preprocess_index_handler(&$variables) {
-  return array($variables['block']->module . '-' . $variables['block']->delta);
+  return array($variables['block']->module . '__' . $variables['block']->delta);
 }
 
 /**
@@ -136,7 +177,7 @@ function block_skinr_preprocess_index_handler(&$variables) {
 function block_skinr_contextual_links(&$variables) {
   $links = array();
   $links['skinr-block'] = array(
-    'admin/appearance/skinr/edit/nojs', array('block', $variables['block']->module . '-' . $variables['block']->delta),
+    'admin/appearance/skinr/edit/nojs', array('block', $variables['block']->module . '__' . $variables['block']->delta),
   );
   return $links;
 }
diff --git modules/comment.skinr.inc modules/comment.skinr.inc
index d823cbe..a2ebae9 100644
--- modules/comment.skinr.inc
+++ modules/comment.skinr.inc
@@ -37,6 +37,19 @@ function comment_skinr_config_info() {
 }
 
 /**
+ * Implements hook_skinr_ui_element_options().
+ */
+function comment_skinr_ui_element_options($theme_name = NULL) {
+  $types = node_type_get_types();
+  foreach ($types as $type) {
+    $options['comment'][$type->type] = $type->name;
+  }
+  asort($options['comment']);
+
+  return $options;
+}
+
+/**
  * Skinr form index handler.
  *
  * @param $op
diff --git modules/node.skinr.inc modules/node.skinr.inc
index ad634d7..08fe1c6 100644
--- modules/node.skinr.inc
+++ modules/node.skinr.inc
@@ -35,6 +35,19 @@ function node_skinr_config_info() {
 }
 
 /**
+ * Implements hook_skinr_ui_element_options().
+ */
+function node_skinr_ui_element_options($theme_name = NULL) {
+  $types = node_type_get_types();
+  foreach ($types as $type) {
+    $options['node'][$type->type] = $type->name;
+  }
+  asort($options['node']);
+
+  return $options;
+}
+
+/**
  * Skinr form index handler.
  *
  * @param $op
diff --git modules/views.skinr.inc modules/views.skinr.inc
index 7beda1f..f6329e2 100644
--- modules/views.skinr.inc
+++ modules/views.skinr.inc
@@ -43,6 +43,24 @@ function views_skinr_config_info() {
 }
 
 /**
+ * Implements hook_skinr_ui_element_options().
+ */
+function views_skinr_ui_element_options($theme_name = NULL) {
+  $views = views_get_all_views();
+  // Load all enabled blocks.
+  foreach ($views as $view) {
+    foreach ($view->display as $display) {
+      $name = 'view-' . $view->name . '-display-' . $display->id;
+      // Fake indentation for views sub-items for better visual result.
+      $options['views']['&#160;&#160;&#160;' . $view->human_name][$name] = $display->display_title;
+    }
+  }
+  ksort($options['views']);
+
+  return $options;
+}
+
+/**
  * Skinr form index handler.
  *
  * @param $op
diff --git skinr_ui.admin.inc skinr_ui.admin.inc
index 6e117df..425e27d 100644
--- skinr_ui.admin.inc
+++ skinr_ui.admin.inc
@@ -1134,6 +1134,111 @@ function skinr_ui_import_form_submit(&$form, &$form_state) {
 }
 
 /**
+ * Return an array of element options for a module.
+ *
+ * If no field type is provided, returns a nested array of all element options,
+ * keyed by module.
+ */
+function skinr_ui_element_options($module = NULL) {
+  $cache = &drupal_static(__FUNCTION__);
+
+  if (!isset($cache)) {
+    $cache = array();
+
+    $config = skinr_get_config_info();
+    foreach ($config as $module => $settings) {
+      $function = $module . '_skinr_ui_element_options';
+      if (function_exists($function)) {
+        $options = $function();
+        if (isset($options) && is_array($options)) {
+          $cache += $options;
+        }
+      }
+    }
+  }
+
+  return $cache;
+}
+
+/**
+ * Form builder for the add a Skinr configuration form.
+ *
+ * @ingroup forms
+ */
+function skinr_ui_add($form, &$form_state) {
+  /*
+  $themes = list_themes();
+  ksort($themes);
+
+  $theme_options = array();
+  foreach ($themes as $theme) {
+    if (!$theme->status) {
+      continue;
+    }
+    $theme_options[$theme->name] = $theme->info['name'];
+  }
+  $form['theme'] = array(
+    '#type' => 'select',
+    '#title' => t('Theme'),
+    '#options' => $theme_options,
+    '#default_value' => skinr_current_theme(),
+    '#required' => TRUE,
+  );
+  */
+
+  $config = skinr_get_config_info();
+  $modules = system_rebuild_module_data();
+
+  $type_options = array();
+  foreach ($config as $module => $ignore) {
+    $name = $module;
+    if ($module == 'rules') {
+      // Exception for rules.
+      $name = t('Rules');
+    }
+    elseif (isset($modules[$module])) {
+      $name = $modules[$module]->info['name'];
+    }
+    $type_options[$module] = $name;
+  }
+
+  $form['type'] = array(
+    '#type' => 'select',
+    '#title' => t('Type'),
+    '#options' => $type_options,
+    '#required' => TRUE,
+  );
+
+  $element_options = skinr_ui_element_options();
+  $form['element'] = array(
+    '#type' => 'select',
+    '#title' => t('Element'),
+    '#options' => $element_options,
+    '#required' => TRUE,
+  );
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add'),
+  );
+
+  return $form;
+}
+
+function skinr_ui_add_validate($form, &$form_state) {
+  // @todo Do some validation.
+}
+
+function skinr_ui_add_submit($form, &$form_state) {
+  $destination = drupal_get_destination();
+  if ($destination['destination'] == 'admin/appearance/skinr/add') {
+    $destination['destination'] = 'admin/appearance/skinr';
+  }
+  $form_state['redirect'] = array('admin/appearance/skinr/edit/nojs/' . check_plain($form_state['values']['type']) . '/' . check_plain($form_state['values']['element']), array('query' => $destination));
+}
+
+/**
  * Form builder for the skinr settings delete confirmation form.
  *
  * @param $theme
diff --git skinr_ui.api.php skinr_ui.api.php
new file mode 100644
index 0000000..a047a64
--- /dev/null
+++ skinr_ui.api.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * @file
+ * This file contains no working PHP code; it exists to provide additional documentation
+ * for doxygen as well as to document hooks in the standard Drupal manner.
+ */
+
+/**
+ * @mainpage Skinr UI API Manual
+ *
+ * Topics:
+ * - @ref skinr_ui_hooks
+ */
+
+/**
+ * @defgroup skinr_ui_hooks Skinr UIs hooks
+ * @{
+ * Hooks that can be implemented by other modules in order to implement the
+ * Skinr UI API.
+ */
+
+/**
+ * Provide available element options for a module.
+ *
+ * @param $theme_name
+ *   The name of the theme to provide available options for.
+ *
+ * @return
+ *   An array consting of arrays of element options, keyed by the implementing
+ *   module name. Each of these array consists of element name => title pairs.
+ */
+function hook_skinr_ui_element_options($theme_name = NULL) {
+  $options['block'] = array(
+    'system__main_menu' => 'Main Menu',
+    'system__navigation' => 'Navigation',
+    'search__form' => 'Search form',
+  );
+
+  return $options;
+}
+
+/**
+ * @}
+ */
diff --git skinr_ui.module skinr_ui.module
index ba60df7..26be86e 100644
--- skinr_ui.module
+++ skinr_ui.module
@@ -128,6 +128,16 @@ function skinr_ui_menu() {
     'file' => 'skinr_ui.admin.inc',
   );
 
+  // Add skin settings for an element.
+  $items['admin/appearance/skinr/add'] = array(
+    'title' => 'Add skin configuration',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('skinr_ui_add'),
+    'type' => MENU_LOCAL_ACTION,
+    'access arguments' => array('edit skin settings'),
+    'file' => 'skinr_ui.admin.inc',
+  );
+
   // Configure skin settings for an element.
   $items['admin/appearance/skinr/edit/%skinr_js/%/%'] = array(
     'title' => 'Edit skin',
@@ -147,13 +157,13 @@ function skinr_ui_menu() {
     'context' => MENU_CONTEXT_INLINE,
   );
 
-  // Delete a skin configuration.
+  // Delete skin settings.
   $items['admin/appearance/skinr/delete/%skinr_skin'] = array(
-    'title' => 'Delete skin',
+    'title' => 'Delete skin configuration',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('skinr_ui_delete_confirm', 4),
     'type' => MENU_CALLBACK,
-    'access arguments' => array('administer skinr'),
+    'access arguments' => array('edit skin settings'),
     'file' => 'skinr_ui.admin.inc',
   );
 

