From d3d3c41f94cbced36586c6ac571acae84e9d7436 Mon Sep 17 00:00:00 2001 From: Chris Svenningsen Date: Thu, 13 Aug 2020 13:53:45 -0700 Subject: [PATCH] Convert component to Storybook Co-authored-by: Chris Svenningsen Co-authored-by: Sidney Keese --- ts/components/Avatar.md | 468 ------------------ ts/components/Avatar.stories.tsx | 126 +++++ ts/components/Avatar.tsx | 3 +- ts/components/CallManager.stories.tsx | 2 +- ts/components/CallScreen.stories.tsx | 2 +- ts/components/ContactListItem.tsx | 3 +- ts/components/ConversationListItem.tsx | 3 +- ts/components/IncomingCallBar.stories.tsx | 20 +- ts/components/MainHeader.tsx | 3 +- ts/components/MessageSearchResult.tsx | 3 +- .../conversation/ConversationHeader.tsx | 3 +- ts/components/conversation/Message.tsx | 3 +- ts/components/conversation/MessageDetail.tsx | 3 +- ts/components/conversation/Quote.tsx | 3 +- ts/components/conversation/ReactionViewer.tsx | 2 +- ts/components/conversation/TypingBubble.tsx | 3 +- ts/model-types.d.ts | 3 +- ts/state/ducks/calling.ts | 2 +- ts/state/ducks/conversations.ts | 2 +- ts/types/Colors.ts | 18 + ts/types/Util.ts | 16 - ts/util/lint/exceptions.json | 8 +- ts/util/migrateColor.ts | 21 +- ts/window.d.ts | 3 +- 24 files changed, 183 insertions(+), 540 deletions(-) delete mode 100644 ts/components/Avatar.md create mode 100644 ts/components/Avatar.stories.tsx create mode 100644 ts/types/Colors.ts diff --git a/ts/components/Avatar.md b/ts/components/Avatar.md deleted file mode 100644 index abedd4bf513c..000000000000 --- a/ts/components/Avatar.md +++ /dev/null @@ -1,468 +0,0 @@ -### With avatar - -```jsx - - - - - -
- console.log('onClick')} - i18n={util.i18n} - /> - console.log('onClick')} - i18n={util.i18n} - /> - console.log('onClick')} - i18n={util.i18n} - /> -
-``` - -### With only name - -```jsx - - - - -``` - -### Just phone number - -```jsx - - - -``` - -### Letters - -```jsx - - - - - -
- console.log('onClick')} - i18n={util.i18n} - /> - console.log('onClick')} - i18n={util.i18n} - /> - console.log('onClick')} - i18n={util.i18n} - /> -
-``` - -### Note to self - -```jsx - - - - - - -``` - -### Group Icon - -```jsx - - - - - - -``` - -### Contact Icon - -```jsx - - - - - - -``` - -### All colors, 28px - -```jsx - - - - - - - - - - - - - - - -``` - -### 52px - -```jsx - - - - - - - -``` - -### 80px - -```jsx - - - - - - - -``` - -### 112px - -```jsx - - - - - - - -``` - -### Broken color - -```jsx - - - -``` - -### Broken image - -```jsx - - - -``` - -### Broken image for group - -```jsx - - - -``` diff --git a/ts/components/Avatar.stories.tsx b/ts/components/Avatar.stories.tsx new file mode 100644 index 000000000000..e80220695443 --- /dev/null +++ b/ts/components/Avatar.stories.tsx @@ -0,0 +1,126 @@ +import * as React from 'react'; +import { Avatar, Props } from './Avatar'; + +import { storiesOf } from '@storybook/react'; +import { boolean, select, text } from '@storybook/addon-knobs'; +import { action } from '@storybook/addon-actions'; + +// @ts-ignore +import { setup as setupI18n } from '../../js/modules/i18n'; + +// @ts-ignore +import enMessages from '../../_locales/en/messages.json'; +import { Colors, ColorType } from '../types/Colors'; + +const i18n = setupI18n('en', enMessages); + +const story = storiesOf('Components/Avatar', module); + +const colorMap: Record = Colors.reduce( + (m, color) => ({ + ...m, + [color]: color, + }), + {} +); + +const conversationTypeMap: Record = { + direct: 'direct', + group: 'group', +}; + +const createProps = (overrideProps: Partial = {}): Props => ({ + avatarPath: text('avatarPath', overrideProps.avatarPath || ''), + color: select('color', colorMap, overrideProps.color || 'blue'), + conversationType: select( + 'conversationType', + conversationTypeMap, + overrideProps.conversationType || 'direct' + ), + i18n, + name: text('name', overrideProps.name || ''), + noteToSelf: boolean('noteToSelf', overrideProps.noteToSelf || false), + onClick: action('onClick'), + phoneNumber: text('phoneNumber', overrideProps.phoneNumber || ''), + size: 80, + title: '', +}); + +const sizes: Array = [112, 80, 52, 32, 28]; + +story.add('Avatar', () => { + const props = createProps({ + avatarPath: '/fixtures/giphy-GVNvOUpeYmI7e.gif', + }); + + return sizes.map(size => ); +}); + +story.add('One-word Name', () => { + const props = createProps({ + name: 'John', + }); + + return sizes.map(size => ); +}); + +story.add('Multi-word Name', () => { + const props = createProps({ + name: 'John Smith', + }); + + return sizes.map(size => ); +}); + +story.add('Note to Self', () => { + const props = createProps({ + noteToSelf: true, + }); + + return sizes.map(size => ); +}); + +story.add('Contact Icon', () => { + const props = createProps(); + + return sizes.map(size => ); +}); + +story.add('Group Icon', () => { + const props = createProps({ + conversationType: 'group', + }); + + return sizes.map(size => ); +}); + +story.add('Colors', () => { + const props = createProps(); + + return Colors.map(color => ); +}); + +story.add('Broken Color', () => { + const props = createProps({ + color: 'nope' as ColorType, + }); + + return sizes.map(size => ); +}); + +story.add('Broken Avatar', () => { + const props = createProps({ + avatarPath: 'badimage.png', + }); + + return sizes.map(size => ); +}); + +story.add('Broken Avatar for Group', () => { + const props = createProps({ + avatarPath: 'badimage.png', + conversationType: 'group', + }); + + return sizes.map(size => ); +}); diff --git a/ts/components/Avatar.tsx b/ts/components/Avatar.tsx index b5bf6e0b7c65..0e8afde31a7f 100644 --- a/ts/components/Avatar.tsx +++ b/ts/components/Avatar.tsx @@ -2,7 +2,8 @@ import * as React from 'react'; import classNames from 'classnames'; import { getInitials } from '../util/getInitials'; -import { ColorType, LocalizerType } from '../types/Util'; +import { LocalizerType } from '../types/Util'; +import { ColorType } from '../types/Colors'; export type Props = { avatarPath?: string; diff --git a/ts/components/CallManager.stories.tsx b/ts/components/CallManager.stories.tsx index 21bd88996ab0..99c59875a7e5 100644 --- a/ts/components/CallManager.stories.tsx +++ b/ts/components/CallManager.stories.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { CallManager } from './CallManager'; import { CallState } from '../types/Calling'; -import { ColorType } from '../types/Util'; +import { ColorType } from '../types/Colors'; // @ts-ignore import { setup as setupI18n } from '../../js/modules/i18n'; diff --git a/ts/components/CallScreen.stories.tsx b/ts/components/CallScreen.stories.tsx index 3c34b6b7edb9..9f847f8e17c7 100644 --- a/ts/components/CallScreen.stories.tsx +++ b/ts/components/CallScreen.stories.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { CallState } from '../types/Calling'; -import { ColorType } from '../types/Util'; +import { ColorType } from '../types/Colors'; import { CallScreen } from './CallScreen'; // @ts-ignore diff --git a/ts/components/ContactListItem.tsx b/ts/components/ContactListItem.tsx index 0438cffa0cdb..6a142840174f 100644 --- a/ts/components/ContactListItem.tsx +++ b/ts/components/ContactListItem.tsx @@ -5,7 +5,8 @@ import { Avatar } from './Avatar'; import { Emojify } from './conversation/Emojify'; import { InContactsIcon } from './InContactsIcon'; -import { ColorType, LocalizerType } from '../types/Util'; +import { LocalizerType } from '../types/Util'; +import { ColorType } from '../types/Colors'; interface Props { title: string; diff --git a/ts/components/ConversationListItem.tsx b/ts/components/ConversationListItem.tsx index aa303a383bf0..4cad6b6a42af 100644 --- a/ts/components/ConversationListItem.tsx +++ b/ts/components/ConversationListItem.tsx @@ -9,7 +9,8 @@ import { ContactName } from './conversation/ContactName'; import { TypingAnimation } from './conversation/TypingAnimation'; import { cleanId } from './_util'; -import { ColorType, LocalizerType } from '../types/Util'; +import { LocalizerType } from '../types/Util'; +import { ColorType } from '../types/Colors'; export type PropsData = { id: string; diff --git a/ts/components/IncomingCallBar.stories.tsx b/ts/components/IncomingCallBar.stories.tsx index 30e819dbe0c9..8c7679e807c4 100644 --- a/ts/components/IncomingCallBar.stories.tsx +++ b/ts/components/IncomingCallBar.stories.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { IncomingCallBar } from './IncomingCallBar'; -import { ColorType } from '../types/Util'; +import { Colors, ColorType } from '../types/Colors'; // @ts-ignore import { setup as setupI18n } from '../../js/modules/i18n'; @@ -31,22 +31,6 @@ const defaultProps = { i18n, }; -const colors: Array = [ - 'blue', - 'blue_grey', - 'brown', - 'deep_orange', - 'green', - 'grey', - 'indigo', - 'light_green', - 'pink', - 'purple', - 'red', - 'teal', - 'ultramarine', -]; - const permutations = [ { title: 'Incoming Call Bar (no call details)', @@ -74,7 +58,7 @@ const permutations = [ storiesOf('Components/IncomingCallBar', module) .add('Knobs Playground', () => { - const color = select('color', colors, 'ultramarine'); + const color = select('color', Colors, 'ultramarine'); const isVideoCall = boolean('isVideoCall', false); const name = text( 'name', diff --git a/ts/components/MainHeader.tsx b/ts/components/MainHeader.tsx index 60f2324513d4..97b7d458e813 100644 --- a/ts/components/MainHeader.tsx +++ b/ts/components/MainHeader.tsx @@ -7,7 +7,8 @@ import { createPortal } from 'react-dom'; import { showSettings } from '../shims/Whisper'; import { Avatar } from './Avatar'; import { AvatarPopup } from './AvatarPopup'; -import { ColorType, LocalizerType } from '../types/Util'; +import { LocalizerType } from '../types/Util'; +import { ColorType } from '../types/Colors'; export interface PropsType { searchTerm: string; diff --git a/ts/components/MessageSearchResult.tsx b/ts/components/MessageSearchResult.tsx index e4463d5a6280..4e753cfb9cd2 100644 --- a/ts/components/MessageSearchResult.tsx +++ b/ts/components/MessageSearchResult.tsx @@ -6,7 +6,8 @@ import { MessageBodyHighlight } from './MessageBodyHighlight'; import { Timestamp } from './conversation/Timestamp'; import { ContactName } from './conversation/ContactName'; -import { ColorType, LocalizerType } from '../types/Util'; +import { LocalizerType } from '../types/Util'; +import { ColorType } from '../types/Colors'; export type PropsDataType = { isSelected?: boolean; diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index 007c468960ae..97d47b5cd991 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -11,7 +11,8 @@ import { Emojify } from './Emojify'; import { Avatar } from '../Avatar'; import { InContactsIcon } from '../InContactsIcon'; -import { ColorType, LocalizerType } from '../../types/Util'; +import { LocalizerType } from '../../types/Util'; +import { ColorType } from '../../types/Colors'; interface TimerOption { name: string; diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index e77c6bb7e3db..079572283a4d 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -39,7 +39,8 @@ import { ContactType } from '../../types/Contact'; import { getIncrement } from '../../util/timer'; import { isFileDangerous } from '../../util/isFileDangerous'; -import { ColorType, LocalizerType } from '../../types/Util'; +import { LocalizerType } from '../../types/Util'; +import { ColorType } from '../../types/Colors'; import { createRefMerger } from '../_util'; import { ContextMenu, ContextMenuTrigger, MenuItem } from 'react-contextmenu'; diff --git a/ts/components/conversation/MessageDetail.tsx b/ts/components/conversation/MessageDetail.tsx index 972549bc0f26..65fd0f74491a 100644 --- a/ts/components/conversation/MessageDetail.tsx +++ b/ts/components/conversation/MessageDetail.tsx @@ -5,7 +5,8 @@ import moment from 'moment'; import { Avatar } from '../Avatar'; import { ContactName } from './ContactName'; import { Message, Props as MessageProps } from './Message'; -import { ColorType, LocalizerType } from '../../types/Util'; +import { LocalizerType } from '../../types/Util'; +import { ColorType } from '../../types/Colors'; interface Contact { status: string; diff --git a/ts/components/conversation/Quote.tsx b/ts/components/conversation/Quote.tsx index f422d8b39b27..7b8d6362fa2c 100644 --- a/ts/components/conversation/Quote.tsx +++ b/ts/components/conversation/Quote.tsx @@ -7,7 +7,8 @@ import * as MIME from '../../../ts/types/MIME'; import * as GoogleChrome from '../../../ts/util/GoogleChrome'; import { MessageBody } from './MessageBody'; -import { ColorType, LocalizerType } from '../../types/Util'; +import { LocalizerType } from '../../types/Util'; +import { ColorType } from '../../types/Colors'; import { ContactName } from './ContactName'; interface Props { diff --git a/ts/components/conversation/ReactionViewer.tsx b/ts/components/conversation/ReactionViewer.tsx index 7394dc4e8743..493706b74f3f 100644 --- a/ts/components/conversation/ReactionViewer.tsx +++ b/ts/components/conversation/ReactionViewer.tsx @@ -5,7 +5,7 @@ import { ContactName } from './ContactName'; import { Avatar, Props as AvatarProps } from '../Avatar'; import { Emoji } from '../emoji/Emoji'; import { useRestoreFocus } from '../../util/hooks'; -import { ColorType } from '../../types/Util'; +import { ColorType } from '../../types/Colors'; export type Reaction = { emoji: string; diff --git a/ts/components/conversation/TypingBubble.tsx b/ts/components/conversation/TypingBubble.tsx index 5e8171097c15..5988afeecccb 100644 --- a/ts/components/conversation/TypingBubble.tsx +++ b/ts/components/conversation/TypingBubble.tsx @@ -4,7 +4,8 @@ import classNames from 'classnames'; import { TypingAnimation } from './TypingAnimation'; import { Avatar } from '../Avatar'; -import { ColorType, LocalizerType } from '../../types/Util'; +import { LocalizerType } from '../../types/Util'; +import { ColorType } from '../../types/Colors'; interface Props { avatarPath?: string; diff --git a/ts/model-types.d.ts b/ts/model-types.d.ts index a4127ad64bfa..0e926bfb7ee0 100644 --- a/ts/model-types.d.ts +++ b/ts/model-types.d.ts @@ -1,6 +1,7 @@ import * as Backbone from 'backbone'; -import { ColorType, LocalizerType } from './types/Util'; +import { LocalizerType } from './types/Util'; +import { ColorType } from './types/Colors'; import { ConversationType } from './state/ducks/conversations'; import { CallingClass, CallHistoryDetailsType } from './services/calling'; import { SendOptionsType } from './textsecure/SendMessage'; diff --git a/ts/state/ducks/calling.ts b/ts/state/ducks/calling.ts index a0df0313933a..5b5a6fd383a6 100644 --- a/ts/state/ducks/calling.ts +++ b/ts/state/ducks/calling.ts @@ -2,7 +2,7 @@ import { notify } from '../../services/notify'; import { calling, VideoCapturer, VideoRenderer } from '../../services/calling'; import { CallState } from '../../types/Calling'; import { CanvasVideoRenderer, GumVideoCapturer } from '../../window.d'; -import { ColorType } from '../../types/Util'; +import { ColorType } from '../../types/Colors'; import { NoopActionType } from './noop'; import { callingTones } from '../../util/callingTones'; import { requestCameraPermissions } from '../../util/callingPermissions'; diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index c24fe6b606d0..6304323f7bd2 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -12,7 +12,7 @@ import { import { trigger } from '../../shims/events'; import { NoopActionType } from './noop'; import { AttachmentType } from '../../types/Attachment'; -import { ColorType } from '../../types/Util'; +import { ColorType } from '../../types/Colors'; // State diff --git a/ts/types/Colors.ts b/ts/types/Colors.ts new file mode 100644 index 000000000000..801a9a62dd57 --- /dev/null +++ b/ts/types/Colors.ts @@ -0,0 +1,18 @@ +export const Colors = [ + 'red', + 'deep_orange', + 'brown', + 'pink', + 'purple', + 'indigo', + 'blue', + 'teal', + 'green', + 'light_green', + 'blue_grey', + 'grey', + 'ultramarine', + 'signal-blue', +] as const; + +export type ColorType = typeof Colors[number]; diff --git a/ts/types/Util.ts b/ts/types/Util.ts index daa931c62911..2ec3d816f621 100644 --- a/ts/types/Util.ts +++ b/ts/types/Util.ts @@ -11,19 +11,3 @@ export type LocalizerType = ( key: string, values?: Array | ReplacementValuesType ) => string; - -export type ColorType = - | 'red' - | 'deep_orange' - | 'brown' - | 'pink' - | 'purple' - | 'indigo' - | 'blue' - | 'teal' - | 'green' - | 'light_green' - | 'blue_grey' - | 'grey' - | 'ultramarine' - | 'signal-blue'; diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index b4fc2352bbbd..4b0aeb643601 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -11770,7 +11770,7 @@ "rule": "React-createRef", "path": "ts/components/MainHeader.tsx", "line": " this.inputRef = React.createRef();", - "lineNumber": 70, + "lineNumber": 71, "reasonCategory": "usageTrusted", "updated": "2020-02-14T20:02:37.507Z", "reasonDetail": "Used only to set focus" @@ -11806,7 +11806,7 @@ "rule": "React-createRef", "path": "ts/components/conversation/ConversationHeader.tsx", "line": " this.menuTriggerRef = React.createRef();", - "lineNumber": 75, + "lineNumber": 76, "reasonCategory": "usageTrusted", "updated": "2020-05-20T20:10:43.540Z", "reasonDetail": "Used to reference popup menu" @@ -11850,7 +11850,7 @@ "rule": "React-createRef", "path": "ts/components/conversation/Message.tsx", "line": " public audioRef: React.RefObject = React.createRef();", - "lineNumber": 185, + "lineNumber": 186, "reasonCategory": "usageTrusted", "updated": "2020-05-21T16:56:07.875Z" }, @@ -11858,7 +11858,7 @@ "rule": "React-createRef", "path": "ts/components/conversation/Message.tsx", "line": " > = React.createRef();", - "lineNumber": 189, + "lineNumber": 190, "reasonCategory": "usageTrusted", "updated": "2020-05-21T16:56:07.875Z" }, diff --git a/ts/util/migrateColor.ts b/ts/util/migrateColor.ts index 21a68805a176..75ef94729b85 100644 --- a/ts/util/migrateColor.ts +++ b/ts/util/migrateColor.ts @@ -1,6 +1,8 @@ +import { ColorType } from '../types/Colors'; + // import { missingCaseError } from './missingCaseError'; -type OldColor = +type OldColorType = | 'amber' | 'blue' | 'blue_grey' @@ -22,22 +24,7 @@ type OldColor = | 'yellow' | 'ultramarine'; -type NewColor = - | 'red' - | 'deep_orange' - | 'brown' - | 'pink' - | 'purple' - | 'indigo' - | 'blue' - | 'teal' - | 'green' - | 'light_green' - | 'blue_grey' - | 'grey' - | 'ultramarine'; - -export function migrateColor(color: OldColor): NewColor { +export function migrateColor(color: OldColorType): ColorType { switch (color) { // These colors no longer exist case 'orange': diff --git a/ts/window.d.ts b/ts/window.d.ts index 67185e1b5363..09c8a5a6662e 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -18,7 +18,8 @@ import { ContactRecordIdentityState, TextSecureType } from './textsecure.d'; import { WebAPIConnectType } from './textsecure/WebAPI'; import { CallingClass, CallHistoryDetailsType } from './services/calling'; import * as Crypto from './Crypto'; -import { ColorType, LocalizerType } from './types/Util'; +import { LocalizerType } from './types/Util'; +import { ColorType } from './types/Colors'; import { ConversationController } from './ConversationController'; import { SendOptionsType } from './textsecure/SendMessage'; import Data from './sql/Client';