gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: some storybook exmaples


From: gnunet
Subject: [taler-wallet-core] branch master updated: some storybook exmaples
Date: Fri, 22 Oct 2021 06:31:57 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 2ec2161a some storybook exmaples
2ec2161a is described below

commit 2ec2161a7e1c0787b5e9ea14311f19c6b6a52d63
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Oct 22 01:31:46 2021 -0300

    some storybook exmaples
---
 packages/anastasis-core/src/reducer-types.ts       |    6 +-
 packages/anastasis-webui/.gitignore                |    1 +
 packages/anastasis-webui/.storybook/.babelrc       |   25 +
 packages/anastasis-webui/.storybook/main.js        |   57 +
 packages/anastasis-webui/.storybook/preview.js     |   49 +
 packages/anastasis-webui/package.json              |   10 +-
 .../src/components/menu/SideBar.tsx                |  164 ++-
 packages/anastasis-webui/src/context/anastasis.ts  |   41 +
 .../pages/home/AttributeEntryScreen.stories.tsx    |   63 +
 .../src/pages/home/AttributeEntryScreen.tsx        |   25 +-
 .../home/AuthenticationEditorScreen.stories.tsx    |   35 +
 .../src/pages/home/AuthenticationEditorScreen.tsx  |   19 +-
 .../pages/home/BackupFinishedScreen.stories.tsx    |   60 +
 .../src/pages/home/BackupFinishedScreen.tsx        |   26 +-
 .../pages/home/ChallengeOverviewScreen.stories.tsx |   83 ++
 .../src/pages/home/ChallengeOverviewScreen.tsx     |   39 +-
 .../home/ContinentSelectionScreen.stories.tsx      |   36 +
 .../src/pages/home/ContinentSelectionScreen.tsx    |   17 +-
 .../pages/home/CountrySelectionScreen.stories.tsx  |   36 +
 .../src/pages/home/CountrySelectionScreen.tsx      |   20 +-
 .../pages/home/PoliciesPayingScreen.stories.tsx    |   47 +
 .../src/pages/home/PoliciesPayingScreen.tsx        |   18 +-
 .../pages/home/RecoveryFinishedScreen.stories.tsx  |   42 +
 .../src/pages/home/RecoveryFinishedScreen.tsx      |   24 +-
 .../pages/home/ReviewPoliciesScreen.stories.tsx    |   81 ++
 .../src/pages/home/ReviewPoliciesScreen.tsx        |   42 +-
 .../src/pages/home/SecretEditorScreen.stories.tsx  |   44 +
 .../src/pages/home/SecretEditorScreen.tsx          |   25 +-
 .../pages/home/SecretSelectionScreen.stories.tsx   |   50 +
 .../src/pages/home/SecretSelectionScreen.tsx       |   37 +-
 .../src/pages/home/SolveEmailEntry.tsx             |   13 +-
 .../src/pages/home/SolvePostEntry.tsx              |   11 +-
 .../src/pages/home/SolveQuestionEntry.tsx          |   11 +-
 .../src/pages/home/SolveScreen.stories.tsx         |  121 ++
 .../anastasis-webui/src/pages/home/SolveScreen.tsx |   32 +-
 .../src/pages/home/SolveSmsEntry.tsx               |   13 +-
 .../src/pages/home/StartScreen.stories.tsx         |   35 +
 .../anastasis-webui/src/pages/home/StartScreen.tsx |   32 +-
 .../src/pages/home/TruthsPayingScreen.stories.tsx  |   40 +
 .../src/pages/home/TruthsPayingScreen.tsx          |   16 +-
 packages/anastasis-webui/src/pages/home/index.tsx  |  162 ++-
 packages/anastasis-webui/src/utils/index.tsx       |  161 +++
 pnpm-lock.yaml                                     | 1233 +++++++++++++++++++-
 43 files changed, 2772 insertions(+), 330 deletions(-)

diff --git a/packages/anastasis-core/src/reducer-types.ts 
b/packages/anastasis-core/src/reducer-types.ts
index f7ba9e0f..1a443bf9 100644
--- a/packages/anastasis-core/src/reducer-types.ts
+++ b/packages/anastasis-core/src/reducer-types.ts
@@ -23,7 +23,7 @@ export interface Policy {
     authentication_method: number;
     provider: string;
   }[];
-}
+} 
 
 export interface PolicyProvider {
   provider_url: string;
@@ -51,7 +51,7 @@ export interface ReducerStateBackup {
   identity_attributes?: { [n: string]: string };
   authentication_providers?: { [url: string]: AuthenticationProviderStatus };
   authentication_methods?: AuthMethod[];
-  required_attributes?: any;
+  required_attributes?: UserAttributeSpec[];
   selected_continent?: string;
   selected_country?: string;
   secret_name?: string;
@@ -133,7 +133,7 @@ export interface ReducerStateRecovery {
   selected_country?: string;
   currencies?: string[];
 
-  required_attributes?: any;
+  required_attributes?: UserAttributeSpec[];
 
   /**
    * Recovery information, used by the UI.
diff --git a/packages/anastasis-webui/.gitignore 
b/packages/anastasis-webui/.gitignore
index 5baa9def..32d0a505 100644
--- a/packages/anastasis-webui/.gitignore
+++ b/packages/anastasis-webui/.gitignore
@@ -2,3 +2,4 @@ node_modules
 /build
 /*.log
 /size-plugin.json
+/storybook-static/
diff --git a/packages/anastasis-webui/.storybook/.babelrc 
b/packages/anastasis-webui/.storybook/.babelrc
new file mode 100644
index 00000000..610b6f33
--- /dev/null
+++ b/packages/anastasis-webui/.storybook/.babelrc
@@ -0,0 +1,25 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+ /**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+{
+    "presets": [
+        "preact-cli/babel"
+    ]
+}
\ No newline at end of file
diff --git a/packages/anastasis-webui/.storybook/main.js 
b/packages/anastasis-webui/.storybook/main.js
new file mode 100644
index 00000000..f8e4bbcc
--- /dev/null
+++ b/packages/anastasis-webui/.storybook/main.js
@@ -0,0 +1,57 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+
+module.exports = {
+  "stories": [
+    "../src/**/*.stories.mdx",
+    "../src/**/*.stories.@(js|jsx|ts|tsx)"
+  ],
+  "addons": [
+    "@storybook/preset-scss",
+    "@storybook/addon-a11y",
+    "@storybook/addon-essentials" //docs, control, actions, viewpot, toolbar, 
background
+  ],
+  // sb does not yet support new jsx transform by default
+  // https://github.com/storybookjs/storybook/issues/12881
+  // https://github.com/storybookjs/storybook/issues/12952
+  babel: async (options) => ({
+    ...options,
+    presets: [
+      ...options.presets,
+      [
+        '@babel/preset-react', {
+          runtime: 'automatic',
+        },
+        'preset-react-jsx-transform' 
+      ],
+    ],
+  }),
+  webpackFinal: (config) => {
+    // should be removed after storybook 6.3
+    // 
https://github.com/storybookjs/storybook/issues/12853#issuecomment-821576113
+    config.resolve.alias = {
+      react: "preact/compat",
+      "react-dom": "preact/compat",
+    };
+    return config;
+  },
+}
\ No newline at end of file
diff --git a/packages/anastasis-webui/.storybook/preview.js 
b/packages/anastasis-webui/.storybook/preview.js
new file mode 100644
index 00000000..7cb9405b
--- /dev/null
+++ b/packages/anastasis-webui/.storybook/preview.js
@@ -0,0 +1,49 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import "../src/scss/main.scss"
+import { TranslationProvider } from '../src/context/translation'
+import { h } from 'preact';
+
+
+export const parameters = {
+  controls: { expanded: true },
+}
+
+export const globalTypes = {
+  locale: {
+    name: 'Locale',
+    description: 'Internationalization locale',
+    defaultValue: 'en',
+    toolbar: {
+      icon: 'globe',
+      items: [
+        { value: 'en', right: 'πŸ‡ΊπŸ‡Έ', title: 'English' },
+        { value: 'es', right: 'πŸ‡ͺπŸ‡Έ', title: 'Spanish' },
+      ],
+    },
+  },
+};
+
+export const decorators = [
+  (Story, { globals }) => {
+    document.body.parentElement.classList = "has-aside-left 
has-aside-mobile-transition has-navbar-fixed-top has-aside-expanded"
+    return <Story />
+  },
+  (Story, { globals }) => <TranslationProvider initial='en' 
forceLang={globals.locale}>
+    <Story />
+  </TranslationProvider>,
+];
diff --git a/packages/anastasis-webui/package.json 
b/packages/anastasis-webui/package.json
index 8f771131..57cfdd8d 100644
--- a/packages/anastasis-webui/package.json
+++ b/packages/anastasis-webui/package.json
@@ -8,7 +8,9 @@
     "serve": "sirv build --port 8080 --cors --single",
     "dev": "preact watch",
     "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
-    "test": "jest ./tests"
+    "test": "jest ./tests",
+    "build-storybook": "build-storybook",
+    "storybook": "start-storybook -p 6006"
   },
   "eslintConfig": {
     "parser": "@typescript-eslint/parser",
@@ -30,6 +32,12 @@
   },
   "devDependencies": {
     "@creativebulma/bulma-tooltip": "^1.2.0",
+    "@storybook/addon-a11y": "^6.2.9",
+    "@storybook/addon-actions": "^6.2.9",
+    "@storybook/addon-essentials": "^6.2.9",
+    "@storybook/addon-links": "^6.2.9",
+    "@storybook/preact": "^6.2.9",
+    "@storybook/preset-scss": "^1.0.3",
     "@types/enzyme": "^3.10.5",
     "@types/jest": "^26.0.8",
     "@typescript-eslint/eslint-plugin": "^2.25.0",
diff --git a/packages/anastasis-webui/src/components/menu/SideBar.tsx 
b/packages/anastasis-webui/src/components/menu/SideBar.tsx
index 628adb57..df582a5d 100644
--- a/packages/anastasis-webui/src/components/menu/SideBar.tsx
+++ b/packages/anastasis-webui/src/components/menu/SideBar.tsx
@@ -20,7 +20,9 @@
 */
 
 
-import { h, VNode } from 'preact';
+import { Fragment, h, VNode } from 'preact';
+import { BackupStates, RecoveryStates } from '../../../../anastasis-core/lib';
+import { useAnastasisContext } from '../../context/anastasis';
 import { Translate } from '../../i18n';
 import { LangSelector } from './LangSelector';
 
@@ -31,8 +33,9 @@ interface Props {
 export function Sidebar({ mobile }: Props): VNode {
   // const config = useConfigContext();
   const config = { version: 'none' }
-  const process = { env : { __VERSION__: '0.0.0'}}
-  
+  const process = { env: { __VERSION__: '0.0.0' } }
+  const reducer = useAnastasisContext()!
+
   return (
     <aside class="aside is-placed-left is-expanded">
       {mobile && <div class="footer" onClick={(e) => { return 
e.stopImmediatePropagation() }}>
@@ -47,52 +50,117 @@ export function Sidebar({ mobile }: Props): VNode {
         </div>
       </div>
       <div class="menu is-menu-main">
-        <p class="menu-label">
-          <Translate>Back up a secret</Translate>
-        </p>
+        {!reducer.currentReducerState &&
+          <p class="menu-label">
+            <Translate>Backup or Recorver</Translate>
+          </p>
+        }
         <ul class="menu-list">
-          <li>
-            <div class="has-icon">
-              <span class="icon"><i class="mdi mdi-square-edit-outline" 
/></span>
-              <span class="menu-item-label"><Translate>Location &amp; 
Currency</Translate></span>
-            </div>
-          </li>
-          <li class="is-active">
-            <div class="has-icon">
-              <span class="icon"><i class="mdi mdi-cash-register" /></span>
-              <span class="menu-item-label"><Translate>Personal 
information</Translate></span>
-            </div>
-          </li>
-          <li>
-            <div class="has-icon">
-              <span class="icon"><i class="mdi mdi-shopping" /></span>
-              <span class="menu-item-label"><Translate>Authorization 
methods</Translate></span>
-            </div>
-          </li>
-          <li>
-            <div  class="has-icon">
-              <span class="icon"><i class="mdi mdi-bank" /></span>
-              <span class="menu-item-label"><Translate>Recovery 
policies</Translate></span>
-            </div>
-          </li>
-          <li>
-            <div  class="has-icon">
-              <span class="icon"><i class="mdi mdi-bank" /></span>
-              <span class="menu-item-label"><Translate>Enter 
secrets</Translate></span>
-            </div>
-          </li>
-          <li>
-            <div  class="has-icon">
-              <span class="icon"><i class="mdi mdi-bank" /></span>
-              <span class="menu-item-label"><Translate>Payment 
(optional)</Translate></span>
-            </div>
-          </li>
-          <li>
-            <div  class="has-icon">
-              <span class="icon"><i class="mdi mdi-cash" /></span>
-              <span class="menu-item-label">Backup completed</span>
-            </div>
-          </li>
+          {!reducer.currentReducerState &&
+            <li>
+              <div class="ml-4">
+                <span class="menu-item-label"><Translate>Start one 
options</Translate></span>
+              </div>
+            </li>
+          }
+          {reducer.currentReducerState && 
reducer.currentReducerState.backup_state ? <Fragment>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.ContinentSelecting ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span class="menu-item-label"><Translate>Continent 
selection</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.CountrySelecting ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span class="menu-item-label"><Translate>Country 
selection</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.UserAttributesCollecting ? 'is-active' : ''}>
+              <div class="ml-4">
+
+                <span class="menu-item-label"><Translate>User 
attributes</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.AuthenticationsEditing ? 'is-active' : ''}>
+              <div class="ml-4">
+
+                <span class="menu-item-label"><Translate>Auth 
methods</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.PoliciesReviewing ? 'is-active' : ''}>
+              <div class="ml-4">
+
+                <span 
class="menu-item-label"><Translate>PoliciesReviewing</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.SecretEditing ? 'is-active' : ''}>
+              <div class="ml-4">
+
+                <span 
class="menu-item-label"><Translate>SecretEditing</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.PoliciesPaying ? 'is-active' : ''}>
+              <div class="ml-4">
+
+                <span 
class="menu-item-label"><Translate>PoliciesPaying</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.BackupFinished ? 'is-active' : ''}>
+              <div class="ml-4">
+
+                <span 
class="menu-item-label"><Translate>BackupFinished</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.backup_state === 
BackupStates.TruthsPaying ? 'is-active' : ''}>
+              <div class="ml-4">
+
+                <span 
class="menu-item-label"><Translate>TruthsPaying</Translate></span>
+              </div>
+            </li>
+          </Fragment> : (reducer.currentReducerState && 
reducer.currentReducerState?.recovery_state && <Fragment>
+            <li class={reducer.currentReducerState.recovery_state === 
RecoveryStates.ContinentSelecting ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span 
class="menu-item-label"><Translate>TruthsPaying</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.recovery_state === 
RecoveryStates.CountrySelecting ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span 
class="menu-item-label"><Translate>CountrySelecting</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.recovery_state === 
RecoveryStates.UserAttributesCollecting ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span 
class="menu-item-label"><Translate>UserAttributesCollecting</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.recovery_state === 
RecoveryStates.SecretSelecting ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span 
class="menu-item-label"><Translate>SecretSelecting</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.recovery_state === 
RecoveryStates.ChallengeSelecting ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span 
class="menu-item-label"><Translate>ChallengeSelecting</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.recovery_state === 
RecoveryStates.ChallengeSolving ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span 
class="menu-item-label"><Translate>ChallengeSolving</Translate></span>
+              </div>
+            </li>
+            <li class={reducer.currentReducerState.recovery_state === 
RecoveryStates.RecoveryFinished ? 'is-active' : ''}>
+              <div class="ml-4">
+                <span 
class="menu-item-label"><Translate>RecoveryFinished</Translate></span>
+              </div>
+            </li>
+          </Fragment>)}
+          {reducer.currentReducerState &&
+            <li>
+              <div class="buttons ml-4">
+                <button class="button is-danger is-right" onClick={() => 
reducer.reset()}>Reset session</button>
+              </div>
+            </li>
+          }
+
         </ul>
       </div>
     </aside>
