summaryrefslogtreecommitdiff
path: root/storybook
diff options
context:
space:
mode:
Diffstat (limited to 'storybook')
-rw-r--r--storybook/index.ts4
-rw-r--r--storybook/storybook-registry.ts10
-rw-r--r--storybook/storybook.tsx31
-rw-r--r--storybook/toggle-storybook.tsx51
-rw-r--r--storybook/toggle-storybook.web.tsx30
-rw-r--r--storybook/views/index.ts3
-rw-r--r--storybook/views/story-screen.tsx15
-rw-r--r--storybook/views/story.tsx16
-rw-r--r--storybook/views/use-case.tsx69
9 files changed, 229 insertions, 0 deletions
diff --git a/storybook/index.ts b/storybook/index.ts
new file mode 100644
index 0000000..4a0399a
--- /dev/null
+++ b/storybook/index.ts
@@ -0,0 +1,4 @@
+// this is the native storybook entry point
+// import { StorybookUI } from "./config"
+
+export * from "./storybook"
diff --git a/storybook/storybook-registry.ts b/storybook/storybook-registry.ts
new file mode 100644
index 0000000..83f0ed8
--- /dev/null
+++ b/storybook/storybook-registry.ts
@@ -0,0 +1,10 @@
+require("../app/components/text/text.story")
+require("../app/components/auto-image/auto-image.story")
+require("../app/components/button/button.story")
+require("../app/components/form-row/form-row.story")
+require("../app/components/switch/switch.story")
+require("../app/components/text-field/text-field.story")
+require("../app/components/checkbox/checkbox.story")
+require("../app/components/wallpaper/wallpaper.story")
+require("../app/components/icon/icon.story")
+require("../app/components/header/header.story")
diff --git a/storybook/storybook.tsx b/storybook/storybook.tsx
new file mode 100644
index 0000000..0479d4e
--- /dev/null
+++ b/storybook/storybook.tsx
@@ -0,0 +1,31 @@
+import React, { useEffect } from "react"
+import { getStorybookUI, configure } from "@storybook/react-native"
+import { initFonts } from "../app/theme/fonts"
+
+declare let module
+
+configure(() => {
+ require("./storybook-registry")
+}, module)
+
+const StorybookUI = getStorybookUI({
+ port: 9001,
+ host: "localhost",
+ onDeviceUI: true,
+ asyncStorage: require("@react-native-async-storage/async-storage").default || null,
+})
+
+export function StorybookUIRoot() {
+ useEffect(() => {
+ ;(async () => {
+ await initFonts() // expo only
+ if (typeof __TEST__ === "undefined" || !__TEST__) {
+ const Reactotron = require("../app/services/reactotron")
+ const reactotron = new Reactotron.Reactotron()
+ reactotron.setup()
+ }
+ })()
+ }, [])
+
+ return <StorybookUI />
+}
diff --git a/storybook/toggle-storybook.tsx b/storybook/toggle-storybook.tsx
new file mode 100644
index 0000000..394ecf4
--- /dev/null
+++ b/storybook/toggle-storybook.tsx
@@ -0,0 +1,51 @@
+import React, { useState, useEffect } from "react"
+import { DevSettings } from "react-native"
+import { loadString, saveString } from "../app/utils/storage"
+
+/**
+ * Toggle Storybook mode, in __DEV__ mode only.
+ *
+ * In non-__DEV__ mode, or when Storybook isn't toggled on,
+ * renders its children.
+ *
+ * The mode flag is persisted in async storage, which means it
+ * persists across reloads/restarts - this is handy when developing
+ * new components in Storybook.
+ */
+export function ToggleStorybook(props) {
+ const [showStorybook, setShowStorybook] = useState(false)
+ const [StorybookUIRoot, setStorybookUIRoot] = useState(null)
+
+ useEffect(() => {
+ if (__DEV__ && DevSettings) {
+ // Load the setting from storage if it's there
+ loadString("devStorybook").then((storedSetting) => {
+ // Set the initial value
+ setShowStorybook(storedSetting === "on")
+
+ // Add our toggle command to the menu
+ DevSettings.addMenuItem("Toggle Storybook", () => {
+ setShowStorybook((show) => {
+ // On toggle, flip the current value
+ show = !show
+
+ // Write it back to storage
+ saveString("devStorybook", show ? "on" : "off")
+
+ // Return it to change the local state
+ return show
+ })
+ })
+
+ // Load the storybook UI once
+ setStorybookUIRoot(() => require("./storybook").StorybookUIRoot)
+ })
+ }
+ }, [])
+
+ if (showStorybook) {
+ return StorybookUIRoot ? <StorybookUIRoot /> : null
+ } else {
+ return props.children
+ }
+}
diff --git a/storybook/toggle-storybook.web.tsx b/storybook/toggle-storybook.web.tsx
new file mode 100644
index 0000000..f1bd034
--- /dev/null
+++ b/storybook/toggle-storybook.web.tsx
@@ -0,0 +1,30 @@
+import React, { useState, useEffect } from "react"
+import * as QueryString from "query-string"
+
+interface StorybookQueryParams {
+ storybook?: boolean
+}
+
+export const ToggleStorybook = (props) => {
+ const [StorybookUIRoot, setStorybookUIRoot] = useState<any>(null)
+ const [queryParams, setQueryParams] = useState<StorybookQueryParams>({})
+
+ useEffect(() => {
+ if (__DEV__) {
+ // Load the storybook UI once
+ setStorybookUIRoot(() => require("./storybook").StorybookUIRoot)
+ }
+ }, [])
+
+ useEffect(() => {
+ if (__DEV__) {
+ setQueryParams(QueryString.parse(window.location.search))
+ }
+ }, [window.location.search])
+
+ if (queryParams?.storybook) {
+ return StorybookUIRoot ? <StorybookUIRoot /> : null
+ } else {
+ return props.children
+ }
+}
diff --git a/storybook/views/index.ts b/storybook/views/index.ts
new file mode 100644
index 0000000..a722e53
--- /dev/null
+++ b/storybook/views/index.ts
@@ -0,0 +1,3 @@
+export * from "./story-screen"
+export * from "./story"
+export * from "./use-case"
diff --git a/storybook/views/story-screen.tsx b/storybook/views/story-screen.tsx
new file mode 100644
index 0000000..d83f6f5
--- /dev/null
+++ b/storybook/views/story-screen.tsx
@@ -0,0 +1,15 @@
+import * as React from "react"
+import { ViewStyle, KeyboardAvoidingView, Platform } from "react-native"
+
+const ROOT: ViewStyle = { backgroundColor: "#f0f0f0", flex: 1 }
+
+export interface StoryScreenProps {
+ children?: React.ReactNode
+}
+
+const behavior = Platform.OS === "ios" ? "padding" : undefined
+export const StoryScreen = (props: StoryScreenProps) => (
+ <KeyboardAvoidingView style={ROOT} behavior={behavior} keyboardVerticalOffset={50}>
+ {props.children}
+ </KeyboardAvoidingView>
+)
diff --git a/storybook/views/story.tsx b/storybook/views/story.tsx
new file mode 100644
index 0000000..c85f7f0
--- /dev/null
+++ b/storybook/views/story.tsx
@@ -0,0 +1,16 @@
+import * as React from "react"
+import { ScrollView, View, ViewStyle } from "react-native"
+
+export interface StoryProps {
+ children?: React.ReactNode
+}
+
+const ROOT: ViewStyle = { flex: 1 }
+
+export function Story(props: StoryProps) {
+ return (
+ <View style={ROOT}>
+ <ScrollView keyboardShouldPersistTaps="handled">{props.children}</ScrollView>
+ </View>
+ )
+}
diff --git a/storybook/views/use-case.tsx b/storybook/views/use-case.tsx
new file mode 100644
index 0000000..08b04b9
--- /dev/null
+++ b/storybook/views/use-case.tsx
@@ -0,0 +1,69 @@
+import * as React from "react"
+import { View, Text, TextStyle, ViewStyle } from "react-native"
+
+const ROOT: ViewStyle = { backgroundColor: "#eee" }
+const TITLE: TextStyle = { fontWeight: "600", color: "#3d3d3d" }
+const TITLE_WRAPPER: ViewStyle = {}
+const USE_CASE_WRAPPER: ViewStyle = {
+ position: "absolute",
+ top: 0,
+ left: 0,
+ right: 0,
+ borderTopColor: "#e6e6e6",
+ borderTopWidth: 1,
+ flexDirection: "row",
+}
+const USE_CASE: TextStyle = {
+ fontSize: 10,
+ color: "#666",
+ paddingHorizontal: 4,
+ paddingBottom: 2,
+}
+const USAGE: TextStyle = { color: "#666", fontSize: 10, paddingTop: 0 }
+const HEADER: ViewStyle = {
+ paddingTop: 20,
+ paddingBottom: 10,
+ paddingHorizontal: 10,
+ borderBottomColor: "#e6e6e6",
+ borderBottomWidth: 1,
+}
+const COMPONENT: ViewStyle = { backgroundColor: "#fff" }
+
+export interface UseCaseProps {
+ /** The title. */
+ text: string
+ /** When should we be using this? */
+ usage?: string
+ /** The component use case. */
+ children: React.ReactNode
+ /** A style override. Rarely used. */
+ style?: ViewStyle
+ /** Don't use any padding because it's important to see the spacing. */
+ noPad?: boolean
+ /** Don't use background color because it's important to see the color. */
+ noBackground?: boolean
+}
+
+export function UseCase(props: UseCaseProps) {
+ const style: ViewStyle = {
+ ...COMPONENT,
+ ...{ padding: props.noPad ? 0 : 10 },
+ ...{ backgroundColor: props.noBackground ? "rgba(0,0,0,0)" : COMPONENT.backgroundColor },
+ ...props.style,
+ }
+
+ return (
+ <View style={ROOT}>
+ <View style={HEADER}>
+ <View style={USE_CASE_WRAPPER}>
+ <Text style={USE_CASE}>Use Case</Text>
+ </View>
+ <View style={TITLE_WRAPPER}>
+ <Text style={TITLE}>{props.text}</Text>
+ </View>
+ {props.usage ? <Text style={USAGE}>{props.usage}</Text> : null}
+ </View>
+ <View style={style}>{props.children}</View>
+ </View>
+ )
+}