diff --git a/ts/components/conversation/EmbeddedContact.md b/ts/components/conversation/EmbeddedContact.md
deleted file mode 100644
index c53f8f8bf4..0000000000
--- a/ts/components/conversation/EmbeddedContact.md
+++ /dev/null
@@ -1,676 +0,0 @@
-### With a contact
-
-#### Including all data types
-
-```jsx
-const contact = {
- name: {
- displayName: 'Someone Somewhere',
- },
- number: [
- {
- value: '(202) 555-0000',
- type: 1,
- },
- ],
- avatar: {
- avatar: {
- path: util.gifObjectUrl,
- },
- },
- onClick: () => console.log('onClick'),
- onSendMessage: () => console.log('onSendMessage'),
- signalAccount: '+12025550000',
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### Image download pending
-
-```jsx
-const contact = {
- name: {
- displayName: 'Someone Somewhere',
- },
- number: [
- {
- value: '(202) 555-0000',
- type: 1,
- },
- ],
- avatar: {
- avatar: {
- pending: true,
- },
- },
- onClick: () => console.log('onClick'),
- onSendMessage: () => console.log('onSendMessage'),
- signalAccount: '+12025550000',
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### Really long data
-
-```jsx
-const contact = {
- name: {
- displayName:
- 'Dr. First Middle Last Junior Senior and all that and a bag of chips',
- },
- number: [
- {
- value: '(202) 555-0000 0000 0000 0000 0000 0000 0000 0000 0000 0000',
- type: 1,
- },
- ],
- avatar: {
- avatar: {
- path: util.gifObjectUrl,
- },
- },
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### In group conversation
-
-```jsx
-const contact = {
- name: {
- displayName: 'Someone Somewhere',
- },
- number: [
- {
- value: '(202) 555-0000',
- type: 1,
- },
- ],
- avatar: {
- avatar: {
- path: util.gifObjectUrl,
- },
- },
- signalAccount: '+12025550000',
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### If contact has no signal account
-
-```jsx
-const contact = {
- name: {
- displayName: 'Someone Somewhere',
- },
- number: [
- {
- value: '(202) 555-0000',
- type: 1,
- },
- ],
- avatar: {
- avatar: {
- path: util.gifObjectUrl,
- },
- },
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### With organization name instead of name
-
-```jsx
-const contact = {
- organization: 'United Somewheres, Inc.',
- email: [
- {
- value: 'someone@somewheres.com',
- type: 2,
- },
- ],
- avatar: {
- avatar: {
- path: util.gifObjectUrl,
- },
- },
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### No displayName or organization
-
-```jsx
-const contact = {
- name: {
- givenName: 'Someone',
- },
- number: [
- {
- value: '(202) 555-1000',
- type: 1,
- },
- ],
- avatar: {
- avatar: {
- path: util.gifObjectUrl,
- },
- },
- signalAccount: '+12025551000',
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### Default avatar
-
-```jsx
-const contact = {
- name: {
- displayName: 'Someone Somewhere',
- },
- number: [
- {
- value: '(202) 555-1001',
- type: 1,
- },
- ],
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### Empty contact
-
-```jsx
-const contact = {};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
-
-#### Contact with caption (cannot currently be sent)
-
-```jsx
-const contactWithAccount = {
- name: {
- displayName: 'Someone Somewhere',
- },
- number: [
- {
- value: '(202) 555-0000',
- type: 1,
- },
- ],
- avatar: {
- avatar: {
- path: util.gifObjectUrl,
- },
- },
- signalAccount: '+12025550000',
-};
-const contactWithoutAccount = {
- name: {
- displayName: 'Someone Somewhere',
- },
- number: [
- {
- value: '(202) 555-0000',
- type: 1,
- },
- ],
- avatar: {
- avatar: {
- path: util.gifObjectUrl,
- },
- },
-};
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-
- console.log('selectMessage', args)}
- />
-
-;
-```
diff --git a/ts/components/conversation/EmbeddedContact.stories.tsx b/ts/components/conversation/EmbeddedContact.stories.tsx
new file mode 100644
index 0000000000..746570d113
--- /dev/null
+++ b/ts/components/conversation/EmbeddedContact.stories.tsx
@@ -0,0 +1,172 @@
+import * as React from 'react';
+
+import { action } from '@storybook/addon-actions';
+import { boolean, number } from '@storybook/addon-knobs';
+import { storiesOf } from '@storybook/react';
+
+import { EmbeddedContact, Props } from './EmbeddedContact';
+
+// @ts-ignore
+import { setup as setupI18n } from '../../../js/modules/i18n';
+// @ts-ignore
+import enMessages from '../../../_locales/en/messages.json';
+import { ContactFormType } from '../../types/Contact';
+const i18n = setupI18n('en', enMessages);
+
+const story = storiesOf('Components/Conversation/EmbeddedContact', module);
+
+const createProps = (overrideProps: Partial = {}): Props => ({
+ contact: overrideProps.contact || {},
+ i18n,
+ isIncoming: boolean('isIncoming', overrideProps.isIncoming || false),
+ onClick: action('onClick'),
+ tabIndex: number('tabIndex', overrideProps.tabIndex || 0),
+ withContentAbove: boolean(
+ 'withContentAbove',
+ overrideProps.withContentAbove || false
+ ),
+ withContentBelow: boolean(
+ 'withContentBelow',
+ overrideProps.withContentBelow || false
+ ),
+});
+
+const fullContact = {
+ avatar: {
+ avatar: {
+ path: '/fixtures/giphy-GVNvOUpeYmI7e.gif',
+ },
+ isProfile: true,
+ },
+ email: [
+ {
+ value: 'jerjor@fakemail.com',
+ type: ContactFormType.HOME,
+ },
+ ],
+ name: {
+ givenName: 'Jerry',
+ familyName: 'Jordan',
+ prefix: 'Dr.',
+ suffix: 'Jr.',
+ middleName: 'James',
+ displayName: 'Jerry Jordan',
+ },
+ number: [
+ {
+ value: '555-444-2323',
+ type: ContactFormType.HOME,
+ },
+ ],
+};
+
+story.add('Full Contact', () => {
+ const props = createProps({
+ contact: fullContact,
+ });
+ return ;
+});
+
+story.add('Only Email', () => {
+ const props = createProps({
+ contact: {
+ email: fullContact.email,
+ },
+ });
+
+ return ;
+});
+
+story.add('Given Name', () => {
+ const props = createProps({
+ contact: {
+ name: {
+ givenName: 'Jerry',
+ },
+ },
+ });
+
+ return ;
+});
+
+story.add('Organization', () => {
+ const props = createProps({
+ contact: {
+ organization: 'Company 5',
+ },
+ });
+
+ return ;
+});
+
+story.add('Given + Family Name', () => {
+ const props = createProps({
+ contact: {
+ name: {
+ givenName: 'Jerry',
+ familyName: 'FamilyName',
+ },
+ },
+ });
+
+ return ;
+});
+
+story.add('Family Name', () => {
+ const props = createProps({
+ contact: {
+ name: {
+ familyName: 'FamilyName',
+ },
+ },
+ });
+
+ return ;
+});
+
+story.add('Loading Avatar', () => {
+ const props = createProps({
+ contact: {
+ name: {
+ displayName: 'Jerry Jordan',
+ },
+ avatar: {
+ avatar: {
+ pending: true,
+ },
+ isProfile: true,
+ },
+ },
+ });
+ return ;
+});
+
+story.add('Incoming', () => {
+ const props = createProps({
+ contact: {
+ name: fullContact.name,
+ },
+ isIncoming: true,
+ });
+
+ // Wrapped in a to provide a background for light color of text
+ return (
+
+
+
+ );
+});
+
+story.add('Content Above and Below', () => {
+ const props = createProps({
+ withContentAbove: true,
+ withContentBelow: true,
+ });
+ return (
+ <>
+
Content Above
+
+
Content Below
+ >
+ );
+});
diff --git a/ts/components/conversation/EmbeddedContact.tsx b/ts/components/conversation/EmbeddedContact.tsx
index 165d028575..dfad99ce2c 100644
--- a/ts/components/conversation/EmbeddedContact.tsx
+++ b/ts/components/conversation/EmbeddedContact.tsx
@@ -10,7 +10,7 @@ import {
renderName,
} from './_contactUtil';
-interface Props {
+export interface Props {
contact: ContactType;
i18n: LocalizerType;
isIncoming: boolean;