diff --git a/packages/anastasis-webui/src/context/anastasis.ts 
b/packages/anastasis-webui/src/context/anastasis.ts
new file mode 100644
index 00000000..e7f93ed4
--- /dev/null
+++ b/packages/anastasis-webui/src/context/anastasis.ts
@@ -0,0 +1,41 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createContext, h, VNode } from 'preact';
+import { useContext } from 'preact/hooks';
+import { AnastasisReducerApi } from '../hooks/use-anastasis-reducer';
+
+type Type = AnastasisReducerApi | undefined;
+
+const initial = undefined
+
+const Context = createContext<Type>(initial)
+
+interface Props {
+  value: AnastasisReducerApi;
+  children: any;
+}
+
+export const AnastasisProvider = ({ value, children }: Props): VNode => {
+  return h(Context.Provider, { value, children });
+}
+
+export const useAnastasisContext = (): Type => useContext(Context);
\ No newline at end of file
diff --git 
a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx
new file mode 100644
index 00000000..d28a6df4
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx
@@ -0,0 +1,63 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { AttributeEntryScreen as TestedComponent } from 
'./AttributeEntryScreen';
+
+
+export default {
+  title: 'Pages/AttributeEntryScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const WithSomeAttributes = createExample(TestedComponent, {
+  ...reducerStatesExample.attributeEditing,
+  required_attributes: [{
+    name: 'first',
+    label: 'first',
+    type: 'type',
+    uuid: 'asdasdsa1',
+    widget: 'wid',
+  }, {
+    name: 'pepe',
+    label: 'second',
+    type: 'type',
+    uuid: 'asdasdsa2',
+    widget: 'wid',
+  }, {
+    name: 'pepe2',
+    label: 'third',
+    type: 'type',
+    uuid: 'asdasdsa3',
+    widget: 'calendar',
+  }]
+} as ReducerState);
+
+export const Empty = createExample(TestedComponent, {
+  ...reducerStatesExample.attributeEditing,
+  required_attributes: undefined
+} as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx 
b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
index 6f87a335..2f804f94 100644
--- a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
@@ -1,15 +1,24 @@
 /* eslint-disable @typescript-eslint/camelcase */
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
-import { ReducerStateRecovery, ReducerStateBackup } from 
"../../../../anastasis-core/lib";
+import { ReducerStateRecovery, ReducerStateBackup, UserAttributeSpec } from 
"anastasis-core/lib";
+import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisReducerApi } from "../../hooks/use-anastasis-reducer";
 import { AnastasisClientFrame, withProcessLabel, LabeledInput } from "./index";
 
-export function AttributeEntryScreen(props: AttributeEntryProps): VNode {
-  const { reducer, reducerState: backupState } = props;
-  const [attrs, setAttrs] = useState<Record<string, string>>(
-    props.reducerState.identity_attributes ?? {}
-  );
+export function AttributeEntryScreen(): VNode {
+  const reducer = useAnastasisContext()
+  const state = reducer?.currentReducerState
+  const currentIdentityAttributes = state && "identity_attributes" in state ? 
(state.identity_attributes || {}) : {}
+  const [attrs, setAttrs] = useState<Record<string, 
string>>(currentIdentityAttributes);
+
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || !("required_attributes" in 
reducer.currentReducerState)) {
+    return <div>invalid state</div>
+  }
+  
   return (
     <AnastasisClientFrame
       title={withProcessLabel(reducer, "Select Country")}
@@ -17,7 +26,7 @@ export function AttributeEntryScreen(props: 
AttributeEntryProps): VNode {
         identity_attributes: attrs,
       })}
     >
