diff --git a/src/components/Dropdown/Dropdown.Skeleton.svelte b/src/components/Dropdown/Dropdown.Skeleton.svelte
new file mode 100644
index 00000000..d6381922
--- /dev/null
+++ b/src/components/Dropdown/Dropdown.Skeleton.svelte
@@ -0,0 +1,20 @@
+
+
+
diff --git a/src/components/Dropdown/Dropdown.Story.svelte b/src/components/Dropdown/Dropdown.Story.svelte
new file mode 100644
index 00000000..7ff22997
--- /dev/null
+++ b/src/components/Dropdown/Dropdown.Story.svelte
@@ -0,0 +1,49 @@
+
+
+
+
+ {#if story === 'skeleton'}
+
+
+
+
+
+ {:else}
+ Currently, this component does not support items as slots.
+
+ items
+ must be an array of objects; mandatory fields are `id` and `text`.
+
+
+ {'items = Array<{ id: string; text: string; }>'}
+
+
+
+
+
+
+
+ {/if}
+
diff --git a/src/components/Dropdown/Dropdown.stories.js b/src/components/Dropdown/Dropdown.stories.js
new file mode 100644
index 00000000..0fe46fd6
--- /dev/null
+++ b/src/components/Dropdown/Dropdown.stories.js
@@ -0,0 +1,34 @@
+import { withKnobs, select, text, boolean } from '@storybook/addon-knobs';
+import Component from './Dropdown.Story.svelte';
+
+export default { title: 'Dropdown', decorators: [withKnobs] };
+
+const types = {
+ 'Default (default)': 'default',
+ 'Inline (inline)': 'inline'
+};
+
+const sizes = {
+ 'Extra large size (xl)': 'xl',
+ 'Regular size (lg)': '',
+ 'Small size (sm)': 'sm'
+};
+
+export const Default = () => ({
+ Component,
+ props: {
+ id: text('Dropdown ID (id)', 'carbon-dropdown-example'),
+ type: select('Dropdown type (type)', types, 'default'),
+ size: select('Field size (size)', sizes, '') || undefined,
+ label: text('Label (label)', 'Dropdown menu options'),
+ 'aria-label': text('Aria Label (aria-label)', 'Dropdown'),
+ disabled: boolean('Disabled (disabled)', false),
+ light: boolean('Light variant (light)', false),
+ titleText: text('Title (titleText)', 'This is not a dropdown title.'),
+ helperText: text('Helper text (helperText)', 'This is not some helper text.'),
+ invalid: boolean('Show form validation UI (invalid)', false),
+ invalidText: text('Form validation UI content (invalidText)', 'A valid value is required')
+ }
+});
+
+export const Skeleton = () => ({ Component, props: { story: 'skeleton' } });
diff --git a/src/components/Dropdown/Dropdown.svelte b/src/components/Dropdown/Dropdown.svelte
new file mode 100644
index 00000000..53ecb4fa
--- /dev/null
+++ b/src/components/Dropdown/Dropdown.svelte
@@ -0,0 +1,144 @@
+
+
+ {
+ if (open && fieldRef && !fieldRef.contains(target)) {
+ open = false;
+ }
+ }} />
+
+
+ {#if titleText}
+
+ {/if}
+ {#if !inline && helperText}
+
+ {helperText}
+
+ {/if}
+
{
+ open = fieldRef.contains(target) ? !open : false;
+ }}
+ {disabled}
+ {open}
+ {invalid}
+ {invalidText}
+ {light}>
+ {#if invalid}
+
+ {/if}
+ {
+ if (key === 'Enter') {
+ open = !open;
+ if (highlightedIndex > -1 && highlightedIndex !== selectedIndex) {
+ selectedIndex = highlightedIndex;
+ open = false;
+ }
+ } else if (key === 'Tab') {
+ open = false;
+ fieldRef.blur();
+ } else if (key === 'ArrowDown') {
+ change(1);
+ } else if (key === 'ArrowUp') {
+ change(-1);
+ }
+ }}
+ on:blur={({ relatedTarget }) => {
+ if (relatedTarget) {
+ fieldRef.focus();
+ }
+ }}
+ {disabled}
+ {translateWithId}
+ {id}>
+
+ {#if selectedItem}{itemToString(selectedItem)}{:else}{label}{/if}
+
+
+
+ {#if open}
+
+ {#each items as item, i (item.id || i)}
+ {
+ selectedId = item.id;
+ selectedIndex = i;
+ }}
+ on:mouseenter={() => {
+ highlightedIndex = i;
+ }}>
+ {itemToString(item)}
+
+ {/each}
+
+ {/if}
+
+
diff --git a/src/components/Dropdown/index.js b/src/components/Dropdown/index.js
new file mode 100644
index 00000000..b6df05fe
--- /dev/null
+++ b/src/components/Dropdown/index.js
@@ -0,0 +1,4 @@
+import Dropdown from './Dropdown.svelte';
+
+export default Dropdown;
+export { default as DropdownSkeleton } from './Dropdown.Skeleton.svelte';