diff --git a/ts/components/stickers/StickerButton.md b/ts/components/stickers/StickerButton.md
deleted file mode 100644
index b941411860..0000000000
--- a/ts/components/stickers/StickerButton.md
+++ /dev/null
@@ -1,495 +0,0 @@
-#### Default
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- cover: sticker1,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'bar',
- cover: sticker2,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'baz',
- cover: sticker3,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[abeSticker, sticker1, sticker2, sticker3]}
- />
-
-;
-```
-
-#### No Installed Packs
-
-When there are no installed packs the button should call the `onClickAddPack`
-callback.
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- cover: sticker1,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'bar',
- cover: sticker2,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'baz',
- cover: sticker3,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[abeSticker, sticker1, sticker2, sticker3]}
- />
-
-;
-```
-
-#### Just known packs
-
-Even with just known packs, the button should render.
-
-```jsx
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-
-const packs = [
- {
- id: 'foo',
- cover: sticker1,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
-];
-
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[]}
- />
-;
-```
-
-#### Just blessed packs
-
-Even with just blessed packs, the button should render.
-
-```jsx
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-
-const packs = [
- {
- id: 'foo',
- cover: sticker1,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
-];
-
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[]}
- />
-;
-```
-
-#### No packs at all
-
-When there are no advertised packs and no installed packs the button should not render anything.
-
-```jsx
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[]}
- />
-
-```
-
-#### Installed Pack Tooltip
-
-When a pack is installed there should be a tooltip saying as such.
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- title: 'Abe',
- cover: abeSticker,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...abeSticker, id })),
- },
- {
- id: 'bar',
- cover: sticker1,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'baz',
- cover: sticker2,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'qux',
- cover: sticker3,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[]}
- />
-
-;
-```
-
-#### Installed Pack Tooltip (Wide Sticker)
-
-When a pack is installed there should be a tooltip saying as such and the sticker should appear in its original aspect ratio.
-
-```jsx
-const landscapeGreenSticker = {
- id: 4,
- url: util.landscapeGreenObjectUrl,
- packId: 'green',
-};
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- title: 'Green',
- cover: landscapeGreenSticker,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...landscapeGreenSticker, id })),
- },
- {
- id: 'bar',
- cover: sticker1,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'baz',
- cover: sticker2,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'qux',
- cover: sticker3,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[]}
- />
-
-;
-```
-
-#### Installed Pack Tooltip (Tall Sticker)
-
-When a pack is installed there should be a tooltip saying as such and the sticker should appear in its original aspect ratio.
-
-```jsx
-const portraitTealSticker = {
- id: 4,
- url: util.portraitTealObjectUrl,
- packId: 'teal',
-};
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- title: 'Teal',
- cover: portraitTealSticker,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...portraitTealSticker, id })),
- },
- {
- id: 'bar',
- cover: sticker1,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'baz',
- cover: sticker2,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'qux',
- cover: sticker3,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[]}
- />
-
-;
-```
-
-#### New Installation Splash Tooltip
-
-When the application is updated or freshly installed there should be a tooltip
-showing the user the sticker button.
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- title: 'Abe',
- cover: abeSticker,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...abeSticker, id })),
- },
- {
- id: 'bar',
- cover: sticker1,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'baz',
- cover: sticker2,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'qux',
- cover: sticker3,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-
-
-
- console.log('onPickSticker', { packId, stickerId })
- }
- clearInstalledStickerPack={() => console.log('clearInstalledStickerPack')}
- onClickAddPack={() => console.log('onClickAddPack')}
- recentStickers={[]}
- showIntroduction
- clearShowIntroduction={() => console.log('clearShowIntroduction')}
- />
-
-;
-```
diff --git a/ts/components/stickers/StickerButton.stories.tsx b/ts/components/stickers/StickerButton.stories.tsx
new file mode 100644
index 0000000000..81bba8ab2c
--- /dev/null
+++ b/ts/components/stickers/StickerButton.stories.tsx
@@ -0,0 +1,153 @@
+import * as React from 'react';
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { boolean } from '@storybook/addon-knobs';
+
+// @ts-ignore
+import { setup as setupI18n } from '../../../js/modules/i18n';
+
+// @ts-ignore
+import enMessages from '../../../_locales/en/messages.json';
+
+import { Props, StickerButton } from './StickerButton';
+import {
+ createPack,
+ sticker1,
+ sticker2,
+ tallSticker,
+ wideSticker,
+} from './StickerPicker.stories';
+
+const i18n = setupI18n('en', enMessages);
+
+const story = storiesOf('Components/Stickers/StickerButton', module);
+
+story.addDecorator(storyFn => (
+
+ {storyFn()}
+
+));
+
+const receivedPacks = [
+ createPack({ id: 'received-pack-1', status: 'downloaded' }, sticker1),
+ createPack({ id: 'received-pack-2', status: 'downloaded' }, sticker2),
+];
+
+const installedPacks = [
+ createPack({ id: 'installed-pack-1', status: 'installed' }, sticker1),
+ createPack({ id: 'installed-pack-2', status: 'installed' }, sticker2),
+];
+
+const blessedPacks = [
+ createPack(
+ { id: 'blessed-pack-1', status: 'downloaded', isBlessed: true },
+ sticker1
+ ),
+ createPack(
+ { id: 'blessed-pack-2', status: 'downloaded', isBlessed: true },
+ sticker2
+ ),
+];
+
+const knownPacks = [
+ createPack({ id: 'known-pack-1', status: 'known' }, sticker1),
+ createPack({ id: 'known-pack-2', status: 'known' }, sticker2),
+];
+
+const createProps = (overrideProps: Partial = {}): Props => ({
+ blessedPacks: overrideProps.blessedPacks || [],
+ clearInstalledStickerPack: action('clearInstalledStickerPack'),
+ clearShowIntroduction: action('clearShowIntroduction'),
+ clearShowPickerHint: action('clearShowPickerHint'),
+ i18n,
+ installedPack: overrideProps.installedPack,
+ installedPacks: overrideProps.installedPacks || [],
+ knownPacks: overrideProps.knownPacks || [],
+ onClickAddPack: action('onClickAddPack'),
+ onPickSticker: action('onPickSticker'),
+ receivedPacks: overrideProps.receivedPacks || [],
+ recentStickers: [],
+ showIntroduction: boolean(
+ 'showIntroduction',
+ overrideProps.showIntroduction || false
+ ),
+ showPickerHint: boolean('showPickerHint', false),
+});
+
+story.add('Only Installed', () => {
+ const props = createProps({ installedPacks });
+
+ return ;
+});
+
+story.add('Only Received', () => {
+ const props = createProps({ receivedPacks });
+
+ return ;
+});
+
+story.add('Only Known', () => {
+ const props = createProps({ knownPacks });
+
+ return ;
+});
+
+story.add('Only Blessed', () => {
+ const props = createProps({ blessedPacks });
+
+ return ;
+});
+
+story.add('No Packs', () => {
+ const props = createProps();
+
+ return ;
+});
+
+story.add('Installed Pack Tooltip', () => {
+ const props = createProps({
+ installedPacks,
+ installedPack: installedPacks[0],
+ });
+
+ return ;
+});
+
+story.add('Installed Pack Tooltip (Wide)', () => {
+ const installedPack = createPack({ id: 'installed-pack-wide' }, wideSticker);
+
+ const props = createProps({
+ installedPacks: [installedPack],
+ installedPack,
+ });
+
+ return ;
+});
+
+story.add('Installed Pack Tooltip (Tall)', () => {
+ const installedPack = createPack({ id: 'installed-pack-tall' }, tallSticker);
+
+ const props = createProps({
+ installedPacks: [installedPack],
+ installedPack,
+ });
+
+ return ;
+});
+
+story.add('New Install Tooltip', () => {
+ const props = createProps({
+ installedPacks,
+ showIntroduction: true,
+ });
+
+ return ;
+});
diff --git a/ts/components/stickers/StickerManager.md b/ts/components/stickers/StickerManager.md
deleted file mode 100644
index 2d23edc04c..0000000000
--- a/ts/components/stickers/StickerManager.md
+++ /dev/null
@@ -1,260 +0,0 @@
-#### Default
-
-```jsx
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-const wideSticker = {
- id: 4,
- url: util.landscapeGreenObjectUrl,
- packId: 'wide',
-};
-const tallSticker = { id: 4, url: util.portraitTealObjectUrl, packId: 'tall' };
-
-const packs = [
- {
- id: 'foo',
- cover: sticker1,
- title: 'Foo',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'bar',
- cover: sticker2,
- title: 'Baz',
- author: 'Foo McBarrington (Official)',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'baz',
- cover: sticker3,
- title: 'Third',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
- {
- id: 'wide',
- cover: wideSticker,
- title: 'Wide',
- author: 'Wide',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...wideSticker, id })),
- },
- {
- id: 'tall',
- cover: tallSticker,
- title: 'Tall',
- author: 'Tall',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...tallSticker, id })),
- },
-];
-
-const receivedPacks = packs.map(p => ({ ...p, status: 'downloaded' }));
-const installedPacks = packs.map(p => ({ ...p, status: 'installed' }));
-const blessedPacks = packs.map(p => ({
- ...p,
- status: 'downloaded',
- isBlessed: true,
-}));
-
-
- console.log('installStickerPack', id)}
- uninstallStickerPack={id => console.log('uninstallStickerPack', id)}
- />
-;
-```
-
-#### Only installed packs
-
-```jsx
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- cover: sticker1,
- title: 'Foo',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'bar',
- cover: sticker2,
- title: 'Baz',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'baz',
- cover: sticker3,
- title: 'Baz',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-const installedPacks = packs.map(p => ({ ...p, status: 'installed' }));
-const noPacks = [];
-
-
- console.log('installStickerPack', id)}
- uninstallStickerPack={id => console.log('uninstallStickerPack', id)}
- />
-;
-```
-
-#### Only received packs
-
-```jsx
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- cover: sticker1,
- title: 'Foo',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'bar',
- cover: sticker2,
- title: 'Baz',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'baz',
- cover: sticker3,
- title: 'Baz',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-const receivedPacks = packs.map(p => ({ ...p, status: 'installed' }));
-const noPacks = [];
-
-
- console.log('installStickerPack', id)}
- />
-;
-```
-
-#### Just installed and 'known'
-
-```jsx
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const installedPacks = [
- {
- id: 'foo',
- cover: sticker1,
- title: 'Foo',
- status: 'installed',
- author: 'Foo McBarrington',
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
-];
-
-const knownPacks = [
- {
- id: 'foo',
- key: 'key1',
- stickers: [],
- state: 'known',
- },
- {
- id: 'bar',
- key: 'key2',
- stickers: [],
- state: 'known',
- },
- {
- id: 'baz',
- key: 'key3',
- stickers: [],
- state: 'known',
- },
-];
-
-const noPacks = [];
-
-
- console.log('installStickerPack', id)}
- downloadStickerPack={(packId, packKey, options) =>
- console.log('downloadStickerPack', { packId, packKey, options })
- }
- />
-;
-```
-
-#### No packs at All
-
-```jsx
-const noPacks = [];
-
-
-
- console.log('installStickerPack', id)}
- uninstallStickerPack={id => console.log('uninstallStickerPack', id)}
- />
-
-;
-```
diff --git a/ts/components/stickers/StickerManager.stories.tsx b/ts/components/stickers/StickerManager.stories.tsx
new file mode 100644
index 0000000000..69d3e8b055
--- /dev/null
+++ b/ts/components/stickers/StickerManager.stories.tsx
@@ -0,0 +1,83 @@
+import * as React from 'react';
+import { storiesOf } from '@storybook/react';
+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 { Props, StickerManager } from './StickerManager';
+import { createPack, sticker1, sticker2 } from './StickerPicker.stories';
+
+const i18n = setupI18n('en', enMessages);
+
+const story = storiesOf('Components/Stickers/StickerManager', module);
+
+const receivedPacks = [
+ createPack({ id: 'received-pack-1', status: 'downloaded' }, sticker1),
+ createPack({ id: 'received-pack-2', status: 'downloaded' }, sticker2),
+];
+
+const installedPacks = [
+ createPack({ id: 'installed-pack-1', status: 'installed' }, sticker1),
+ createPack({ id: 'installed-pack-2', status: 'installed' }, sticker2),
+];
+
+const blessedPacks = [
+ createPack(
+ { id: 'blessed-pack-1', status: 'downloaded', isBlessed: true },
+ sticker1
+ ),
+ createPack(
+ { id: 'blessed-pack-2', status: 'downloaded', isBlessed: true },
+ sticker2
+ ),
+];
+
+const knownPacks = [
+ createPack({ id: 'known-pack-1', status: 'known' }, sticker1),
+ createPack({ id: 'known-pack-2', status: 'known' }, sticker2),
+];
+
+const createProps = (overrideProps: Partial = {}): Props => ({
+ blessedPacks: overrideProps.blessedPacks || [],
+ downloadStickerPack: action('downloadStickerPack'),
+ i18n,
+ installStickerPack: action('installStickerPack'),
+ installedPacks: overrideProps.installedPacks || [],
+ knownPacks: overrideProps.knownPacks || [],
+ receivedPacks: overrideProps.receivedPacks || [],
+ uninstallStickerPack: action('uninstallStickerPack'),
+});
+
+story.add('Full', () => {
+ const props = createProps({ installedPacks, receivedPacks, blessedPacks });
+
+ return ;
+});
+
+story.add('Installed Packs', () => {
+ const props = createProps({ installedPacks });
+
+ return ;
+});
+
+story.add('Received Packs', () => {
+ const props = createProps({ receivedPacks });
+
+ return ;
+});
+
+story.add('Installed + Known Packs', () => {
+ const props = createProps({ installedPacks, knownPacks });
+
+ return ;
+});
+
+story.add('Empty', () => {
+ const props = createProps();
+
+ return ;
+});
diff --git a/ts/components/stickers/StickerPicker.md b/ts/components/stickers/StickerPicker.md
deleted file mode 100644
index 36ee775251..0000000000
--- a/ts/components/stickers/StickerPicker.md
+++ /dev/null
@@ -1,351 +0,0 @@
-#### Default
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-const wideSticker = {
- id: 4,
- url: util.landscapeGreenObjectUrl,
- packId: 'wide',
-};
-const tallSticker = { id: 4, url: util.portraitTealObjectUrl, packId: 'tall' };
-
-const packs = [
- {
- id: 'tall',
- cover: tallSticker,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...tallSticker, id })),
- },
- {
- id: 'wide',
- cover: wideSticker,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...wideSticker, id })),
- },
- {
- id: 'foo',
- cover: sticker1,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'bar',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'baz',
- cover: sticker3,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
- {
- id: 'qux',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'quux',
- cover: sticker3,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'corge',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'grault',
- cover: sticker1,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'garply',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'waldo',
- cover: sticker3,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
- {
- id: 'fred',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'plugh',
- cover: sticker1,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'xyzzy',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'thud',
- cover: abeSticker,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...abeSticker, id })),
- },
- {
- id: 'banana',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'apple',
- cover: sticker1,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'strawberry',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'tombrady',
- cover: abeSticker,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...abeSticker, id })),
- },
-];
-
-
- console.log('onClose')}
- onClickAddPack={() => console.log('onClickAddPack')}
- onPickSticker={(packId, stickerId) =>
- console.log('onPickSticker', { packId, stickerId })
- }
- />
-;
-```
-
-#### No Recently Used Stickers
-
-The sticker picker defaults to the first pack when there are no recent stickers.
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const sticker1 = { id: 1, url: util.kitten164ObjectUrl, packId: 'foo' };
-const sticker2 = { id: 2, url: util.kitten264ObjectUrl, packId: 'bar' };
-const sticker3 = { id: 3, url: util.kitten364ObjectUrl, packId: 'baz' };
-
-const packs = [
- {
- id: 'foo',
- cover: sticker1,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker1, id })),
- },
- {
- id: 'bar',
- cover: sticker2,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker2, id })),
- },
- {
- id: 'baz',
- cover: sticker3,
- stickerCount: 101,
- stickers: Array(101)
- .fill(0)
- .map((n, id) => ({ ...sticker3, id })),
- },
-];
-
-
- console.log('onClose')}
- onClickAddPack={() => console.log('onClickAddPack')}
- onPickSticker={(packId, stickerId) =>
- console.log('onPickSticker', { packId, stickerId })
- }
- />
-;
-```
-
-#### Empty
-
-```jsx
-
- console.log('onClose')}
- onClickAddPack={() => console.log('onClickAddPack')}
- onPickSticker={(packId, stickerId) =>
- console.log('onPickSticker', { packId, stickerId })
- }
- />
-
-```
-
-#### Pending Download
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const packs = [
- {
- id: 'tombrady',
- status: 'pending',
- cover: abeSticker,
- stickerCount: 30,
- stickers: [abeSticker],
- },
-];
-
-
- console.log('onClose')}
- onClickAddPack={() => console.log('onClickAddPack')}
- onPickSticker={(packId, stickerId) =>
- console.log('onPickSticker', { packId, stickerId })
- }
- />
-;
-```
-
-#### Picker Hint
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const packs = [
- {
- id: 'tombrady',
- cover: abeSticker,
- stickerCount: 100,
- stickers: Array(100)
- .fill(0)
- .map((_el, i) => ({ ...abeSticker, id: i })),
- },
-];
-
-
- console.log('onClose')}
- onClickAddPack={() => console.log('onClickAddPack')}
- onPickSticker={(packId, stickerId) =>
- console.log('onPickSticker', { packId, stickerId })
- }
- showPickerHint={true}
- />
-;
-```
-
-#### Pack With Error
-
-```jsx
-const abeSticker = { id: 4, url: util.squareStickerObjectUrl, packId: 'abe' };
-const packs = [
- {
- id: 'tombrady',
- status: 'error',
- cover: abeSticker,
- stickerCount: 3,
- stickers: [],
- },
- {
- id: 'foo',
- status: 'error',
- cover: abeSticker,
- stickerCount: 3,
- stickers: [abeSticker],
- },
-];
-
-
- console.log('onClose')}
- onClickAddPack={() => console.log('onClickAddPack')}
- onPickSticker={(packId, stickerId) =>
- console.log('onPickSticker', { packId, stickerId })
- }
- />
-;
-```
diff --git a/ts/components/stickers/StickerPicker.stories.tsx b/ts/components/stickers/StickerPicker.stories.tsx
new file mode 100644
index 0000000000..032e489cb6
--- /dev/null
+++ b/ts/components/stickers/StickerPicker.stories.tsx
@@ -0,0 +1,167 @@
+import * as React from 'react';
+import { sample } from 'lodash';
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { boolean } from '@storybook/addon-knobs';
+
+// @ts-ignore
+import { setup as setupI18n } from '../../../js/modules/i18n';
+
+// @ts-ignore
+import enMessages from '../../../_locales/en/messages.json';
+
+import { Props, StickerPicker } from './StickerPicker';
+import { StickerPackType, StickerType } from '../../state/ducks/stickers';
+
+const i18n = setupI18n('en', enMessages);
+
+const story = storiesOf('Components/Stickers/StickerPicker', module);
+
+export const sticker1: StickerType = {
+ id: 1,
+ url: '/fixtures/kitten-1-64-64.jpg',
+ packId: 'foo',
+ emoji: '',
+};
+
+export const sticker2: StickerType = {
+ id: 2,
+ url: '/fixtures/kitten-2-64-64.jpg',
+ packId: 'bar',
+ emoji: '',
+};
+
+export const sticker3: StickerType = {
+ id: 3,
+ url: '/fixtures/kitten-3-64-64.jpg',
+ packId: 'baz',
+ emoji: '',
+};
+
+export const abeSticker: StickerType = {
+ id: 4,
+ url: '/fixtures/512x515-thumbs-up-lincoln.webp',
+ packId: 'abe',
+ emoji: '',
+};
+
+export const wideSticker: StickerType = {
+ id: 5,
+ url: '/fixtures/1000x50-green.jpeg',
+ packId: 'wide',
+ emoji: '',
+};
+
+export const tallSticker: StickerType = {
+ id: 6,
+ url: '/fixtures/50x1000-teal.jpeg',
+ packId: 'tall',
+ emoji: '',
+};
+
+const choosableStickers = [sticker1, sticker2, sticker3, abeSticker];
+
+export const createPack = (
+ props: Partial,
+ sticker?: StickerType
+): StickerPackType => ({
+ id: '',
+ title: props.id ? `${props.id} title` : 'title',
+ key: '',
+ author: '',
+ isBlessed: false,
+ lastUsed: 0,
+ status: 'known',
+ cover: sticker,
+ stickerCount: 101,
+ stickers: sticker
+ ? Array(101)
+ .fill(0)
+ .map((_, id) => ({ ...sticker, id }))
+ : [],
+ ...props,
+});
+
+const packs = [
+ createPack({ id: 'tall' }, tallSticker),
+ createPack({ id: 'wide' }, wideSticker),
+ ...Array(20)
+ .fill(0)
+ .map((_, n) =>
+ createPack({ id: `pack-${n}` }, sample(choosableStickers) as StickerType)
+ ),
+];
+
+const recentStickers = [
+ abeSticker,
+ sticker1,
+ sticker2,
+ sticker3,
+ tallSticker,
+ wideSticker,
+ { ...sticker2, id: 9999 },
+];
+
+const createProps = (overrideProps: Partial = {}): Props => ({
+ i18n,
+ onClickAddPack: action('onClickAddPack'),
+ onClose: action('onClose'),
+ onPickSticker: action('onPickSticker'),
+ packs: overrideProps.packs || [],
+ recentStickers: overrideProps.recentStickers || [],
+ showPickerHint: boolean(
+ 'showPickerHint',
+ overrideProps.showPickerHint || false
+ ),
+});
+
+story.add('Full', () => {
+ const props = createProps({ packs, recentStickers });
+
+ return ;
+});
+
+story.add('Picker Hint', () => {
+ const props = createProps({ packs, recentStickers, showPickerHint: true });
+
+ return ;
+});
+
+story.add('No Recent Stickers', () => {
+ const props = createProps({ packs });
+
+ return ;
+});
+
+story.add('Empty', () => {
+ const props = createProps();
+
+ return ;
+});
+
+story.add('Pending Download', () => {
+ const pack = createPack(
+ { status: 'pending', stickers: [abeSticker] },
+ abeSticker
+ );
+ const props = createProps({ packs: [pack] });
+
+ return ;
+});
+
+story.add('Error', () => {
+ const pack = createPack(
+ { status: 'error', stickers: [abeSticker] },
+ abeSticker
+ );
+ const props = createProps({ packs: [pack] });
+
+ return ;
+});
+
+story.add('No Cover', () => {
+ const pack = createPack({ status: 'error', stickers: [abeSticker] });
+ const props = createProps({ packs: [pack] });
+
+ return ;
+});
diff --git a/ts/state/ducks/stickers.ts b/ts/state/ducks/stickers.ts
index 472138d3ff..f931dfcdc2 100644
--- a/ts/state/ducks/stickers.ts
+++ b/ts/state/ducks/stickers.ts
@@ -27,6 +27,17 @@ export type StickerDBType = {
readonly path: string;
};
+export const StickerPackStatuses = [
+ 'known',
+ 'ephemeral',
+ 'downloaded',
+ 'installed',
+ 'pending',
+ 'error',
+] as const;
+
+export type StickerPackStatus = typeof StickerPackStatuses[number];
+
export type StickerPackDBType = {
readonly id: string;
readonly key: string;
@@ -38,13 +49,7 @@ export type StickerPackDBType = {
readonly downloadAttempts: number;
readonly installedAt: number | null;
readonly lastUsed: number;
- readonly status:
- | 'known'
- | 'ephemeral'
- | 'downloaded'
- | 'installed'
- | 'pending'
- | 'error';
+ readonly status: StickerPackStatus;
readonly stickerCount: number;
readonly stickers: Dictionary;
readonly title: string;
@@ -80,13 +85,7 @@ export type StickerPackType = {
readonly cover?: StickerType;
readonly lastUsed: number;
readonly attemptedStatus?: 'downloaded' | 'installed' | 'ephemeral';
- readonly status:
- | 'known'
- | 'ephemeral'
- | 'downloaded'
- | 'installed'
- | 'pending'
- | 'error';
+ readonly status: StickerPackStatus;
readonly stickers: Array;
readonly stickerCount: number;
};