-      {backupState.required_attributes.map((x: any, i: number) => {
+      {reducer.currentReducerState.required_attributes?.map((x, i: number) => {
         return (
           <AttributeEntryField
             key={i}
@@ -40,7 +49,7 @@ export interface AttributeEntryFieldProps {
   isFirst: boolean;
   value: string;
   setValue: (newValue: string) => void;
-  spec: any;
+  spec: UserAttributeSpec;
 }
 
 export function AttributeEntryField(props: AttributeEntryFieldProps): VNode {
diff --git 
a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
new file mode 100644
index 00000000..44d3795b
--- /dev/null
+++ 
b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
@@ -0,0 +1,35 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../utils';
+import { AuthenticationEditorScreen as TestedComponent } from 
'./AuthenticationEditorScreen';
+
+
+export default {
+  title: 'Pages/AuthenticationEditorScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const Example = createExample(TestedComponent, 
reducerStatesExample.authEditing);
diff --git 
a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx 
b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx
index fc28942a..e9ffccba 100644
--- a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx
@@ -1,7 +1,8 @@
 /* eslint-disable @typescript-eslint/camelcase */
+import { AuthMethod, ReducerStateBackup } from "anastasis-core";
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
-import { AuthMethod, ReducerStateBackup } from "anastasis-core";
+import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisReducerApi } from "../../hooks/use-anastasis-reducer";
 import { AuthMethodEmailSetup } from "./AuthMethodEmailSetup";
 import { AuthMethodPostSetup } from "./AuthMethodPostSetup";
@@ -9,12 +10,18 @@ import { AuthMethodQuestionSetup } from 
"./AuthMethodQuestionSetup";
 import { AuthMethodSmsSetup } from "./AuthMethodSmsSetup";
 import { AnastasisClientFrame } from "./index";
 
-export function AuthenticationEditorScreen(props: AuthenticationEditorProps): 
VNode {
+export function AuthenticationEditorScreen(): VNode {
   const [selectedMethod, setSelectedMethod] = useState<string | undefined>(
     undefined
   );
-  const { reducer, backupState } = props;
-  const providers = backupState.authentication_providers!;
+  const reducer = useAnastasisContext()
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || reducer.currentReducerState.backup_state 
=== undefined) {
+    return <div>invalid state</div>
+  }
+  const providers = reducer.currentReducerState.authentication_providers!;
   const authAvailableSet = new Set<string>();
   for (const provKey of Object.keys(providers)) {
     const p = providers[provKey];
@@ -52,14 +59,14 @@ export function AuthenticationEditorScreen(props: 
AuthenticationEditorProps): VN
         disabled={!authAvailableSet.has(props.method)}
         onClick={() => {
           setSelectedMethod(props.method);
-          reducer.dismissError();
+          if (reducer) reducer.dismissError();
         }}
       >
         {props.label}
       </button>
     );
   }
-  const configuredAuthMethods: AuthMethod[] = 
backupState.authentication_methods ?? [];
+  const configuredAuthMethods: AuthMethod[] = 
reducer.currentReducerState.authentication_methods ?? [];
   const haveMethodsConfigured = configuredAuthMethods.length;
   return (
     <AnastasisClientFrame title="Backup: Configure Authentication Methods">
diff --git 
a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
new file mode 100644
index 00000000..65a2b7e1
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
@@ -0,0 +1,60 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { BackupFinishedScreen as TestedComponent } from 
'./BackupFinishedScreen';
+
+
+export default {
+  title: 'Pages/BackupFinishedScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const Simple = createExample(TestedComponent, 
reducerStatesExample.backupFinished);
+
+export const WithName = createExample(TestedComponent, 
{...reducerStatesExample.backupFinished,
+  secret_name: 'super_secret',
+} as ReducerState);
+
+export const WithDetails = createExample(TestedComponent, {
+  ...reducerStatesExample.backupFinished,
+  secret_name: 'super_secret',
+  success_details: {
+    'http://anastasis.net': {
+      policy_expiration: {
+        t_ms: 'never'
+      },
+      policy_version: 0
+    },
+    'http://taler.net': {
+      policy_expiration: {
+        t_ms: new Date().getTime() + 60*60*24*1000
+      },
+      policy_version: 1
+    },
+  }
+} as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx 
b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
index 6c277094..218f1d1f 100644
--- a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
@@ -1,23 +1,33 @@
 import { h, VNode } from "preact";
-import { BackupReducerProps, AnastasisClientFrame } from "./index";
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame } from "./index";
 
-export function BackupFinishedScreen(props: BackupReducerProps): VNode {
+export function BackupFinishedScreen(): VNode {
+  const reducer = useAnastasisContext()
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || reducer.currentReducerState.backup_state 
=== undefined) {
+    return <div>invalid state</div>
+  }
+  const details = reducer.currentReducerState.success_details
   return (<AnastasisClientFrame hideNext title="Backup finished">
     <p>
-      Your backup of secret "{props.backupState.secret_name ?? "??"}" was
+      Your backup of secret "{reducer.currentReducerState.secret_name ?? 
"??"}" was
       successful.
     </p>
     <p>The backup is stored by the following providers:</p>
-    <ul>
-      {Object.keys(props.backupState.success_details!).map((x, i) => {
-        const sd = props.backupState.success_details![x];
+
+    {details && <ul>
+      {Object.keys(details).map((x, i) => {
+        const sd = details[x];
         return (
           <li key={i}>
             {x} (Policy version {sd.policy_version})
           </li>
         );
       })}
-    </ul>
-    <button onClick={() => props.reducer.reset()}>Back to start</button>
+    </ul>}
+    <button onClick={() => reducer.reset()}>Back to start</button>
   </AnastasisClientFrame>);
 }
diff --git 
a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
new file mode 100644
index 00000000..4f186c03
--- /dev/null
+++ 
b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
@@ -0,0 +1,83 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { ChallengeOverviewScreen as TestedComponent } from 
'./ChallengeOverviewScreen';
+
+
+export default {
+  title: 'Pages/ChallengeOverviewScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const OneChallenge = createExample(TestedComponent, 
{...reducerStatesExample.challengeSelecting,
+  recovery_information: {
+    policies: [[{uuid:'1'}]],
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'just go for it',
+      type: 'question',
+      uuid: '1',
+    }]
+  },
+} as ReducerState);
+
+export const MoreChallenges = createExample(TestedComponent, 
{...reducerStatesExample.challengeSelecting,
+  recovery_information: {
+    policies: [[{uuid:'1'}, {uuid:'2'}],[{uuid:'3'}]],
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'just go for it',
+      type: 'question',
+      uuid: '1',
+    },{
+      cost: 'USD:1',
+      instructions: 'just go for it',
+      type: 'question',
+      uuid: '2',
+    },{
+      cost: 'USD:1',
+      instructions: 'just go for it',
+      type: 'question',
+      uuid: '3',
+    }]
+  },
+} as ReducerState);
+
+export const OneBadConfiguredPolicy = createExample(TestedComponent, 
{...reducerStatesExample.challengeSelecting,
+  recovery_information: {
+    policies: [[{uuid:'2'}]],
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'just go for it',
+      type: 'sasd',
+      uuid: '1',
+    }]
+  },
+} as ReducerState);
+
+export const NoPolicies = createExample(TestedComponent, 
reducerStatesExample.challengeSelecting);
diff --git 
a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx 
b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
index 1f108ce6..c9b52e91 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
@@ -1,10 +1,21 @@
 import { h, VNode } from "preact";
-import { RecoveryReducerProps, AnastasisClientFrame } from "./index";
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame } from "./index";
+
+export function ChallengeOverviewScreen(): VNode {
+  const reducer = useAnastasisContext()
+
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || 
reducer.currentReducerState.recovery_state === undefined) {
+    return <div>invalid state</div>
+  }
+
+  const policies = reducer.currentReducerState.recovery_information?.policies 
?? [];
+  const chArr = reducer.currentReducerState.recovery_information?.challenges 
?? [];
+  const challengeFeedback = reducer.currentReducerState?.challenge_feedback;
 
-export function ChallengeOverviewScreen(props: RecoveryReducerProps): VNode {
-  const { recoveryState, reducer } = props;
-  const policies = recoveryState.recovery_information!.policies;
-  const chArr = recoveryState.recovery_information!.challenges;
   const challenges: {
     [uuid: string]: {
       type: string;
@@ -22,15 +33,21 @@ export function ChallengeOverviewScreen(props: 
RecoveryReducerProps): VNode {
   return (
     <AnastasisClientFrame title="Recovery: Solve challenges">
       <h2>Policies</h2>
-      {policies.map((x, i) => {
+      {!policies.length && <p>
+        No policies found
+      </p>}
+      {policies.map((row, i) => {
         return (
           <div key={i}>
             <h3>Policy #{i + 1}</h3>
-            {x.map((x, j) => {
-              const ch = challenges[x.uuid];
-              const feedback = recoveryState.challenge_feedback?.[x.uuid];
+            {row.map(column => {
+              const ch = challenges[column.uuid];
+              if (!ch) return <div>
+                There is no challenge for this policy
+              </div>
+              const feedback = challengeFeedback?.[column.uuid];
               return (
-                <div key={j}
+                <div key={column.uuid}
                   style={{
                     borderLeft: "2px solid gray",
                     paddingLeft: "0.5em",
@@ -46,7 +63,7 @@ export function ChallengeOverviewScreen(props: 
RecoveryReducerProps): VNode {
                   {feedback?.state !== "solved" ? (
                     <button
                       onClick={() => reducer.transition("select_challenge", {
-                        uuid: x.uuid,
+                        uuid: column.uuid,
                       })}
                     >
                       Solve
diff --git 
a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx
new file mode 100644
index 00000000..aad37cd7
--- /dev/null
+++ 
b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx
@@ -0,0 +1,36 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../utils';
+import { ContinentSelectionScreen as TestedComponent } from 
'./ContinentSelectionScreen';
+
+
+export default {
+  title: 'Pages/ContinentSelectionScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const Backup = createExample(TestedComponent, 
reducerStatesExample.backupSelectCountry);
+export const Recovery = createExample(TestedComponent, 
reducerStatesExample.recoverySelectCountry);
diff --git 
a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx 
b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
index 2fed23d4..ad529a4a 100644
--- a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
@@ -1,15 +1,16 @@
 import { h, VNode } from "preact";
-import { CommonReducerProps, AnastasisClientFrame, withProcessLabel } from 
"./index";
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame, withProcessLabel } from "./index";
 
-export function ContinentSelectionScreen(props: CommonReducerProps): VNode {
-  const { reducer, reducerState } = props;
+export function ContinentSelectionScreen(): VNode {
+  const reducer = useAnastasisContext()
+  if (!reducer || !reducer.currentReducerState || !("continents" in 
reducer.currentReducerState)) {
+    return <div />
+  }
   const sel = (x: string): void => reducer.transition("select_continent", { 
continent: x });
   return (
-    <AnastasisClientFrame
-      hideNext
-      title={withProcessLabel(reducer, "Select Continent")}
-    >
-      {reducerState.continents.map((x: any) => (
+    <AnastasisClientFrame hideNext title={withProcessLabel(reducer, "Select 
Continent")}>
+      {reducer.currentReducerState.continents.map((x: any) => (
         <button onClick={() => sel(x.name)} key={x.name}>
           {x.name}
         </button>
diff --git 
a/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.stories.tsx
new file mode 100644
index 00000000..adf36980
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.stories.tsx
@@ -0,0 +1,36 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../utils';
+import { CountrySelectionScreen as TestedComponent } from 
'./CountrySelectionScreen';
+
+
+export default {
+  title: 'Pages/CountrySelectionScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const Backup = createExample(TestedComponent, 
reducerStatesExample.backupSelectCountry);
+export const Recovery = createExample(TestedComponent, 
reducerStatesExample.recoverySelectCountry);
diff --git a/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx 
b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx
index dbe4b761..555622c1 100644
--- a/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx
@@ -1,19 +1,23 @@
 /* eslint-disable @typescript-eslint/camelcase */
 import { h, VNode } from "preact";
-import { CommonReducerProps, AnastasisClientFrame, withProcessLabel } from 
"./index";
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame, withProcessLabel } from "./index";
 
-export function CountrySelectionScreen(props: CommonReducerProps): VNode {
-  const { reducer, reducerState } = props;
+export function CountrySelectionScreen(): VNode {
+  const reducer = useAnastasisContext()
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || !("countries" in 
reducer.currentReducerState)) {
+    return <div>invalid state</div>
+  }
   const sel = (x: any): void => reducer.transition("select_country", {
     country_code: x.code,
     currencies: [x.currency],
   });
   return (
-    <AnastasisClientFrame
-      hideNext
-      title={withProcessLabel(reducer, "Select Country")}
-    >
-      {reducerState.countries.map((x: any) => (
+    <AnastasisClientFrame hideNext title={withProcessLabel(reducer, "Select 
Country")} >
+      {reducer.currentReducerState.countries.map((x: any) => (
         <button onClick={() => sel(x)} key={x.name}>
           {x.name} ({x.currency})
         </button>
diff --git 
a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx
new file mode 100644
index 00000000..1a9462b8
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx
@@ -0,0 +1,47 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { PoliciesPayingScreen as TestedComponent } from 
'./PoliciesPayingScreen';
+
+
+export default {
+  title: 'Pages/PoliciesPayingScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const Example = createExample(TestedComponent, 
reducerStatesExample.policyPay);
+export const WithSomePaymentRequest = createExample(TestedComponent, {
+  ...reducerStatesExample.policyPay,
+  policy_payment_requests: [{
+    payto: 'payto://x-taler-bank/bank.taler/account-a',
+    provider: 'provider1'
+  }, {
+    payto: 'payto://x-taler-bank/bank.taler/account-b',
+    provider: 'provider2'
+  }]
+} as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx 
b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx
index be74729e..8a39cf0e 100644
--- a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx
@@ -1,9 +1,17 @@
 import { h, VNode } from "preact";
-import { BackupReducerProps, AnastasisClientFrame } from "./index";
-
-export function PoliciesPayingScreen(props: BackupReducerProps): VNode {
-  const payments = props.backupState.policy_payment_requests ?? [];
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame } from "./index";
 
+export function PoliciesPayingScreen(): VNode {
+  const reducer = useAnastasisContext()
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || reducer.currentReducerState.backup_state 
=== undefined) {
+    return <div>invalid state</div>
+  }
+  const payments = reducer.currentReducerState.policy_payment_requests ?? [];
+  
   return (
     <AnastasisClientFrame hideNext title="Backup: Recovery Document Payments">
       <p>
@@ -19,7 +27,7 @@ export function PoliciesPayingScreen(props: 
BackupReducerProps): VNode {
           );
         })}
       </ul>
-      <button onClick={() => props.reducer.transition("pay", {})}>
+      <button onClick={() => reducer.transition("pay", {})}>
         Check payment status now
       </button>
     </AnastasisClientFrame>
diff --git 
a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx
new file mode 100644
index 00000000..0c184242
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx
@@ -0,0 +1,42 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { RecoveryFinishedScreen as TestedComponent } from 
'./RecoveryFinishedScreen';
+
+
+export default {
+  title: 'Pages/RecoveryFinishedScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const NormalEnding = createExample(TestedComponent, {
+  ...reducerStatesExample.recoveryFinished,
+  core_secret: { mime: 'text/plain', value: 'hello' }
+} as ReducerState);
+
+export const BadEnding = createExample(TestedComponent, 
reducerStatesExample.recoveryFinished);
diff --git a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx 
b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
index 7ccc511f..8c8a2c7c 100644
--- a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
@@ -3,13 +3,31 @@ import {
   decodeCrock
 } from "@gnu-taler/taler-util";
 import { h, VNode } from "preact";
-import { RecoveryReducerProps, AnastasisClientFrame } from "./index";
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame } from "./index";
 
-export function RecoveryFinishedScreen(props: RecoveryReducerProps): VNode {
+export function RecoveryFinishedScreen(): VNode {
+  const reducer = useAnastasisContext()
+
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || 
reducer.currentReducerState.recovery_state === undefined) {
+    return <div>invalid state</div>
+  }
+  const encodedSecret = reducer.currentReducerState.core_secret?.value
+  if (!encodedSecret) {
+    return <AnastasisClientFrame title="Recovery Problem" hideNext>
+      <p>
+        Secret not found
+      </p>
+    </AnastasisClientFrame>
+  }
+  const secret = bytesToString(decodeCrock(encodedSecret))
   return (
     <AnastasisClientFrame title="Recovery Finished" hideNext>
       <p>
-        Secret: 
{bytesToString(decodeCrock(props.recoveryState.core_secret?.value!))}
+        Secret: {secret}
       </p>
     </AnastasisClientFrame>
   );
diff --git 
a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx
new file mode 100644
index 00000000..b52699e7
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx
@@ -0,0 +1,81 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { ReviewPoliciesScreen as TestedComponent } from 
'./ReviewPoliciesScreen';
+
+
+export default {
+  title: 'Pages/ReviewPoliciesScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const HasPoliciesButMethodListIsEmpty = createExample(TestedComponent, {
+  ...reducerStatesExample.policyReview,
+  policies: [{
+    methods: [{
+      authentication_method: 0,
+      provider: 'asd'
+    },{
+      authentication_method: 1,
+      provider: 'asd'
+    }]
+  },{
+    methods: [{
+      authentication_method: 1,
+      provider: 'asd'
+    }]
+  }],
+  authentication_methods: []
+} as ReducerState);
+
+export const SomePoliciesWithMethods = createExample(TestedComponent, {
+  ...reducerStatesExample.policyReview,
+  policies: [{
+    methods: [{
+      authentication_method: 0,
+      provider: 'asd'
+    },{
+      authentication_method: 1,
+      provider: 'asd'
+    }]
+  },{
+    methods: [{
+      authentication_method: 1,
+      provider: 'asd'
+    }]
+  }],
+  authentication_methods: [{
+    challenge: 'asd',
+    instructions: 'ins',
+    type: 'type',
+  },{
+    challenge: 'asd2',
+    instructions: 'ins2',
+    type: 'type2',
+  }]
+} as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx 
b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
index 3e20538d..b360ccaf 100644
--- a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
@@ -1,35 +1,49 @@
 /* eslint-disable @typescript-eslint/camelcase */
 import { h, VNode } from "preact";
-import { BackupReducerProps, AnastasisClientFrame } from "./index";
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame } from "./index";
+
+export function ReviewPoliciesScreen(): VNode {
+  const reducer = useAnastasisContext()
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || reducer.currentReducerState.backup_state 
=== undefined) {
+    return <div>invalid state</div>
+  }
+  const authMethods = reducer.currentReducerState.authentication_methods ?? [];
+  const policies = reducer.currentReducerState.policies ?? [];
 
-export function ReviewPoliciesScreen(props: BackupReducerProps): VNode {
-  const { reducer, backupState } = props;
-  const authMethods = backupState.authentication_methods!;
   return (
     <AnastasisClientFrame title="Backup: Review Recovery Policies">
-      {backupState.policies?.map((p, i) => {
-        const policyName = p.methods
-          .map((x, i) => authMethods[x.authentication_method].type)
-          .join(" + ");
+      {policies.map((p, policy_index) => {
+        const methods = p.methods
+          .map(x => authMethods[x.authentication_method] && ({ 
...authMethods[x.authentication_method], provider: x.provider }))
+          .filter(x => !!x)
+
+        const policyName = methods.map(x => x.type).join(" + ");
+
         return (
-          <div key={i} class="policy">
+          <div key={policy_index} class="policy">
             <h3>
-              Policy #{i + 1}: {policyName}
+              Policy #{policy_index + 1}: {policyName}
             </h3>
             Required Authentications:
+            {!methods.length && <p>
+              No auth method found
+            </p>}
             <ul>
-              {p.methods.map((x, i) => {
-                const m = authMethods[x.authentication_method];
+              {methods.map((m, i) => {
                 return (
                   <li key={i}>
-                    {m.type} ({m.instructions}) at provider {x.provider}
+                    {m.type} ({m.instructions}) at provider {m.provider}
                   </li>
                 );
               })}
             </ul>
             <div>
               <button
-                onClick={() => reducer.transition("delete_policy", { 
policy_index: i })}
+                onClick={() => reducer.transition("delete_policy", { 
policy_index })}
               >
                 Delete Policy
               </button>
diff --git 
a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx
new file mode 100644
index 00000000..18560356
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx
@@ -0,0 +1,44 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { SecretEditorScreen as TestedComponent } from './SecretEditorScreen';
+
+
+export default {
+  title: 'Pages/SecretEditorScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const WithSecretNamePreselected = createExample(TestedComponent, {
+  ...reducerStatesExample.secretEdition,
+  secret_name: 'someSecretName',
+} as ReducerState);
+
+export const WithoutName = createExample(TestedComponent, {
+  ...reducerStatesExample.secretEdition,
+} as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx 
b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
index 086d4921..a5235d66 100644
--- a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
@@ -2,18 +2,29 @@
 import { encodeCrock, stringToBytes } from "@gnu-taler/taler-util";
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
+import { useAnastasisContext } from "../../context/anastasis";
 import {
-  BackupReducerProps,
   AnastasisClientFrame,
-  LabeledInput,
+  LabeledInput
 } from "./index";
 
-export function SecretEditorScreen(props: BackupReducerProps): VNode {
-  const { reducer } = props;
-  const [secretName, setSecretName] = useState(
-    props.backupState.secret_name ?? "",
-  );
+export function SecretEditorScreen(): VNode {
+  const reducer = useAnastasisContext()
   const [secretValue, setSecretValue] = useState("");
+
+  const currentSecretName = reducer?.currentReducerState 
+    && ("secret_name" in reducer.currentReducerState) 
+    && reducer.currentReducerState.secret_name;
+
+  const [secretName, setSecretName] = useState(currentSecretName || "");
+  
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || reducer.currentReducerState.backup_state 
=== undefined) {
+    return <div>invalid state</div>
+  }
+
   const secretNext = (): void => {
     reducer.runTransaction(async (tx) => {
       await tx.transition("enter_secret_name", {
diff --git 
a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx
new file mode 100644
index 00000000..e9c59702
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx
@@ -0,0 +1,50 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { SecretSelectionScreen as TestedComponent } from 
'./SecretSelectionScreen';
+
+
+export default {
+  title: 'Pages/SecretSelectionScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const Example = createExample(TestedComponent, {
+  ...reducerStatesExample.secretSelection,
+  recovery_document: {
+    provider_url: 'http://anastasis.url/',
+    secret_name: 'secretName',
+    version: 1,
+  },
+} as ReducerState);
+
+
+export const NoRecoveryDocumentFound = createExample(TestedComponent, {
+  ...reducerStatesExample.secretSelection,
+  recovery_document: undefined,
+} as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx 
b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
index 7cb7fdf2..903f5786 100644
--- a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
@@ -1,17 +1,29 @@
 /* eslint-disable @typescript-eslint/camelcase */
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
-import { RecoveryReducerProps, AnastasisClientFrame } from "./index";
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame } from "./index";
 
-export function SecretSelectionScreen(props: RecoveryReducerProps): VNode {
-  const { reducer, recoveryState } = props;
+export function SecretSelectionScreen(): VNode {
   const [selectingVersion, setSelectingVersion] = useState<boolean>(false);
-  const [otherVersion, setOtherVersion] = useState<number>(
-    recoveryState.recovery_document?.version ?? 0
-  );
-  const recoveryDocument = recoveryState.recovery_document!;
   const [otherProvider, setOtherProvider] = useState<string>("");
+  const reducer = useAnastasisContext()
+
+  const currentVersion = reducer?.currentReducerState
+    && ("recovery_document" in reducer.currentReducerState)
+    && reducer.currentReducerState.recovery_document?.version;
+
+  const [otherVersion, setOtherVersion] = useState<number>(currentVersion || 
0);
+
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || 
reducer.currentReducerState.recovery_state === undefined) {
+    return <div>invalid state</div>
+  }
+
   function selectVersion(p: string, n: number): void {
+    if (!reducer) return;
     reducer.runTransaction(async (tx) => {
       await tx.transition("change_version", {
         version: n,
@@ -20,12 +32,21 @@ export function SecretSelectionScreen(props: 
RecoveryReducerProps): VNode {
       setSelectingVersion(false);
     });
   }
+
+  const recoveryDocument = reducer.currentReducerState.recovery_document
+  if (!recoveryDocument) {
+    return (
+      <AnastasisClientFrame hideNav title="Recovery: Problem">
+        <p>No recovery document found</p>
+      </AnastasisClientFrame>
+    )
+  }
   if (selectingVersion) {
     return (
       <AnastasisClientFrame hideNav title="Recovery: Select secret">
         <p>Select a different version of the secret</p>
         <select onChange={(e) => setOtherProvider((e.target as any).value)}>
-          {Object.keys(recoveryState.authentication_providers ?? {}).map(
+          {Object.keys(reducer.currentReducerState.authentication_providers ?? 
{}).map(
             (x, i) => (
               <option key={i} selected={x === recoveryDocument.provider_url} 
value={x}>
                 {x}
diff --git a/packages/anastasis-webui/src/pages/home/SolveEmailEntry.tsx 
b/packages/anastasis-webui/src/pages/home/SolveEmailEntry.tsx
index 6296dc02..2c27895c 100644
--- a/packages/anastasis-webui/src/pages/home/SolveEmailEntry.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveEmailEntry.tsx
@@ -1,14 +1,17 @@
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
+import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame, LabeledInput } from "./index";
 import { SolveEntryProps } from "./SolveScreen";
 
-export function SolveEmailEntry(props: SolveEntryProps): VNode {
+export function SolveEmailEntry({ challenge, feedback }: SolveEntryProps): 
VNode {
   const [answer, setAnswer] = useState("");
-  const { reducer, challenge, feedback } = props;
-  const next = (): void => reducer.transition("solve_challenge", {
-    answer,
-  });
+  const reducer = useAnastasisContext()
+  const next = (): void => {
+    if (reducer) reducer.transition("solve_challenge", {
+      answer,
+    })
+  };
   return (
     <AnastasisClientFrame
       title="Recovery: Solve challenge"
diff --git a/packages/anastasis-webui/src/pages/home/SolvePostEntry.tsx 
b/packages/anastasis-webui/src/pages/home/SolvePostEntry.tsx
index b11ceed2..1a824acb 100644
--- a/packages/anastasis-webui/src/pages/home/SolvePostEntry.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolvePostEntry.tsx
@@ -1,14 +1,15 @@
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
+import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame, LabeledInput } from "./index";
 import { SolveEntryProps } from "./SolveScreen";
 
-export function SolvePostEntry(props: SolveEntryProps): VNode {
+export function SolvePostEntry({ challenge, feedback }: SolveEntryProps): 
VNode {
   const [answer, setAnswer] = useState("");
-  const { reducer, challenge, feedback } = props;
-  const next = (): void => reducer.transition("solve_challenge", {
-    answer,
-  });
+  const reducer = useAnastasisContext()
+  const next = (): void => {
+    if (reducer) reducer.transition("solve_challenge", { answer })
+  };
   return (
     <AnastasisClientFrame
       title="Recovery: Solve challenge"
diff --git a/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx 
b/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
index 6393958b..72dadbe8 100644
--- a/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
@@ -1,14 +1,15 @@
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
+import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame, LabeledInput } from "./index";
 import { SolveEntryProps } from "./SolveScreen";
 
-export function SolveQuestionEntry(props: SolveEntryProps): VNode {
+export function SolveQuestionEntry({ challenge, feedback }: SolveEntryProps): 
VNode {
   const [answer, setAnswer] = useState("");
-  const { reducer, challenge, feedback } = props;
-  const next = (): void => reducer.transition("solve_challenge", {
-    answer,
-  });
+  const reducer = useAnastasisContext()
+  const next = (): void => {
+    if (reducer) reducer.transition("solve_challenge", { answer })
+  };
   return (
     <AnastasisClientFrame
       title="Recovery: Solve challenge"
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
new file mode 100644
index 00000000..69af9be4
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
@@ -0,0 +1,121 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { SolveScreen as TestedComponent } from './SolveScreen';
+
+
+export default {
+  title: 'Pages/SolveScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const NoInformation = createExample(TestedComponent, 
reducerStatesExample.challengeSolving);
+
+export const NotSupportedChallenge = createExample(TestedComponent, {
+  ...reducerStatesExample.challengeSolving,
+  recovery_information: {
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'follow htis instructions',
+      type: 'chall-type',
+      uuid: 'ASDASDSAD!1'
+    }],
+    policies: [],
+  },
+  selected_challenge_uuid: 'ASDASDSAD!1'
+} as ReducerState);
+
+export const MismatchedChallengeId = createExample(TestedComponent, {
+  ...reducerStatesExample.challengeSolving,
+  recovery_information: {
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'follow htis instructions',
+      type: 'chall-type',
+      uuid: 'ASDASDSAD!1'
+    }],
+    policies: [],
+  },
+  selected_challenge_uuid: 'no-no-no'
+} as ReducerState);
+
+export const SmsChallenge = createExample(TestedComponent, {
+  ...reducerStatesExample.challengeSolving,
+  recovery_information: {
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'follow htis instructions',
+      type: 'sms',
+      uuid: 'ASDASDSAD!1'
+    }],
+    policies: [],
+  },
+  selected_challenge_uuid: 'ASDASDSAD!1'
+} as ReducerState);
+
+export const QuestionChallenge = createExample(TestedComponent, {
+  ...reducerStatesExample.challengeSolving,
+  recovery_information: {
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'follow htis instructions',
+      type: 'question',
+      uuid: 'ASDASDSAD!1'
+    }],
+    policies: [],
+  },
+  selected_challenge_uuid: 'ASDASDSAD!1'
+} as ReducerState);
+
+export const EmailChallenge = createExample(TestedComponent, {
+  ...reducerStatesExample.challengeSolving,
+  recovery_information: {
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'follow htis instructions',
+      type: 'email',
+      uuid: 'ASDASDSAD!1'
+    }],
+    policies: [],
+  },
+  selected_challenge_uuid: 'ASDASDSAD!1'
+} as ReducerState);
+
+export const PostChallenge = createExample(TestedComponent, {
+  ...reducerStatesExample.challengeSolving,
+  recovery_information: {
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'follow htis instructions',
+      type: 'post',
+      uuid: 'ASDASDSAD!1'
+    }],
+    policies: [],
+  },
+  selected_challenge_uuid: 'ASDASDSAD!1'
+} as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx 
b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
index 357a7c2d..05ae50b4 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
@@ -1,17 +1,31 @@
 import { h, VNode } from "preact";
-import { AnastasisReducerApi } from "../../hooks/use-anastasis-reducer";
+import { ChallengeFeedback, ChallengeInfo } from 
"../../../../anastasis-core/lib";
+import { useAnastasisContext } from "../../context/anastasis";
 import { SolveEmailEntry } from "./SolveEmailEntry";
 import { SolvePostEntry } from "./SolvePostEntry";
 import { SolveQuestionEntry } from "./SolveQuestionEntry";
 import { SolveSmsEntry } from "./SolveSmsEntry";
 import { SolveUnsupportedEntry } from "./SolveUnsupportedEntry";
-import { RecoveryReducerProps } from "./index";
-import { ChallengeInfo, ChallengeFeedback } from 
"../../../../anastasis-core/lib";
 
-export function SolveScreen(props: RecoveryReducerProps): VNode {
-  const chArr = props.recoveryState.recovery_information!.challenges;
-  const challengeFeedback = props.recoveryState.challenge_feedback ?? {};
-  const selectedUuid = props.recoveryState.selected_challenge_uuid!;
+export function SolveScreen(): VNode {
+  const reducer = useAnastasisContext()
+
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || 
reducer.currentReducerState.recovery_state === undefined) {
+    return <div>invalid state</div>
+  }
+
+  if (!reducer.currentReducerState.recovery_information) {
+    return <div>no recovery information found</div>
+  }
+  if (!reducer.currentReducerState.selected_challenge_uuid) {
+    return <div>no selected uuid</div>
+  }
+  const chArr = reducer.currentReducerState.recovery_information.challenges;
+  const challengeFeedback = reducer.currentReducerState.challenge_feedback ?? 
{};
+  const selectedUuid = reducer.currentReducerState.selected_challenge_uuid;
   const challenges: {
     [uuid: string]: ChallengeInfo;
   } = {};
@@ -25,17 +39,15 @@ export function SolveScreen(props: RecoveryReducerProps): 
VNode {
     email: SolveEmailEntry,
     post: SolvePostEntry,
   };
-  const SolveDialog = dialogMap[selectedChallenge.type] ?? 
SolveUnsupportedEntry;
+  const SolveDialog = dialogMap[selectedChallenge?.type] ?? 
SolveUnsupportedEntry;
   return (
     <SolveDialog
       challenge={selectedChallenge}
-      reducer={props.reducer}
       feedback={challengeFeedback[selectedUuid]} />
   );
 }
 
 export interface SolveEntryProps {
-  reducer: AnastasisReducerApi;
   challenge: ChallengeInfo;
   feedback?: ChallengeFeedback;
 }
diff --git a/packages/anastasis-webui/src/pages/home/SolveSmsEntry.tsx 
b/packages/anastasis-webui/src/pages/home/SolveSmsEntry.tsx
index d0cd4133..163e0d1f 100644
--- a/packages/anastasis-webui/src/pages/home/SolveSmsEntry.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveSmsEntry.tsx
@@ -1,14 +1,17 @@
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
+import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame, LabeledInput } from "./index";
 import { SolveEntryProps } from "./SolveScreen";
 
-export function SolveSmsEntry(props: SolveEntryProps): VNode {
+export function SolveSmsEntry({ challenge, feedback }: SolveEntryProps): VNode 
{
   const [answer, setAnswer] = useState("");
-  const { reducer, challenge, feedback } = props;
-  const next = (): void => reducer.transition("solve_challenge", {
-    answer,
-  });
+  const reducer = useAnastasisContext()
+  const next = (): void => {
+    if (reducer) reducer.transition("solve_challenge", {
+      answer,
+    })
+  };
   return (
     <AnastasisClientFrame
       title="Recovery: Solve challenge"
diff --git a/packages/anastasis-webui/src/pages/home/StartScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/StartScreen.stories.tsx
new file mode 100644
index 00000000..ad84cd8f
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/StartScreen.stories.tsx
@@ -0,0 +1,35 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../utils';
+import { StartScreen as TestedComponent } from './StartScreen';
+
+
+export default {
+  title: 'Pages/StartScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const InitialState = createExample(TestedComponent, 
reducerStatesExample.initial);
\ No newline at end of file
diff --git a/packages/anastasis-webui/src/pages/home/StartScreen.tsx 
b/packages/anastasis-webui/src/pages/home/StartScreen.tsx
index 38124887..6625ec5b 100644
--- a/packages/anastasis-webui/src/pages/home/StartScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/StartScreen.tsx
@@ -1,14 +1,34 @@
+
 import { h, VNode } from "preact";
-import { AnastasisReducerApi } from "../../hooks/use-anastasis-reducer";
+import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame } from "./index";
 
-export function StartScreen(props: { reducer: AnastasisReducerApi; }): VNode {
+export function StartScreen(): VNode {
+  const reducer = useAnastasisContext()
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
   return (
     <AnastasisClientFrame hideNav title="Home">
-      <button autoFocus onClick={() => props.reducer.startBackup()}>
-        Backup
-      </button>
-      <button onClick={() => props.reducer.startRecover()}>Recover</button>
+      <div>
+        <section class="section is-main-section">
+          <div class="columns">
+            <div class="column" />
+            <div class="column is-four-fifths">
+
+              <div class="buttons is-right">
+                <button class="button is-success" autoFocus onClick={() => 
reducer.startBackup()}>
+                  Backup
+                </button>
+
+                <button class="button is-info" onClick={() => 
reducer.startRecover()}>Recover</button>
+              </div>
+
+            </div>
+            <div class="column" />
+          </div>
+        </section>
+      </div>
     </AnastasisClientFrame>
   );
 }
diff --git 
a/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.stories.tsx
new file mode 100644
index 00000000..e2f3d521
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.stories.tsx
@@ -0,0 +1,40 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ReducerState } from 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../utils';
+import { TruthsPayingScreen as TestedComponent } from './TruthsPayingScreen';
+
+
+export default {
+  title: 'Pages/TruthsPayingScreen',
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+export const Example = createExample(TestedComponent, 
reducerStatesExample.truthsPaying);
+export const WithPaytoList = createExample(TestedComponent, {
+  ...reducerStatesExample.truthsPaying,
+  payments: ['payto://x-taler-bank/bank/account']
+} as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.tsx 
b/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.tsx
index 5b8a835b..319f590a 100644
--- a/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.tsx
@@ -1,8 +1,16 @@
 import { h, VNode } from "preact";
-import { BackupReducerProps, AnastasisClientFrame } from "./index";
+import { useAnastasisContext } from "../../context/anastasis";
+import { AnastasisClientFrame } from "./index";
 
-export function TruthsPayingScreen(props: BackupReducerProps): VNode {
-  const payments = props.backupState.payments ?? [];
+export function TruthsPayingScreen(): VNode {
+  const reducer = useAnastasisContext()
+  if (!reducer) {
+    return <div>no reducer in context</div>
+  }
+  if (!reducer.currentReducerState || reducer.currentReducerState.backup_state 
=== undefined) {
+    return <div>invalid state</div>
+  }
+  const payments = reducer.currentReducerState.payments ?? [];
   return (
     <AnastasisClientFrame
       hideNext
@@ -17,7 +25,7 @@ export function TruthsPayingScreen(props: 
BackupReducerProps): VNode {
           return <li key={i}>{x}</li>;
         })}
       </ul>
-      <button onClick={() => props.reducer.transition("pay", {})}>
+      <button onClick={() => reducer.transition("pay", {})}>
         Check payment status now
       </button>
     </AnastasisClientFrame>
diff --git a/packages/anastasis-webui/src/pages/home/index.tsx 
b/packages/anastasis-webui/src/pages/home/index.tsx
index 5001d1ee..4cec47ec 100644
--- a/packages/anastasis-webui/src/pages/home/index.tsx
+++ b/packages/anastasis-webui/src/pages/home/index.tsx
@@ -1,28 +1,25 @@
 import {
-  Component,
-  ComponentChildren,
-  createContext,
-  Fragment,
+  BackupStates,
+  RecoveryStates,
+  ReducerStateBackup,
+  ReducerStateRecovery
+} from "anastasis-core";
+import {
+  ComponentChildren, Fragment,
   FunctionalComponent,
   h,
-  VNode,
+  VNode
 } from "preact";
 import {
-  useContext,
   useErrorBoundary,
   useLayoutEffect,
-  useRef,
+  useRef
 } from "preact/hooks";
 import { Menu } from "../../components/menu";
-import {
-  BackupStates,
-  RecoveryStates,
-  ReducerStateBackup,
-  ReducerStateRecovery,
-} from "anastasis-core";
+import { AnastasisProvider, useAnastasisContext } from 
"../../context/anastasis";
 import {
   AnastasisReducerApi,
-  useAnastasisReducer,
+  useAnastasisReducer
 } from "../../hooks/use-anastasis-reducer";
 import { AttributeEntryScreen } from "./AttributeEntryScreen";
 import { AuthenticationEditorScreen } from "./AuthenticationEditorScreen";
@@ -38,19 +35,11 @@ import { SecretSelectionScreen } from 
"./SecretSelectionScreen";
 import { SolveScreen } from "./SolveScreen";
 import { StartScreen } from "./StartScreen";
 import { TruthsPayingScreen } from "./TruthsPayingScreen";
-import "./../home/style";
-
-const WithReducer = createContext<AnastasisReducerApi | undefined>(undefined);
 
 function isBackup(reducer: AnastasisReducerApi): boolean {
   return !!reducer.currentReducerState?.backup_state;
 }
 
-export interface CommonReducerProps {
-  reducer: AnastasisReducerApi;
-  reducerState: ReducerStateBackup | ReducerStateRecovery;
-}
-
 export function withProcessLabel(
   reducer: AnastasisReducerApi,
   text: string,
@@ -61,16 +50,6 @@ export function withProcessLabel(
   return `Recovery: ${text}`;
 }
 
-export interface BackupReducerProps {
-  reducer: AnastasisReducerApi;
-  backupState: ReducerStateBackup;
-}
-
-export interface RecoveryReducerProps {
-  reducer: AnastasisReducerApi;
-  recoveryState: ReducerStateRecovery;
-}
-
 interface AnastasisClientFrameProps {
   onNext?(): void;
   title: string;
@@ -88,7 +67,7 @@ interface AnastasisClientFrameProps {
 function ErrorBoundary(props: {
   reducer: AnastasisReducerApi;
   children: ComponentChildren;
-}) {
+}): VNode {
   const [error, resetError] = useErrorBoundary((error) =>
     console.log("got error", error),
   );
@@ -113,7 +92,7 @@ function ErrorBoundary(props: {
 }
 
 export function AnastasisClientFrame(props: AnastasisClientFrameProps): VNode {
-  const reducer = useContext(WithReducer);
+  const reducer = useAnastasisContext();
   if (!reducer) {
     return <p>Fatal: Reducer must be in context.</p>;
   }
@@ -135,9 +114,8 @@ export function AnastasisClientFrame(props: 
AnastasisClientFrameProps): VNode {
       <Menu title="Anastasis" />
       <div>
         <div class="home" onKeyPress={(e) => handleKeyPress(e)}>
-          <button onClick={() => reducer.reset()}>Reset session</button>
           <h1>{props.title}</h1>
-          <ErrorBanner reducer={reducer} />
+          <ErrorBanner />
           {props.children}
           {!props.hideNav ? (
             <div>
@@ -154,96 +132,94 @@ export function AnastasisClientFrame(props: 
AnastasisClientFrameProps): VNode {
 const AnastasisClient: FunctionalComponent = () => {
   const reducer = useAnastasisReducer();
   return (
-    <WithReducer.Provider value={reducer}>
+    <AnastasisProvider value={reducer}>
       <ErrorBoundary reducer={reducer}>
         <AnastasisClientImpl />
       </ErrorBoundary>
-    </WithReducer.Provider>
+    </AnastasisProvider>
   );
 };
 
 const AnastasisClientImpl: FunctionalComponent = () => {
-  const reducer = useContext(WithReducer)!;
-  const reducerState = reducer.currentReducerState;
-  if (!reducerState) {
-    return <StartScreen reducer={reducer} />;
+  const reducer = useAnastasisContext()
+  if (!reducer) {
+    return <p>Fatal: Reducer must be in context.</p>;
+  }
+  const state = reducer.currentReducerState;
+  if (!state) {
+    return <StartScreen />;
   }
   console.log("state", reducer.currentReducerState);
 
   if (
-    reducerState.backup_state === BackupStates.ContinentSelecting ||
-    reducerState.recovery_state === RecoveryStates.ContinentSelecting
+    state.backup_state === BackupStates.ContinentSelecting ||
+    state.recovery_state === RecoveryStates.ContinentSelecting
   ) {
     return (
-      <ContinentSelectionScreen reducer={reducer} reducerState={reducerState} 
/>
+      <ContinentSelectionScreen />
     );
   }
   if (
-    reducerState.backup_state === BackupStates.CountrySelecting ||
-    reducerState.recovery_state === RecoveryStates.CountrySelecting
+    state.backup_state === BackupStates.CountrySelecting ||
+    state.recovery_state === RecoveryStates.CountrySelecting
   ) {
     return (
-      <CountrySelectionScreen reducer={reducer} reducerState={reducerState} />
+      <CountrySelectionScreen />
     );
   }
   if (
-    reducerState.backup_state === BackupStates.UserAttributesCollecting ||
-    reducerState.recovery_state === RecoveryStates.UserAttributesCollecting
+    state.backup_state === BackupStates.UserAttributesCollecting ||
+    state.recovery_state === RecoveryStates.UserAttributesCollecting
   ) {
     return (
-      <AttributeEntryScreen reducer={reducer} reducerState={reducerState} />
+      <AttributeEntryScreen />
     );
   }
-  if (reducerState.backup_state === BackupStates.AuthenticationsEditing) {
+  if (state.backup_state === BackupStates.AuthenticationsEditing) {
     return (
-      <AuthenticationEditorScreen
-        backupState={reducerState}
-        reducer={reducer}
-      />
+      <AuthenticationEditorScreen />
     );
   }
-  if (reducerState.backup_state === BackupStates.PoliciesReviewing) {
+  if (state.backup_state === BackupStates.PoliciesReviewing) {
     return (
-      <ReviewPoliciesScreen reducer={reducer} backupState={reducerState} />
+      <ReviewPoliciesScreen />
     );
   }
-  if (reducerState.backup_state === BackupStates.SecretEditing) {
-    return <SecretEditorScreen reducer={reducer} backupState={reducerState} />;
+  if (state.backup_state === BackupStates.SecretEditing) {
+    return <SecretEditorScreen />;
   }
 
-  if (reducerState.backup_state === BackupStates.BackupFinished) {
-    const backupState: ReducerStateBackup = reducerState;
-    return <BackupFinishedScreen reducer={reducer} backupState={backupState} 
/>;
+  if (state.backup_state === BackupStates.BackupFinished) {
+    return <BackupFinishedScreen />;
   }
 
-  if (reducerState.backup_state === BackupStates.TruthsPaying) {
-    return <TruthsPayingScreen reducer={reducer} backupState={reducerState} />;
+  if (state.backup_state === BackupStates.TruthsPaying) {
+    return <TruthsPayingScreen />;
   }
 
-  if (reducerState.backup_state === BackupStates.PoliciesPaying) {
-    const backupState: ReducerStateBackup = reducerState;
-    return <PoliciesPayingScreen reducer={reducer} backupState={backupState} 
/>;
+  if (state.backup_state === BackupStates.PoliciesPaying) {
+    return <PoliciesPayingScreen />;
   }
 
-  if (reducerState.recovery_state === RecoveryStates.SecretSelecting) {
+  if (state.recovery_state === RecoveryStates.SecretSelecting) {
     return (
-      <SecretSelectionScreen reducer={reducer} recoveryState={reducerState} />
+      <SecretSelectionScreen />
     );
   }
 
-  if (reducerState.recovery_state === RecoveryStates.ChallengeSelecting) {
+  if (state.recovery_state === RecoveryStates.ChallengeSelecting) {
     return (
-      <ChallengeOverviewScreen reducer={reducer} recoveryState={reducerState} 
/>
+      <ChallengeOverviewScreen />
     );
   }
 
-  if (reducerState.recovery_state === RecoveryStates.ChallengeSolving) {
-    return <SolveScreen reducer={reducer} recoveryState={reducerState} />;
+  if (state.recovery_state === RecoveryStates.ChallengeSolving) {
+    return <SolveScreen />;
   }
 
-  if (reducerState.recovery_state === RecoveryStates.RecoveryFinished) {
+  if (state.recovery_state === RecoveryStates.RecoveryFinished) {
     return (
-      <RecoveryFinishedScreen reducer={reducer} recoveryState={reducerState} />
+      <RecoveryFinishedScreen />
     );
   }
 
@@ -251,7 +227,9 @@ const AnastasisClientImpl: FunctionalComponent = () => {
   return (
     <AnastasisClientFrame hideNav title="Bug">
       <p>Bug: Unknown state.</p>
-      <button onClick={() => reducer.reset()}>Reset</button>
+      <div class="buttons is-right">
+        <button class="button" onClick={() => reducer.reset()}>Reset</button>
+      </div>
     </AnastasisClientFrame>
   );
 };
@@ -282,26 +260,20 @@ export function LabeledInput(props: LabeledInputProps): 
VNode {
   );
 }
 
-interface ErrorBannerProps {
-  reducer: AnastasisReducerApi;
-}
-
 /**
- * Show a dismissable error banner if there is a current error.
+ * Show a dismissible error banner if there is a current error.
  */
-function ErrorBanner(props: ErrorBannerProps): VNode | null {
-  const currentError = props.reducer.currentError;
-  if (currentError) {
-    return (
-      <div id="error">
-        <p>Error: {JSON.stringify(currentError)}</p>
-        <button onClick={() => props.reducer.dismissError()}>
-          Dismiss Error
-        </button>
-      </div>
-    );
-  }
-  return null;
+function ErrorBanner(): VNode | null {
+  const reducer = useAnastasisContext();
+  if (!reducer || !reducer.currentError) return null;
+  return (
+    <div id="error">
+      <p>Error: {JSON.stringify(reducer.currentError)}</p>
+      <button onClick={() => reducer.dismissError()}>
+        Dismiss Error
+      </button>
+    </div>
+  );
 }
 
 export default AnastasisClient;
diff --git a/packages/anastasis-webui/src/utils/index.tsx 
b/packages/anastasis-webui/src/utils/index.tsx
new file mode 100644
index 00000000..d1d86146
--- /dev/null
+++ b/packages/anastasis-webui/src/utils/index.tsx
@@ -0,0 +1,161 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import { BackupStates, RecoveryStates, ReducerState } from 'anastasis-core';
+import { FunctionalComponent, h, VNode } from 'preact';
+import { AnastasisProvider } from '../context/anastasis';
+
+export function createExample<Props>(Component: FunctionalComponent<Props>, 
currentReducerState?: ReducerState, props?: Partial<Props>): { (args: Props): 
VNode } {
+  const r = (args: Props): VNode => {
+    return <AnastasisProvider value={{
+      currentReducerState,
+      currentError: undefined,
+      back: () => { null },
+      dismissError: () => { null },
+      reset: () => { null },
+      runTransaction: () => { null },
+      startBackup: () => { null },
+      startRecover: () => { null },
+      transition: () => { null },
+    }}>
+      <Component {...args} />
+    </AnastasisProvider>
+  }
+  r.args = props
+  return r
+}
+
+const base = {
+  continents: [
+    {
+      name: "Europe"
+    },
+    {
+      name: "India"
+    },
+    {
+      name: "Asia"
+    },
+    {
+      name: "North America"
+    },
+    {
+      name: "Testcontinent"
+    }
+  ],
+  countries: [
+    {
+      code: "xx",
+      name: "Testland",
+      continent: "Testcontinent",
+      continent_i18n: {
+        de_DE: "Testkontinent"
+      },
+      name_i18n: {
+        de_DE: "Testlandt",
+        de_CH: "Testlandi",
+        fr_FR: "Testpais",
+        en_UK: "Testland"
+      },
+      currency: "TESTKUDOS",
+      call_code: "+00"
+    },
+    {
+      code: "xy",
+      name: "Demoland",
+      continent: "Testcontinent",
+      continent_i18n: {
+        de_DE: "Testkontinent"
+      },
+      name_i18n: {
+        de_DE: "Demolandt",
+        de_CH: "Demolandi",
+        fr_FR: "Demopais",
+        en_UK: "Demoland"
+      },
+      currency: "KUDOS",
+      call_code: "+01"
+    }
+  ],
+  authentication_providers: {
+    "http://localhost:8086/": {
+      http_status: 200,
+      annual_fee: "COL:0",
+      business_name: "ana",
+      currency: "COL",
+      liability_limit: "COL:10",
+      methods: [
+        {
+          type: "question",
+          usage_fee: "COL:0"
+        }
+      ],
+      salt: "WBMDD76BR1E90YQ5AHBMKPH7GW",
+      storage_limit_in_megabytes: 16,
+      truth_upload_fee: "COL:0"
+    },
+    "http://localhost:8087/": {
+      code: 8414,
+      hint: "request to provider failed"
+    },
+    "http://localhost:8088/": {
+      code: 8414,
+      hint: "request to provider failed"
+    },
+    "http://localhost:8089/": {
+      code: 8414,
+      hint: "request to provider failed"
+    }
+  },
+  // expiration: {
+  //   d_ms: 1792525051855 // check t_ms
+  // },
+} as Partial<ReducerState>
+
+export const reducerStatesExample = {
+  initial: undefined,
+  recoverySelectCountry: {...base,
+    recovery_state: RecoveryStates.CountrySelecting
+  } as ReducerState,
+  backupSelectCountry: {...base,
+    backup_state: BackupStates.CountrySelecting
+  } as ReducerState,
+  recoverySelectContinent: {...base,
+    recovery_state: RecoveryStates.ContinentSelecting,
+  } as ReducerState,
+  backupSelectContinent: {...base,
+    backup_state: BackupStates.ContinentSelecting,
+  } as ReducerState,
+  secretSelection: {...base,
+    recovery_state: RecoveryStates.SecretSelecting,
+  } as ReducerState,
+  recoveryFinished: {...base,
+    recovery_state: RecoveryStates.RecoveryFinished,
+  } as ReducerState,
+  challengeSelecting: {...base,
+    recovery_state: RecoveryStates.ChallengeSelecting,
+  } as ReducerState,
+  challengeSolving: {...base,
+    recovery_state: RecoveryStates.ChallengeSolving,
+  } as ReducerState,
+  secretEdition: {...base,
+    backup_state: BackupStates.SecretEditing,
+  } as ReducerState,
+  policyReview: {...base,
+    backup_state: BackupStates.PoliciesReviewing,
+  } as ReducerState,
+  policyPay: {...base,
+    backup_state: BackupStates.PoliciesPaying,
+  } as ReducerState,
+  backupFinished: {...base,
+    backup_state: BackupStates.BackupFinished,
+  } as ReducerState,
+  authEditing: {...base,
+    backup_state: BackupStates.AuthenticationsEditing
+  } as ReducerState,
+  attributeEditing: {...base,
+    backup_state: BackupStates.UserAttributesCollecting
+  } as ReducerState,
+  truthsPaying: {...base,
+    backup_state: BackupStates.TruthsPaying
+  } as ReducerState,
+
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f5f77e57..cd6d7ae5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -35,6 +35,12 @@ importers:
     specifiers:
       '@creativebulma/bulma-tooltip': ^1.2.0
       '@gnu-taler/taler-util': workspace:^0.8.3
+      '@storybook/addon-a11y': ^6.2.9
+      '@storybook/addon-actions': ^6.2.9
+      '@storybook/addon-essentials': ^6.2.9
+      '@storybook/addon-links': ^6.2.9
+      '@storybook/preact': ^6.2.9
+      '@storybook/preset-scss': ^1.0.3
       '@types/enzyme': ^3.10.5
       '@types/jest': ^26.0.8
       '@typescript-eslint/eslint-plugin': ^2.25.0
@@ -67,6 +73,12 @@ importers:
       preact-router: 3.2.1_preact@10.5.14
     devDependencies:
       '@creativebulma/bulma-tooltip': 1.2.0
+      '@storybook/addon-a11y': 6.3.7
+      '@storybook/addon-actions': 6.3.7
+      '@storybook/addon-essentials': 6.3.7_typescript@3.9.10
+      '@storybook/addon-links': 6.3.12
+      '@storybook/preact': 6.3.7_preact@10.5.14+typescript@3.9.10
+      '@storybook/preset-scss': 1.0.3_sass-loader@10.2.0
       '@types/enzyme': 3.10.9
       '@types/jest': 26.0.24
       '@typescript-eslint/eslint-plugin': 
2.34.0_2b015b1c4b7c4a3ed9a197dc233b1a35
@@ -1724,6 +1736,15 @@ packages:
       '@babel/helper-plugin-utils': 7.14.5
     dev: true
 
+  /@babel/plugin-syntax-jsx/7.14.5:
+    resolution: {integrity: 
sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/helper-plugin-utils': 7.14.5
+    dev: true
+
   /@babel/plugin-syntax-jsx/7.14.5_@babel+core@7.13.16:
     resolution: {integrity: 
sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==}
     engines: {node: '>=6.9.0'}
@@ -2812,6 +2833,19 @@ packages:
       '@babel/helper-plugin-utils': 7.14.5
     dev: true
 
+  /@babel/plugin-transform-react-jsx/7.14.9:
+    resolution: {integrity: 
sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/helper-annotate-as-pure': 7.14.5
+      '@babel/helper-module-imports': 7.14.5
+      '@babel/helper-plugin-utils': 7.14.5
+      '@babel/plugin-syntax-jsx': 7.14.5
+      '@babel/types': 7.15.0
+    dev: true
+
   /@babel/plugin-transform-react-jsx/7.14.9_@babel+core@7.13.16:
     resolution: {integrity: 
sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==}
     engines: {node: '>=6.9.0'}
@@ -4800,6 +4834,101 @@ packages:
       - '@types/react'
     dev: true
 
+  /@storybook/addon-docs/6.3.7_typescript@3.9.10:
+    resolution: {integrity: 
sha512-cyuyoLuB5ELhbrXgnZneDCHqNq1wSdWZ4dzdHy1E5WwLPEhLlD6INfEsm8gnDIb4IncYuzMhK3XYBDd7d3ijOg==}
+    peerDependencies:
+      '@storybook/angular': 6.3.7
+      '@storybook/vue': 6.3.7
+      '@storybook/vue3': 6.3.7
+      '@storybook/web-components': 6.3.7
+      lit: ^2.0.0-rc.1
+      lit-html: ^1.4.1 || ^2.0.0-rc.3
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      svelte: ^3.31.2
+      sveltedoc-parser: ^4.1.0
+      vue: ^2.6.10 || ^3.0.0
+      webpack: '*'
+    peerDependenciesMeta:
+      '@storybook/angular':
+        optional: true
+      '@storybook/vue':
+        optional: true
+      '@storybook/vue3':
+        optional: true
+      '@storybook/web-components':
+        optional: true
+      lit:
+        optional: true
+      lit-html:
+        optional: true
+      react:
+        optional: true
+      react-dom:
+        optional: true
+      svelte:
+        optional: true
+      sveltedoc-parser:
+        optional: true
+      vue:
+        optional: true
+      webpack:
+        optional: true
+    dependencies:
+      '@babel/core': 7.15.0
+      '@babel/generator': 7.15.0
+      '@babel/parser': 7.15.3
+      '@babel/plugin-transform-react-jsx': 7.14.9_@babel+core@7.15.0
+      '@babel/preset-env': 7.15.0_@babel+core@7.15.0
+      '@jest/transform': 26.6.2
+      '@mdx-js/loader': 1.6.22
+      '@mdx-js/mdx': 1.6.22
+      '@mdx-js/react': 1.6.22
+      '@storybook/addons': 6.3.7
+      '@storybook/api': 6.3.7
+      '@storybook/builder-webpack4': 6.3.7_typescript@3.9.10
+      '@storybook/client-api': 6.3.7
+      '@storybook/client-logger': 6.3.7
+      '@storybook/components': 6.3.7
+      '@storybook/core': 6.3.7_36f75bb62e0c484c1a06658ad2872463
+      '@storybook/core-events': 6.3.7
+      '@storybook/csf': 0.0.1
+      '@storybook/csf-tools': 6.3.7_@babel+core@7.15.0
+      '@storybook/node-logger': 6.3.7
+      '@storybook/postinstall': 6.3.7
+      '@storybook/source-loader': 6.3.7
+      '@storybook/theming': 6.3.7
+      acorn: 7.4.1
+      acorn-jsx: 5.3.2_acorn@7.4.1
+      acorn-walk: 7.2.0
+      core-js: 3.16.2
+      doctrine: 3.0.0
+      escodegen: 2.0.0
+      fast-deep-equal: 3.1.3
+      global: 4.4.0
+      html-tags: 3.1.0
+      js-string-escape: 1.0.1
+      loader-utils: 2.0.0
+      lodash: 4.17.21
+      p-limit: 3.1.0
+      prettier: 2.2.1
+      prop-types: 15.7.2
+      react-element-to-jsx-string: 14.3.2
+      regenerator-runtime: 0.13.9
+      remark-external-links: 8.0.0
+      remark-slug: 6.1.0
+      ts-dedent: 2.2.0
+      util-deprecate: 1.0.2
+    transitivePeerDependencies:
+      - '@storybook/builder-webpack5'
+      - '@storybook/manager-webpack5'
+      - '@types/react'
+      - supports-color
+      - typescript
+      - webpack-cli
+      - webpack-command
+    dev: true
+
   /@storybook/addon-docs/6.3.7_typescript@4.3.5:
     resolution: {integrity: 
sha512-cyuyoLuB5ELhbrXgnZneDCHqNq1wSdWZ4dzdHy1E5WwLPEhLlD6INfEsm8gnDIb4IncYuzMhK3XYBDd7d3ijOg==}
     peerDependencies:
@@ -4955,6 +5084,89 @@ packages:
       - webpack-command
     dev: true
 
+  /@storybook/addon-essentials/6.3.7_typescript@3.9.10:
+    resolution: {integrity: 
sha512-ZWAW3qMFrrpfSekmCZibp/ivnohFLJdJweiIA0CLnuCNuuK9kQdpFahWdvyBy5NlCj3UJwB7epTZYZyHqYW7UQ==}
+    peerDependencies:
+      '@babel/core': ^7.9.6
+      '@storybook/vue': 6.3.7
+      '@storybook/web-components': 6.3.7
+      babel-loader: ^8.0.0
+      lit-html: ^1.4.1 || ^2.0.0-rc.3
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      webpack: '*'
+    peerDependenciesMeta:
+      '@storybook/vue':
+        optional: true
+      '@storybook/web-components':
+        optional: true
+      lit-html:
+        optional: true
+      react:
+        optional: true
+      react-dom:
+        optional: true
+      webpack:
+        optional: true
+    dependencies:
+      '@storybook/addon-actions': 6.3.7
+      '@storybook/addon-backgrounds': 6.3.7
+      '@storybook/addon-controls': 6.3.7
+      '@storybook/addon-docs': 6.3.7_typescript@3.9.10
+      '@storybook/addon-measure': 2.0.0_a4b77c99d63b159b69a1438c89904ed9
+      '@storybook/addon-toolbars': 6.3.7
+      '@storybook/addon-viewport': 6.3.7
+      '@storybook/addons': 6.3.7
+      '@storybook/api': 6.3.7
+      '@storybook/node-logger': 6.3.7
+      core-js: 3.16.2
+      regenerator-runtime: 0.13.9
+      storybook-addon-outline: 1.4.1
+      ts-dedent: 2.2.0
+    transitivePeerDependencies:
+      - '@storybook/angular'
+      - '@storybook/builder-webpack5'
+      - '@storybook/components'
+      - '@storybook/core-events'
+      - '@storybook/manager-webpack5'
+      - '@storybook/theming'
+      - '@storybook/vue3'
+      - '@types/react'
+      - lit
+      - supports-color
+      - svelte
+      - sveltedoc-parser
+      - typescript
+      - vue
+      - webpack-cli
+      - webpack-command
+    dev: true
+
+  /@storybook/addon-links/6.3.12:
+    resolution: {integrity: 
sha512-NfOGEm0+QxIrAXCa05LOXmxLtI+RlcDqHXZ1jNNj8mjeRoG1nX3qhkB8PWWIBbPuz+bktLV9ox8UZj0W6+ZPOQ==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+    peerDependenciesMeta:
+      react:
+        optional: true
+      react-dom:
+        optional: true
+    dependencies:
+      '@storybook/addons': 6.3.12
+      '@storybook/client-logger': 6.3.12
+      '@storybook/core-events': 6.3.12
+      '@storybook/csf': 0.0.1
+      '@storybook/router': 6.3.12
+      '@types/qs': 6.9.7
+      core-js: 3.16.2
+      global: 4.4.0
+      prop-types: 15.7.2
+      qs: 6.10.1
+      regenerator-runtime: 0.13.9
+      ts-dedent: 2.2.0
+    dev: true
+
   /@storybook/addon-measure/2.0.0_a4b77c99d63b159b69a1438c89904ed9:
     resolution: {integrity: 
sha512-ZhdT++cX+L9LwjhGYggvYUUVQH/MGn2rwbrAwCMzA/f2QTFvkjxzX8nDgMxIhaLCDC+gHIxfJG2wrWN0jkBr3g==}
     peerDependencies:
@@ -5023,6 +5235,23 @@ packages:
       - '@types/react'
     dev: true
 
+  /@storybook/addons/6.3.12:
+    resolution: {integrity: 
sha512-UgoMyr7Qr0FS3ezt8u6hMEcHgyynQS9ucr5mAwZky3wpXRPFyUTmMto9r4BBUdqyUvTUj/LRKIcmLBfj+/l0Fg==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+    dependencies:
+      '@storybook/api': 6.3.12
+      '@storybook/channels': 6.3.12
+      '@storybook/client-logger': 6.3.12
+      '@storybook/core-events': 6.3.12
+      '@storybook/router': 6.3.12
+      '@storybook/theming': 6.3.12
+      core-js: 3.16.2
+      global: 4.4.0
+      regenerator-runtime: 0.13.9
+    dev: true
+
   /@storybook/addons/6.3.7:
     resolution: {integrity: 
sha512-9stVjTcc52bqqh7YQex/LpSjJ4e2Czm4/ZYDjIiNy0p4OZEx+yLhL5mZzMWh2NQd6vv+pHASBSxf2IeaR5511A==}
     peerDependencies:
@@ -5059,6 +5288,34 @@ packages:
       regenerator-runtime: 0.13.9
     dev: true
 
+  /@storybook/api/6.3.12:
+    resolution: {integrity: 
sha512-LScRXUeCWEW/OP+jiooNMQICVdusv7azTmULxtm72fhkXFRiQs2CdRNTiqNg46JLLC9z95f1W+pGK66X6HiiQA==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+    dependencies:
+      '@reach/router': 1.3.4
+      '@storybook/channels': 6.3.12
+      '@storybook/client-logger': 6.3.12
+      '@storybook/core-events': 6.3.12
+      '@storybook/csf': 0.0.1
+      '@storybook/router': 6.3.12
+      '@storybook/semver': 7.3.2
+      '@storybook/theming': 6.3.12
+      '@types/reach__router': 1.3.9
+      core-js: 3.16.2
+      fast-deep-equal: 3.1.3
+      global: 4.4.0
+      lodash: 4.17.21
+      memoizerific: 1.11.3
+      qs: 6.10.1
+      regenerator-runtime: 0.13.9
+      store2: 2.12.0
+      telejson: 5.3.3
+      ts-dedent: 2.2.0
+      util-deprecate: 1.0.2
+    dev: true
+
   /@storybook/api/6.3.7:
     resolution: {integrity: 
sha512-57al8mxmE9agXZGo8syRQ8UhvGnDC9zkuwkBPXchESYYVkm3Mc54RTvdAOYDiy85VS4JxiGOywHayCaRwgUddQ==}
     peerDependencies:
@@ -5117,7 +5374,7 @@ packages:
       util-deprecate: 1.0.2
     dev: true
 
-  /@storybook/builder-webpack4/6.3.7_8073bd74a106ff14517e8eecceb690e6:
+  /@storybook/builder-webpack4/6.3.7_6b8328ae33be7bccbaedcbeca6bc1253:
     resolution: {integrity: 
sha512-M5envblMzAUrNqP1+ouKiL8iSIW/90+kBRU2QeWlZoZl1ib+fiFoKk06cgbaC70Bx1lU8nOnI/VBvB5pLhXLaw==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0
@@ -5155,7 +5412,7 @@ packages:
       '@storybook/client-api': 6.3.7_react-dom@16.14.0+react@16.14.0
       '@storybook/client-logger': 6.3.7
       '@storybook/components': 6.3.7_react-dom@16.14.0+react@16.14.0
-      '@storybook/core-common': 6.3.7_8073bd74a106ff14517e8eecceb690e6
+      '@storybook/core-common': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
       '@storybook/core-events': 6.3.7
       '@storybook/node-logger': 6.3.7
       '@storybook/router': 6.3.7_react-dom@16.14.0+react@16.14.0
@@ -5180,7 +5437,7 @@ packages:
       glob-promise: 3.4.0_glob@7.1.7
       global: 4.4.0
       html-webpack-plugin: 4.5.2_webpack@4.46.0
-      pnp-webpack-plugin: 1.6.4_typescript@4.3.5
+      pnp-webpack-plugin: 1.6.4_typescript@3.9.10
       postcss: 7.0.36
       postcss-flexbugs-fixes: 4.2.1
       postcss-loader: 4.3.0_postcss@7.0.36+webpack@4.46.0
@@ -5192,7 +5449,7 @@ packages:
       style-loader: 1.3.0_webpack@4.46.0
       terser-webpack-plugin: 4.2.3_webpack@4.46.0
       ts-dedent: 2.2.0
-      typescript: 4.3.5
+      typescript: 3.9.10
       url-loader: 4.1.1_file-loader@6.2.0+webpack@4.46.0
       util-deprecate: 1.0.2
       webpack: 4.46.0
@@ -5207,7 +5464,7 @@ packages:
       - webpack-command
     dev: true
 
-  /@storybook/builder-webpack4/6.3.7_typescript@4.3.5:
+  /@storybook/builder-webpack4/6.3.7_8073bd74a106ff14517e8eecceb690e6:
     resolution: {integrity: 
sha512-M5envblMzAUrNqP1+ouKiL8iSIW/90+kBRU2QeWlZoZl1ib+fiFoKk06cgbaC70Bx1lU8nOnI/VBvB5pLhXLaw==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0
@@ -5238,20 +5495,20 @@ packages:
       '@babel/preset-env': 7.15.0_@babel+core@7.15.0
       '@babel/preset-react': 7.14.5_@babel+core@7.15.0
       '@babel/preset-typescript': 7.15.0_@babel+core@7.15.0
-      '@storybook/addons': 6.3.7
-      '@storybook/api': 6.3.7
+      '@storybook/addons': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@storybook/api': 6.3.7_react-dom@16.14.0+react@16.14.0
       '@storybook/channel-postmessage': 6.3.7
       '@storybook/channels': 6.3.7
-      '@storybook/client-api': 6.3.7
+      '@storybook/client-api': 6.3.7_react-dom@16.14.0+react@16.14.0
       '@storybook/client-logger': 6.3.7
-      '@storybook/components': 6.3.7
-      '@storybook/core-common': 6.3.7_typescript@4.3.5
+      '@storybook/components': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@storybook/core-common': 6.3.7_8073bd74a106ff14517e8eecceb690e6
       '@storybook/core-events': 6.3.7
       '@storybook/node-logger': 6.3.7
-      '@storybook/router': 6.3.7
+      '@storybook/router': 6.3.7_react-dom@16.14.0+react@16.14.0
       '@storybook/semver': 7.3.2
-      '@storybook/theming': 6.3.7
-      '@storybook/ui': 6.3.7
+      '@storybook/theming': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@storybook/ui': 6.3.7_react-dom@16.14.0+react@16.14.0
       '@types/node': 14.17.10
       '@types/webpack': 4.41.30
       autoprefixer: 9.8.6
@@ -5275,7 +5532,9 @@ packages:
       postcss-flexbugs-fixes: 4.2.1
       postcss-loader: 4.3.0_postcss@7.0.36+webpack@4.46.0
       raw-loader: 4.0.2_webpack@4.46.0
+      react: 16.14.0
       react-dev-utils: 11.0.4
+      react-dom: 16.14.0_react@16.14.0
       stable: 0.1.8
       style-loader: 1.3.0_webpack@4.46.0
       terser-webpack-plugin: 4.2.3_webpack@4.46.0
@@ -5295,8 +5554,184 @@ packages:
       - webpack-command
     dev: true
 
-  /@storybook/channel-postmessage/6.3.7:
-    resolution: {integrity: 
sha512-Cmw8HRkeSF1yUFLfEIUIkUICyCXX8x5Ol/5QPbiW9HPE2hbZtYROCcg4bmWqdq59N0Tp9FQNSn+9ZygPgqQtNw==}
+  /@storybook/builder-webpack4/6.3.7_typescript@3.9.10:
+    resolution: {integrity: 
sha512-M5envblMzAUrNqP1+ouKiL8iSIW/90+kBRU2QeWlZoZl1ib+fiFoKk06cgbaC70Bx1lU8nOnI/VBvB5pLhXLaw==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@babel/core': 7.15.0
+      '@babel/plugin-proposal-class-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-decorators': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-export-default-from': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-nullish-coalescing-operator': 
7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-object-rest-spread': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-proposal-optional-chaining': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-private-methods': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.15.0
+      '@babel/plugin-transform-arrow-functions': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-block-scoping': 7.15.3_@babel+core@7.15.0
+      '@babel/plugin-transform-classes': 7.14.9_@babel+core@7.15.0
+      '@babel/plugin-transform-destructuring': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-transform-for-of': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-parameters': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-shorthand-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-spread': 7.14.6_@babel+core@7.15.0
+      '@babel/plugin-transform-template-literals': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-env': 7.15.0_@babel+core@7.15.0
+      '@babel/preset-react': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-typescript': 7.15.0_@babel+core@7.15.0
+      '@storybook/addons': 6.3.7
+      '@storybook/api': 6.3.7
+      '@storybook/channel-postmessage': 6.3.7
+      '@storybook/channels': 6.3.7
+      '@storybook/client-api': 6.3.7
+      '@storybook/client-logger': 6.3.7
+      '@storybook/components': 6.3.7
+      '@storybook/core-common': 6.3.7_typescript@3.9.10
+      '@storybook/core-events': 6.3.7
+      '@storybook/node-logger': 6.3.7
+      '@storybook/router': 6.3.7
+      '@storybook/semver': 7.3.2
+      '@storybook/theming': 6.3.7
+      '@storybook/ui': 6.3.7
+      '@types/node': 14.17.10
+      '@types/webpack': 4.41.30
+      autoprefixer: 9.8.6
+      babel-loader: 8.2.2_be352a5a80662835a7707f972edfcfde
+      babel-plugin-macros: 2.8.0
+      babel-plugin-polyfill-corejs3: 0.1.7_@babel+core@7.15.0
+      case-sensitive-paths-webpack-plugin: 2.4.0
+      core-js: 3.16.2
+      css-loader: 3.6.0_webpack@4.46.0
+      dotenv-webpack: 1.8.0_webpack@4.46.0
+      file-loader: 6.2.0_webpack@4.46.0
+      find-up: 5.0.0
+      fork-ts-checker-webpack-plugin: 4.1.6
+      fs-extra: 9.1.0
+      glob: 7.1.7
+      glob-promise: 3.4.0_glob@7.1.7
+      global: 4.4.0
+      html-webpack-plugin: 4.5.2_webpack@4.46.0
+      pnp-webpack-plugin: 1.6.4_typescript@3.9.10
+      postcss: 7.0.36
+      postcss-flexbugs-fixes: 4.2.1
+      postcss-loader: 4.3.0_postcss@7.0.36+webpack@4.46.0
+      raw-loader: 4.0.2_webpack@4.46.0
+      react-dev-utils: 11.0.4
+      stable: 0.1.8
+      style-loader: 1.3.0_webpack@4.46.0
+      terser-webpack-plugin: 4.2.3_webpack@4.46.0
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      url-loader: 4.1.1_file-loader@6.2.0+webpack@4.46.0
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+      webpack-dev-middleware: 3.7.3_webpack@4.46.0
+      webpack-filter-warnings-plugin: 1.2.1_webpack@4.46.0
+      webpack-hot-middleware: 2.25.0
+      webpack-virtual-modules: 0.2.2
+    transitivePeerDependencies:
+      - '@types/react'
+      - supports-color
+      - webpack-cli
+      - webpack-command
+    dev: true
+
+  /@storybook/builder-webpack4/6.3.7_typescript@4.3.5:
+    resolution: {integrity: 
sha512-M5envblMzAUrNqP1+ouKiL8iSIW/90+kBRU2QeWlZoZl1ib+fiFoKk06cgbaC70Bx1lU8nOnI/VBvB5pLhXLaw==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@babel/core': 7.15.0
+      '@babel/plugin-proposal-class-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-decorators': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-export-default-from': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-nullish-coalescing-operator': 
7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-object-rest-spread': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-proposal-optional-chaining': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-private-methods': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.15.0
+      '@babel/plugin-transform-arrow-functions': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-block-scoping': 7.15.3_@babel+core@7.15.0
+      '@babel/plugin-transform-classes': 7.14.9_@babel+core@7.15.0
+      '@babel/plugin-transform-destructuring': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-transform-for-of': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-parameters': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-shorthand-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-spread': 7.14.6_@babel+core@7.15.0
+      '@babel/plugin-transform-template-literals': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-env': 7.15.0_@babel+core@7.15.0
+      '@babel/preset-react': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-typescript': 7.15.0_@babel+core@7.15.0
+      '@storybook/addons': 6.3.7
+      '@storybook/api': 6.3.7
+      '@storybook/channel-postmessage': 6.3.7
+      '@storybook/channels': 6.3.7
+      '@storybook/client-api': 6.3.7
+      '@storybook/client-logger': 6.3.7
+      '@storybook/components': 6.3.7
+      '@storybook/core-common': 6.3.7_typescript@4.3.5
+      '@storybook/core-events': 6.3.7
+      '@storybook/node-logger': 6.3.7
+      '@storybook/router': 6.3.7
+      '@storybook/semver': 7.3.2
+      '@storybook/theming': 6.3.7
+      '@storybook/ui': 6.3.7
+      '@types/node': 14.17.10
+      '@types/webpack': 4.41.30
+      autoprefixer: 9.8.6
+      babel-loader: 8.2.2_be352a5a80662835a7707f972edfcfde
+      babel-plugin-macros: 2.8.0
+      babel-plugin-polyfill-corejs3: 0.1.7_@babel+core@7.15.0
+      case-sensitive-paths-webpack-plugin: 2.4.0
+      core-js: 3.16.2
+      css-loader: 3.6.0_webpack@4.46.0
+      dotenv-webpack: 1.8.0_webpack@4.46.0
+      file-loader: 6.2.0_webpack@4.46.0
+      find-up: 5.0.0
+      fork-ts-checker-webpack-plugin: 4.1.6
+      fs-extra: 9.1.0
+      glob: 7.1.7
+      glob-promise: 3.4.0_glob@7.1.7
+      global: 4.4.0
+      html-webpack-plugin: 4.5.2_webpack@4.46.0
+      pnp-webpack-plugin: 1.6.4_typescript@4.3.5
+      postcss: 7.0.36
+      postcss-flexbugs-fixes: 4.2.1
+      postcss-loader: 4.3.0_postcss@7.0.36+webpack@4.46.0
+      raw-loader: 4.0.2_webpack@4.46.0
+      react-dev-utils: 11.0.4
+      stable: 0.1.8
+      style-loader: 1.3.0_webpack@4.46.0
+      terser-webpack-plugin: 4.2.3_webpack@4.46.0
+      ts-dedent: 2.2.0
+      typescript: 4.3.5
+      url-loader: 4.1.1_file-loader@6.2.0+webpack@4.46.0
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+      webpack-dev-middleware: 3.7.3_webpack@4.46.0
+      webpack-filter-warnings-plugin: 1.2.1_webpack@4.46.0
+      webpack-hot-middleware: 2.25.0
+      webpack-virtual-modules: 0.2.2
+    transitivePeerDependencies:
+      - '@types/react'
+      - supports-color
+      - webpack-cli
+      - webpack-command
+    dev: true
+
+  /@storybook/channel-postmessage/6.3.7:
+    resolution: {integrity: 
sha512-Cmw8HRkeSF1yUFLfEIUIkUICyCXX8x5Ol/5QPbiW9HPE2hbZtYROCcg4bmWqdq59N0Tp9FQNSn+9ZygPgqQtNw==}
     dependencies:
       '@storybook/channels': 6.3.7
       '@storybook/client-logger': 6.3.7
@@ -5307,6 +5742,14 @@ packages:
       telejson: 5.3.3
     dev: true
 
+  /@storybook/channels/6.3.12:
+    resolution: {integrity: 
sha512-l4sA+g1PdUV8YCbgs47fIKREdEQAKNdQIZw0b7BfTvY9t0x5yfBywgQhYON/lIeiNGz2OlIuD+VUtqYfCtNSyw==}
+    dependencies:
+      core-js: 3.16.2
+      ts-dedent: 2.2.0
+      util-deprecate: 1.0.2
+    dev: true
+
   /@storybook/channels/6.3.7:
     resolution: {integrity: 
sha512-aErXO+SRO8MPp2wOkT2n9d0fby+8yM35tq1tI633B4eQsM74EykbXPv7EamrYPqp1AI4BdiloyEpr0hmr2zlvg==}
     dependencies:
@@ -5369,6 +5812,13 @@ packages:
       util-deprecate: 1.0.2
     dev: true
 
+  /@storybook/client-logger/6.3.12:
+    resolution: {integrity: 
sha512-zNDsamZvHnuqLznDdP9dUeGgQ9TyFh4ray3t1VGO7ZqWVZ2xtVCCXjDvMnOXI2ifMpX5UsrOvshIPeE9fMBmiQ==}
+    dependencies:
+      core-js: 3.16.2
+      global: 4.4.0
+    dev: true
+
   /@storybook/client-logger/6.3.7:
     resolution: {integrity: 
sha512-BQRErHE3nIEuUJN/3S3dO1LzxAknOgrFeZLd4UVcH/fvjtS1F4EkhcbH+jNyUWvcWGv66PZYN0oFPEn/g3Savg==}
     dependencies:
@@ -5446,7 +5896,7 @@ packages:
       - '@types/react'
     dev: true
 
-  /@storybook/core-client/6.3.7_70d39b49be06a92d1ddadaf2d0a6de02:
+  /@storybook/core-client/6.3.7_3c33386fd9b1d5f07f48f07869b17b73:
     resolution: {integrity: 
sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0
@@ -5474,7 +5924,7 @@ packages:
       react-dom: 16.14.0_react@16.14.0
       regenerator-runtime: 0.13.9
       ts-dedent: 2.2.0
-      typescript: 4.3.5
+      typescript: 3.9.10
       unfetch: 4.2.0
       util-deprecate: 1.0.2
       webpack: 4.46.0
@@ -5482,7 +5932,42 @@ packages:
       - '@types/react'
     dev: true
 
-  /@storybook/core-client/6.3.7_8073bd74a106ff14517e8eecceb690e6:
+  /@storybook/core-client/6.3.7_6b8328ae33be7bccbaedcbeca6bc1253:
+    resolution: {integrity: 
sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+      webpack: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@storybook/addons': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@storybook/channel-postmessage': 6.3.7
+      '@storybook/client-api': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@storybook/client-logger': 6.3.7
+      '@storybook/core-events': 6.3.7
+      '@storybook/csf': 0.0.1
+      '@storybook/ui': 6.3.7_react-dom@16.14.0+react@16.14.0
+      airbnb-js-shims: 2.2.1
+      ansi-to-html: 0.6.15
+      core-js: 3.16.2
+      global: 4.4.0
+      lodash: 4.17.21
+      qs: 6.10.1
+      react: 16.14.0
+      react-dom: 16.14.0_react@16.14.0
+      regenerator-runtime: 0.13.9
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      unfetch: 4.2.0
+      util-deprecate: 1.0.2
+    transitivePeerDependencies:
+      - '@types/react'
+    dev: true
+
+  /@storybook/core-client/6.3.7_70d39b49be06a92d1ddadaf2d0a6de02:
     resolution: {integrity: 
sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0
@@ -5513,11 +5998,12 @@ packages:
       typescript: 4.3.5
       unfetch: 4.2.0
       util-deprecate: 1.0.2
+      webpack: 4.46.0
     transitivePeerDependencies:
       - '@types/react'
     dev: true
 
-  /@storybook/core-client/6.3.7_typescript@4.3.5:
+  /@storybook/core-client/6.3.7_8073bd74a106ff14517e8eecceb690e6:
     resolution: {integrity: 
sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0
@@ -5528,19 +6014,21 @@ packages:
       typescript:
         optional: true
     dependencies:
-      '@storybook/addons': 6.3.7
+      '@storybook/addons': 6.3.7_react-dom@16.14.0+react@16.14.0
       '@storybook/channel-postmessage': 6.3.7
-      '@storybook/client-api': 6.3.7
+      '@storybook/client-api': 6.3.7_react-dom@16.14.0+react@16.14.0
       '@storybook/client-logger': 6.3.7
       '@storybook/core-events': 6.3.7
       '@storybook/csf': 0.0.1
-      '@storybook/ui': 6.3.7
+      '@storybook/ui': 6.3.7_react-dom@16.14.0+react@16.14.0
       airbnb-js-shims: 2.2.1
       ansi-to-html: 0.6.15
       core-js: 3.16.2
       global: 4.4.0
       lodash: 4.17.21
       qs: 6.10.1
+      react: 16.14.0
+      react-dom: 16.14.0_react@16.14.0
       regenerator-runtime: 0.13.9
       ts-dedent: 2.2.0
       typescript: 4.3.5
@@ -5550,7 +6038,7 @@ packages:
       - '@types/react'
     dev: true
 
-  /@storybook/core-client/6.3.7_typescript@4.3.5+webpack@4.46.0:
+  /@storybook/core-client/6.3.7_typescript@3.9.10:
     resolution: {integrity: 
sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0
@@ -5576,44 +6064,211 @@ packages:
       qs: 6.10.1
       regenerator-runtime: 0.13.9
       ts-dedent: 2.2.0
-      typescript: 4.3.5
+      typescript: 3.9.10
       unfetch: 4.2.0
       util-deprecate: 1.0.2
-      webpack: 4.46.0
     transitivePeerDependencies:
       - '@types/react'
     dev: true
 
-  /@storybook/core-common/6.3.7_8073bd74a106ff14517e8eecceb690e6:
-    resolution: {integrity: 
sha512-exLoqRPPsAefwyjbsQBLNFrlPCcv69Q/pclqmIm7FqAPR7f3CKP1rqsHY0PnemizTL/+cLX5S7mY90gI6wpNug==}
+  /@storybook/core-client/6.3.7_typescript@3.9.10+webpack@4.46.0:
+    resolution: {integrity: 
sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0
       react-dom: ^16.8.0 || ^17.0.0
       typescript: '*'
+      webpack: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
-      '@babel/core': 7.15.0
-      '@babel/plugin-proposal-class-properties': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-proposal-decorators': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-proposal-export-default-from': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-proposal-nullish-coalescing-operator': 
7.14.5_@babel+core@7.15.0
-      '@babel/plugin-proposal-object-rest-spread': 7.14.7_@babel+core@7.15.0
-      '@babel/plugin-proposal-optional-chaining': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-proposal-private-methods': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.15.0
-      '@babel/plugin-transform-arrow-functions': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-transform-block-scoping': 7.15.3_@babel+core@7.15.0
-      '@babel/plugin-transform-classes': 7.14.9_@babel+core@7.15.0
-      '@babel/plugin-transform-destructuring': 7.14.7_@babel+core@7.15.0
-      '@babel/plugin-transform-for-of': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-transform-parameters': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-transform-shorthand-properties': 7.14.5_@babel+core@7.15.0
-      '@babel/plugin-transform-spread': 7.14.6_@babel+core@7.15.0
-      '@babel/preset-env': 7.15.0_@babel+core@7.15.0
-      '@babel/preset-react': 7.14.5_@babel+core@7.15.0
-      '@babel/preset-typescript': 7.15.0_@babel+core@7.15.0
+      '@storybook/addons': 6.3.7
+      '@storybook/channel-postmessage': 6.3.7
+      '@storybook/client-api': 6.3.7
+      '@storybook/client-logger': 6.3.7
+      '@storybook/core-events': 6.3.7
+      '@storybook/csf': 0.0.1
+      '@storybook/ui': 6.3.7
+      airbnb-js-shims: 2.2.1
+      ansi-to-html: 0.6.15
+      core-js: 3.16.2
+      global: 4.4.0
+      lodash: 4.17.21
+      qs: 6.10.1
+      regenerator-runtime: 0.13.9
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      unfetch: 4.2.0
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+    transitivePeerDependencies:
+      - '@types/react'
+    dev: true
+
+  /@storybook/core-client/6.3.7_typescript@4.3.5:
+    resolution: {integrity: 
sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+      webpack: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@storybook/addons': 6.3.7
+      '@storybook/channel-postmessage': 6.3.7
+      '@storybook/client-api': 6.3.7
+      '@storybook/client-logger': 6.3.7
+      '@storybook/core-events': 6.3.7
+      '@storybook/csf': 0.0.1
+      '@storybook/ui': 6.3.7
+      airbnb-js-shims: 2.2.1
+      ansi-to-html: 0.6.15
+      core-js: 3.16.2
+      global: 4.4.0
+      lodash: 4.17.21
+      qs: 6.10.1
+      regenerator-runtime: 0.13.9
+      ts-dedent: 2.2.0
+      typescript: 4.3.5
+      unfetch: 4.2.0
+      util-deprecate: 1.0.2
+    transitivePeerDependencies:
+      - '@types/react'
+    dev: true
+
+  /@storybook/core-client/6.3.7_typescript@4.3.5+webpack@4.46.0:
+    resolution: {integrity: 
sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+      webpack: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@storybook/addons': 6.3.7
+      '@storybook/channel-postmessage': 6.3.7
+      '@storybook/client-api': 6.3.7
+      '@storybook/client-logger': 6.3.7
+      '@storybook/core-events': 6.3.7
+      '@storybook/csf': 0.0.1
+      '@storybook/ui': 6.3.7
+      airbnb-js-shims: 2.2.1
+      ansi-to-html: 0.6.15
+      core-js: 3.16.2
+      global: 4.4.0
+      lodash: 4.17.21
+      qs: 6.10.1
+      regenerator-runtime: 0.13.9
+      ts-dedent: 2.2.0
+      typescript: 4.3.5
+      unfetch: 4.2.0
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+    transitivePeerDependencies:
+      - '@types/react'
+    dev: true
+
+  /@storybook/core-common/6.3.7_6b8328ae33be7bccbaedcbeca6bc1253:
+    resolution: {integrity: 
sha512-exLoqRPPsAefwyjbsQBLNFrlPCcv69Q/pclqmIm7FqAPR7f3CKP1rqsHY0PnemizTL/+cLX5S7mY90gI6wpNug==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@babel/core': 7.15.0
+      '@babel/plugin-proposal-class-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-decorators': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-export-default-from': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-nullish-coalescing-operator': 
7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-object-rest-spread': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-proposal-optional-chaining': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-private-methods': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.15.0
+      '@babel/plugin-transform-arrow-functions': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-block-scoping': 7.15.3_@babel+core@7.15.0
+      '@babel/plugin-transform-classes': 7.14.9_@babel+core@7.15.0
+      '@babel/plugin-transform-destructuring': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-transform-for-of': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-parameters': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-shorthand-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-spread': 7.14.6_@babel+core@7.15.0
+      '@babel/preset-env': 7.15.0_@babel+core@7.15.0
+      '@babel/preset-react': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-typescript': 7.15.0_@babel+core@7.15.0
+      '@babel/register': 7.15.3_@babel+core@7.15.0
+      '@storybook/node-logger': 6.3.7
+      '@storybook/semver': 7.3.2
+      '@types/glob-base': 0.3.0
+      '@types/micromatch': 4.0.2
+      '@types/node': 14.17.10
+      '@types/pretty-hrtime': 1.0.1
+      babel-loader: 8.2.2_be352a5a80662835a7707f972edfcfde
+      babel-plugin-macros: 3.1.0
+      babel-plugin-polyfill-corejs3: 0.1.7_@babel+core@7.15.0
+      chalk: 4.1.2
+      core-js: 3.16.2
+      express: 4.17.1
+      file-system-cache: 1.0.5
+      find-up: 5.0.0
+      fork-ts-checker-webpack-plugin: 6.3.2
+      glob: 7.1.7
+      glob-base: 0.3.0
+      interpret: 2.2.0
+      json5: 2.2.0
+      lazy-universal-dotenv: 3.0.1
+      micromatch: 4.0.4
+      pkg-dir: 5.0.0
+      pretty-hrtime: 1.0.3
+      react: 16.14.0
+      react-dom: 16.14.0_react@16.14.0
+      resolve-from: 5.0.0
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+    transitivePeerDependencies:
+      - supports-color
+      - webpack-cli
+      - webpack-command
+    dev: true
+
+  /@storybook/core-common/6.3.7_8073bd74a106ff14517e8eecceb690e6:
+    resolution: {integrity: 
sha512-exLoqRPPsAefwyjbsQBLNFrlPCcv69Q/pclqmIm7FqAPR7f3CKP1rqsHY0PnemizTL/+cLX5S7mY90gI6wpNug==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@babel/core': 7.15.0
+      '@babel/plugin-proposal-class-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-decorators': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-export-default-from': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-nullish-coalescing-operator': 
7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-object-rest-spread': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-proposal-optional-chaining': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-private-methods': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.15.0
+      '@babel/plugin-transform-arrow-functions': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-block-scoping': 7.15.3_@babel+core@7.15.0
+      '@babel/plugin-transform-classes': 7.14.9_@babel+core@7.15.0
+      '@babel/plugin-transform-destructuring': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-transform-for-of': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-parameters': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-shorthand-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-spread': 7.14.6_@babel+core@7.15.0
+      '@babel/preset-env': 7.15.0_@babel+core@7.15.0
+      '@babel/preset-react': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-typescript': 7.15.0_@babel+core@7.15.0
       '@babel/register': 7.15.3_@babel+core@7.15.0
       '@storybook/node-logger': 6.3.7
       '@storybook/semver': 7.3.2
@@ -5651,6 +6306,71 @@ packages:
       - webpack-command
     dev: true
 
+  /@storybook/core-common/6.3.7_typescript@3.9.10:
+    resolution: {integrity: 
sha512-exLoqRPPsAefwyjbsQBLNFrlPCcv69Q/pclqmIm7FqAPR7f3CKP1rqsHY0PnemizTL/+cLX5S7mY90gI6wpNug==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@babel/core': 7.15.0
+      '@babel/plugin-proposal-class-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-decorators': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-export-default-from': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-nullish-coalescing-operator': 
7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-object-rest-spread': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-proposal-optional-chaining': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-proposal-private-methods': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.15.0
+      '@babel/plugin-transform-arrow-functions': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-block-scoping': 7.15.3_@babel+core@7.15.0
+      '@babel/plugin-transform-classes': 7.14.9_@babel+core@7.15.0
+      '@babel/plugin-transform-destructuring': 7.14.7_@babel+core@7.15.0
+      '@babel/plugin-transform-for-of': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-parameters': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-shorthand-properties': 7.14.5_@babel+core@7.15.0
+      '@babel/plugin-transform-spread': 7.14.6_@babel+core@7.15.0
+      '@babel/preset-env': 7.15.0_@babel+core@7.15.0
+      '@babel/preset-react': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-typescript': 7.15.0_@babel+core@7.15.0
+      '@babel/register': 7.15.3_@babel+core@7.15.0
+      '@storybook/node-logger': 6.3.7
+      '@storybook/semver': 7.3.2
+      '@types/glob-base': 0.3.0
+      '@types/micromatch': 4.0.2
+      '@types/node': 14.17.10
+      '@types/pretty-hrtime': 1.0.1
+      babel-loader: 8.2.2_be352a5a80662835a7707f972edfcfde
+      babel-plugin-macros: 3.1.0
+      babel-plugin-polyfill-corejs3: 0.1.7_@babel+core@7.15.0
+      chalk: 4.1.2
+      core-js: 3.16.2
+      express: 4.17.1
+      file-system-cache: 1.0.5
+      find-up: 5.0.0
+      fork-ts-checker-webpack-plugin: 6.3.2
+      glob: 7.1.7
+      glob-base: 0.3.0
+      interpret: 2.2.0
+      json5: 2.2.0
+      lazy-universal-dotenv: 3.0.1
+      micromatch: 4.0.4
+      pkg-dir: 5.0.0
+      pretty-hrtime: 1.0.3
+      resolve-from: 5.0.0
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+    transitivePeerDependencies:
+      - supports-color
+      - webpack-cli
+      - webpack-command
+    dev: true
+
   /@storybook/core-common/6.3.7_typescript@4.3.5:
     resolution: {integrity: 
sha512-exLoqRPPsAefwyjbsQBLNFrlPCcv69Q/pclqmIm7FqAPR7f3CKP1rqsHY0PnemizTL/+cLX5S7mY90gI6wpNug==}
     peerDependencies:
@@ -5716,12 +6436,136 @@ packages:
       - webpack-command
     dev: true
 
+  /@storybook/core-events/6.3.12:
+    resolution: {integrity: 
sha512-SXfD7xUUMazaeFkB92qOTUV8Y/RghE4SkEYe5slAdjeocSaH7Nz2WV0rqNEgChg0AQc+JUI66no8L9g0+lw4Gw==}
+    dependencies:
+      core-js: 3.16.2
+    dev: true
+
   /@storybook/core-events/6.3.7:
     resolution: {integrity: 
sha512-l5Hlhe+C/dqxjobemZ6DWBhTOhQoFF3F1Y4kjFGE7pGZl/mas4M72I5I/FUcYCmbk2fbLfZX8hzKkUqS1hdyLA==}
     dependencies:
       core-js: 3.16.2
     dev: true
 
+  /@storybook/core-server/6.3.7_36f75bb62e0c484c1a06658ad2872463:
+    resolution: {integrity: 
sha512-m5OPD/rmZA7KFewkXzXD46/i1ngUoFO4LWOiAY/wR6RQGjYXGMhSa5UYFF6MNwSbiGS5YieHkR5crB1HP47AhQ==}
+    peerDependencies:
+      '@storybook/builder-webpack5': 6.3.7
+      '@storybook/manager-webpack5': 6.3.7
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      '@storybook/builder-webpack5':
+        optional: true
+      '@storybook/manager-webpack5':
+        optional: true
+      typescript:
+        optional: true
+    dependencies:
+      '@storybook/builder-webpack4': 6.3.7_typescript@3.9.10
+      '@storybook/core-client': 6.3.7_typescript@3.9.10+webpack@4.46.0
+      '@storybook/core-common': 6.3.7_typescript@3.9.10
+      '@storybook/csf-tools': 6.3.7_@babel+core@7.15.0
+      '@storybook/manager-webpack4': 6.3.7_typescript@3.9.10
+      '@storybook/node-logger': 6.3.7
+      '@storybook/semver': 7.3.2
+      '@types/node': 14.17.10
+      '@types/node-fetch': 2.5.12
+      '@types/pretty-hrtime': 1.0.1
+      '@types/webpack': 4.41.30
+      better-opn: 2.1.1
+      boxen: 4.2.0
+      chalk: 4.1.2
+      cli-table3: 0.6.0
+      commander: 6.2.1
+      compression: 1.7.4
+      core-js: 3.16.2
+      cpy: 8.1.2
+      detect-port: 1.3.0
+      express: 4.17.1
+      file-system-cache: 1.0.5
+      fs-extra: 9.1.0
+      globby: 11.0.4
+      ip: 1.1.5
+      node-fetch: 2.6.1
+      pretty-hrtime: 1.0.3
+      prompts: 2.4.1
+      regenerator-runtime: 0.13.9
+      serve-favicon: 2.5.0
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+    transitivePeerDependencies:
+      - '@babel/core'
+      - '@types/react'
+      - supports-color
+      - webpack-cli
+      - webpack-command
+    dev: true
+
+  /@storybook/core-server/6.3.7_6b8328ae33be7bccbaedcbeca6bc1253:
+    resolution: {integrity: 
sha512-m5OPD/rmZA7KFewkXzXD46/i1ngUoFO4LWOiAY/wR6RQGjYXGMhSa5UYFF6MNwSbiGS5YieHkR5crB1HP47AhQ==}
+    peerDependencies:
+      '@storybook/builder-webpack5': 6.3.7
+      '@storybook/manager-webpack5': 6.3.7
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      '@storybook/builder-webpack5':
+        optional: true
+      '@storybook/manager-webpack5':
+        optional: true
+      typescript:
+        optional: true
+    dependencies:
+      '@storybook/builder-webpack4': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
+      '@storybook/core-client': 6.3.7_3c33386fd9b1d5f07f48f07869b17b73
+      '@storybook/core-common': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
+      '@storybook/csf-tools': 6.3.7
+      '@storybook/manager-webpack4': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
+      '@storybook/node-logger': 6.3.7
+      '@storybook/semver': 7.3.2
+      '@types/node': 14.17.10
+      '@types/node-fetch': 2.5.12
+      '@types/pretty-hrtime': 1.0.1
+      '@types/webpack': 4.41.30
+      better-opn: 2.1.1
+      boxen: 4.2.0
+      chalk: 4.1.2
+      cli-table3: 0.6.0
+      commander: 6.2.1
+      compression: 1.7.4
+      core-js: 3.16.2
+      cpy: 8.1.2
+      detect-port: 1.3.0
+      express: 4.17.1
+      file-system-cache: 1.0.5
+      fs-extra: 9.1.0
+      globby: 11.0.4
+      ip: 1.1.5
+      node-fetch: 2.6.1
+      pretty-hrtime: 1.0.3
+      prompts: 2.4.1
+      react: 16.14.0
+      react-dom: 16.14.0_react@16.14.0
+      regenerator-runtime: 0.13.9
+      serve-favicon: 2.5.0
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+    transitivePeerDependencies:
+      - '@babel/core'
+      - '@types/react'
+      - supports-color
+      - webpack-cli
+      - webpack-command
+    dev: true
+
   /@storybook/core-server/6.3.7_f0b419a7e119055c71dcaf6063a7ba7a:
     resolution: {integrity: 
sha512-m5OPD/rmZA7KFewkXzXD46/i1ngUoFO4LWOiAY/wR6RQGjYXGMhSa5UYFF6MNwSbiGS5YieHkR5crB1HP47AhQ==}
     peerDependencies:
@@ -5840,6 +6684,60 @@ packages:
       - webpack-command
     dev: true
 
+  /@storybook/core/6.3.7_36f75bb62e0c484c1a06658ad2872463:
+    resolution: {integrity: 
sha512-YTVLPXqgyBg7TALNxQ+cd+GtCm/NFjxr/qQ1mss1T9GCMR0IjE0d0trgOVHHLAO8jCVlK8DeuqZCCgZFTXulRw==}
+    peerDependencies:
+      '@storybook/builder-webpack5': 6.3.7
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      '@storybook/builder-webpack5':
+        optional: true
+      typescript:
+        optional: true
+    dependencies:
+      '@storybook/core-client': 6.3.7_typescript@3.9.10
+      '@storybook/core-server': 6.3.7_36f75bb62e0c484c1a06658ad2872463
+      typescript: 3.9.10
+    transitivePeerDependencies:
+      - '@babel/core'
+      - '@storybook/manager-webpack5'
+      - '@types/react'
+      - supports-color
+      - webpack
+      - webpack-cli
+      - webpack-command
+    dev: true
+
+  /@storybook/core/6.3.7_6b8328ae33be7bccbaedcbeca6bc1253:
+    resolution: {integrity: 
sha512-YTVLPXqgyBg7TALNxQ+cd+GtCm/NFjxr/qQ1mss1T9GCMR0IjE0d0trgOVHHLAO8jCVlK8DeuqZCCgZFTXulRw==}
+    peerDependencies:
+      '@storybook/builder-webpack5': 6.3.7
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      '@storybook/builder-webpack5':
+        optional: true
+      typescript:
+        optional: true
+    dependencies:
+      '@storybook/core-client': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
+      '@storybook/core-server': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
+      react: 16.14.0
+      react-dom: 16.14.0_react@16.14.0
+      typescript: 3.9.10
+    transitivePeerDependencies:
+      - '@babel/core'
+      - '@storybook/manager-webpack5'
+      - '@types/react'
+      - supports-color
+      - webpack
+      - webpack-cli
+      - webpack-command
+    dev: true
+
   /@storybook/core/6.3.7_f0b419a7e119055c71dcaf6063a7ba7a:
     resolution: {integrity: 
sha512-YTVLPXqgyBg7TALNxQ+cd+GtCm/NFjxr/qQ1mss1T9GCMR0IjE0d0trgOVHHLAO8jCVlK8DeuqZCCgZFTXulRw==}
     peerDependencies:
@@ -5894,6 +6792,28 @@ packages:
       - webpack-command
     dev: true
 
+  /@storybook/csf-tools/6.3.7:
+    resolution: {integrity: 
sha512-A7yGsrYwh+vwVpmG8dHpEimX021RbZd9VzoREcILH56u8atssdh/rseljyWlRes3Sr4QgtLvDB7ggoJ+XDZH7w==}
+    dependencies:
+      '@babel/generator': 7.15.0
+      '@babel/parser': 7.15.3
+      '@babel/plugin-transform-react-jsx': 7.14.9
+      '@babel/preset-env': 7.15.0
+      '@babel/traverse': 7.15.0
+      '@babel/types': 7.15.0
+      '@mdx-js/mdx': 1.6.22
+      '@storybook/csf': 0.0.1
+      core-js: 3.16.2
+      fs-extra: 9.1.0
+      js-string-escape: 1.0.1
+      lodash: 4.17.21
+      prettier: 2.2.1
+      regenerator-runtime: 0.13.9
+    transitivePeerDependencies:
+      - '@babel/core'
+      - supports-color
+    dev: true
+
   /@storybook/csf-tools/6.3.7_@babel+core@7.13.16:
     resolution: {integrity: 
sha512-A7yGsrYwh+vwVpmG8dHpEimX021RbZd9VzoREcILH56u8atssdh/rseljyWlRes3Sr4QgtLvDB7ggoJ+XDZH7w==}
     dependencies:
@@ -5944,6 +6864,63 @@ packages:
       lodash: 4.17.21
     dev: true
 
+  /@storybook/manager-webpack4/6.3.7_6b8328ae33be7bccbaedcbeca6bc1253:
+    resolution: {integrity: 
sha512-cwUdO3oklEtx6y+ZOl2zHvflICK85emiXBQGgRcCsnwWQRBZOMh+tCgOSZj4jmISVpT52RtT9woG4jKe15KBig==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@babel/core': 7.15.0
+      '@babel/plugin-transform-template-literals': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-react': 7.14.5_@babel+core@7.15.0
+      '@storybook/addons': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@storybook/core-client': 6.3.7_3c33386fd9b1d5f07f48f07869b17b73
+      '@storybook/core-common': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
+      '@storybook/node-logger': 6.3.7
+      '@storybook/theming': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@storybook/ui': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@types/node': 14.17.10
+      '@types/webpack': 4.41.30
+      babel-loader: 8.2.2_be352a5a80662835a7707f972edfcfde
+      case-sensitive-paths-webpack-plugin: 2.4.0
+      chalk: 4.1.2
+      core-js: 3.16.2
+      css-loader: 3.6.0_webpack@4.46.0
+      dotenv-webpack: 1.8.0_webpack@4.46.0
+      express: 4.17.1
+      file-loader: 6.2.0_webpack@4.46.0
+      file-system-cache: 1.0.5
+      find-up: 5.0.0
+      fs-extra: 9.1.0
+      html-webpack-plugin: 4.5.2_webpack@4.46.0
+      node-fetch: 2.6.1
+      pnp-webpack-plugin: 1.6.4_typescript@3.9.10
+      react: 16.14.0
+      react-dom: 16.14.0_react@16.14.0
+      read-pkg-up: 7.0.1
+      regenerator-runtime: 0.13.9
+      resolve-from: 5.0.0
+      style-loader: 1.3.0_webpack@4.46.0
+      telejson: 5.3.3
+      terser-webpack-plugin: 4.2.3_webpack@4.46.0
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      url-loader: 4.1.1_file-loader@6.2.0+webpack@4.46.0
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+      webpack-dev-middleware: 3.7.3_webpack@4.46.0
+      webpack-virtual-modules: 0.2.2
+    transitivePeerDependencies:
+      - '@types/react'
+      - supports-color
+      - webpack-cli
+      - webpack-command
+    dev: true
+
   /@storybook/manager-webpack4/6.3.7_8073bd74a106ff14517e8eecceb690e6:
     resolution: {integrity: 
sha512-cwUdO3oklEtx6y+ZOl2zHvflICK85emiXBQGgRcCsnwWQRBZOMh+tCgOSZj4jmISVpT52RtT9woG4jKe15KBig==}
     peerDependencies:
@@ -6001,6 +6978,61 @@ packages:
       - webpack-command
     dev: true
 
+  /@storybook/manager-webpack4/6.3.7_typescript@3.9.10:
+    resolution: {integrity: 
sha512-cwUdO3oklEtx6y+ZOl2zHvflICK85emiXBQGgRcCsnwWQRBZOMh+tCgOSZj4jmISVpT52RtT9woG4jKe15KBig==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@babel/core': 7.15.0
+      '@babel/plugin-transform-template-literals': 7.14.5_@babel+core@7.15.0
+      '@babel/preset-react': 7.14.5_@babel+core@7.15.0
+      '@storybook/addons': 6.3.7
+      '@storybook/core-client': 6.3.7_typescript@3.9.10+webpack@4.46.0
+      '@storybook/core-common': 6.3.7_typescript@3.9.10
+      '@storybook/node-logger': 6.3.7
+      '@storybook/theming': 6.3.7
+      '@storybook/ui': 6.3.7
+      '@types/node': 14.17.10
+      '@types/webpack': 4.41.30
+      babel-loader: 8.2.2_be352a5a80662835a7707f972edfcfde
+      case-sensitive-paths-webpack-plugin: 2.4.0
+      chalk: 4.1.2
+      core-js: 3.16.2
+      css-loader: 3.6.0_webpack@4.46.0
+      dotenv-webpack: 1.8.0_webpack@4.46.0
+      express: 4.17.1
+      file-loader: 6.2.0_webpack@4.46.0
+      file-system-cache: 1.0.5
+      find-up: 5.0.0
+      fs-extra: 9.1.0
+      html-webpack-plugin: 4.5.2_webpack@4.46.0
+      node-fetch: 2.6.1
+      pnp-webpack-plugin: 1.6.4_typescript@3.9.10
+      read-pkg-up: 7.0.1
+      regenerator-runtime: 0.13.9
+      resolve-from: 5.0.0
+      style-loader: 1.3.0_webpack@4.46.0
+      telejson: 5.3.3
+      terser-webpack-plugin: 4.2.3_webpack@4.46.0
+      ts-dedent: 2.2.0
+      typescript: 3.9.10
+      url-loader: 4.1.1_file-loader@6.2.0+webpack@4.46.0
+      util-deprecate: 1.0.2
+      webpack: 4.46.0
+      webpack-dev-middleware: 3.7.3_webpack@4.46.0
+      webpack-virtual-modules: 0.2.2
+    transitivePeerDependencies:
+      - '@types/react'
+      - supports-color
+      - webpack-cli
+      - webpack-command
+    dev: true
+
   /@storybook/manager-webpack4/6.3.7_typescript@4.3.5:
     resolution: {integrity: 
sha512-cwUdO3oklEtx6y+ZOl2zHvflICK85emiXBQGgRcCsnwWQRBZOMh+tCgOSZj4jmISVpT52RtT9woG4jKe15KBig==}
     peerDependencies:
@@ -6105,6 +7137,66 @@ packages:
       - webpack-command
     dev: true
 
+  /@storybook/preact/6.3.7_preact@10.5.14+typescript@3.9.10:
+    resolution: {integrity: 
sha512-mP6+e1toCd59ALUNsiJWQN0CuOVV7faaMcAs21T+GJeU5igEWbRpe/ixKdMdu7RqHA9jAHOeMZfjSNhBkvnwAw==}
+    engines: {node: '>=10.13.0'}
+    hasBin: true
+    peerDependencies:
+      '@babel/core': '*'
+      preact: ^8.0.0||^10.0.0
+      webpack: '*'
+    dependencies:
+      '@babel/plugin-transform-react-jsx': 7.14.9
+      '@storybook/addons': 6.3.7_react-dom@16.14.0+react@16.14.0
+      '@storybook/core': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
+      '@storybook/core-common': 6.3.7_6b8328ae33be7bccbaedcbeca6bc1253
+      '@types/webpack-env': 1.16.2
+      core-js: 3.16.2
+      global: 4.4.0
+      preact: 10.5.14
+      react: 16.14.0
+      react-dom: 16.14.0_react@16.14.0
+      read-pkg-up: 7.0.1
+      regenerator-runtime: 0.13.9
+      ts-dedent: 2.2.0
+    transitivePeerDependencies:
+      - '@storybook/builder-webpack5'
+      - '@storybook/manager-webpack5'
+      - '@types/react'
+      - supports-color
+      - typescript
+      - webpack-cli
+      - webpack-command
+    dev: true
+
+  /@storybook/preset-scss/1.0.3_sass-loader@10.2.0:
+    resolution: {integrity: 
sha512-o9Iz6wxPeNENrQa2mKlsDKynBfqU2uWaRP80HeWp4TkGgf7/x3DVF2O7yi9N0x/PI1qzzTTpxlQ90D62XmpiTw==}
+    peerDependencies:
+      css-loader: '*'
+      sass-loader: '*'
+      style-loader: '*'
+    dependencies:
+      sass-loader: 10.2.0_sass@1.43.2
+    dev: true
+
+  /@storybook/router/6.3.12:
+    resolution: {integrity: 
sha512-G/pNGCnrJRetCwyEZulHPT+YOcqEj/vkPVDTUfii2qgqukup6K0cjwgd7IukAURnAnnzTi1gmgFuEKUi8GE/KA==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+    dependencies:
+      '@reach/router': 1.3.4
+      '@storybook/client-logger': 6.3.12
+      '@types/reach__router': 1.3.9
+      core-js: 3.16.2
+      fast-deep-equal: 3.1.3
+      global: 4.4.0
+      lodash: 4.17.21
+      memoizerific: 1.11.3
+      qs: 6.10.1
+      ts-dedent: 2.2.0
+    dev: true
+
   /@storybook/router/6.3.7:
     resolution: {integrity: 
sha512-6tthN8op7H0NoYoE1SkQFJKC42pC4tGaoPn7kEql8XGeUJnxPtVFjrnywlTrRnKuxZKIvbilQBAwDml97XH23Q==}
     peerDependencies:
@@ -6170,6 +7262,26 @@ packages:
       regenerator-runtime: 0.13.9
     dev: true
 
+  /@storybook/theming/6.3.12:
+    resolution: {integrity: 
sha512-wOJdTEa/VFyFB2UyoqyYGaZdym6EN7RALuQOAMT6zHA282FBmKw8nL5DETHEbctpnHdcrMC/391teK4nNSrdOA==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0
+      react-dom: ^16.8.0 || ^17.0.0
+    dependencies:
+      '@emotion/core': 10.1.1
+      '@emotion/is-prop-valid': 0.8.8
+      '@emotion/styled': 10.0.27_@emotion+core@10.1.1
+      '@storybook/client-logger': 6.3.12
+      core-js: 3.16.2
+      deep-object-diff: 1.1.0
+      emotion-theming: 10.0.27_@emotion+core@10.1.1
+      global: 4.4.0
+      memoizerific: 1.11.3
+      polished: 4.1.3
+      resolve-from: 5.0.0
+      ts-dedent: 2.2.0
+    dev: true
+
   /@storybook/theming/6.3.7:
     resolution: {integrity: 
sha512-GXBdw18JJd5jLLcRonAZWvGGdwEXByxF1IFNDSOYCcpHWsMgTk4XoLjceu9MpXET04pVX51LbVPLCvMdggoohg==}
     peerDependencies:
@@ -7709,7 +8821,7 @@ packages:
   /axios/0.21.1:
     resolution: {integrity: 
sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==}
     dependencies:
-      follow-redirects: 1.14.2_debug@4.3.2
+      follow-redirects: 1.14.2
     transitivePeerDependencies:
       - debug
 
@@ -11506,7 +12618,7 @@ packages:
       readable-stream: 2.3.7
     dev: true
 
-  /follow-redirects/1.14.2_debug@4.3.2:
+  /follow-redirects/1.14.2:
     resolution: {integrity: 
sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==}
     engines: {node: '>=4.0'}
     peerDependencies:
@@ -11514,8 +12626,6 @@ packages:
     peerDependenciesMeta:
       debug:
         optional: true
-    dependencies:
-      debug: 4.3.2_supports-color@6.1.0
 
   /for-each/0.3.3:
     resolution: {integrity: 
sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
@@ -12550,7 +13660,7 @@ packages:
     engines: {node: '>=8.0.0'}
     dependencies:
       eventemitter3: 4.0.7
-      follow-redirects: 1.14.2_debug@4.3.2
+      follow-redirects: 1.14.2
       requires-port: 1.0.0
     transitivePeerDependencies:
       - debug
@@ -16025,6 +17135,15 @@ packages:
     resolution: {integrity: 
sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==}
     dev: true
 
+  /pnp-webpack-plugin/1.6.4_typescript@3.9.10:
+    resolution: {integrity: 
sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==}
+    engines: {node: '>=6'}
+    dependencies:
+      ts-pnp: 1.2.0_typescript@3.9.10
+    transitivePeerDependencies:
+      - typescript
+    dev: true
+
   /pnp-webpack-plugin/1.6.4_typescript@4.3.5:
     resolution: {integrity: 
sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==}
     engines: {node: '>=6'}
@@ -16038,7 +17157,7 @@ packages:
     resolution: {integrity: 
sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==}
     engines: {node: '>=6'}
     dependencies:
-      ts-pnp: 1.2.0_typescript@4.4.3
+      ts-pnp: 1.2.0_typescript@4.3.5
     transitivePeerDependencies:
       - typescript
     dev: true
@@ -19791,7 +20910,7 @@ packages:
     resolution: {integrity: 
sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==}
     dev: true
 
-  /ts-pnp/1.2.0_typescript@4.3.5:
+  /ts-pnp/1.2.0_typescript@3.9.10:
     resolution: {integrity: 
sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==}
     engines: {node: '>=6'}
     peerDependencies:
@@ -19800,10 +20919,10 @@ packages:
       typescript:
         optional: true
     dependencies:
-      typescript: 4.3.5
+      typescript: 3.9.10
     dev: true
 
-  /ts-pnp/1.2.0_typescript@4.4.3:
+  /ts-pnp/1.2.0_typescript@4.3.5:
     resolution: {integrity: 
sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==}
     engines: {node: '>=6'}
     peerDependencies:
@@ -19812,7 +20931,7 @@ packages:
       typescript:
         optional: true
     dependencies:
-      typescript: 4.4.3
+      typescript: 4.3.5
     dev: true
 
   /tsconfig-paths/3.9.0:

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]