Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove react-spring, and replace it with reanimated #49

Merged
merged 4 commits into from
Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/publish-canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: "yarn"
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
run: git fetch --unshallow --tags
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: "yarn"
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ dist
android/app/src/main/assets/fonts/*
ios/PaletteMobile/fonts/*

.cache


#########################################################
# Keep this rule last.
Expand Down
2 changes: 2 additions & 0 deletions .storybook/storybook.requires.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ const getStories = () => {
require("../lib/atoms/Spacer/Spacer.stories.tsx"),
require("../lib/colors.stories.tsx"),
require("../lib/elements/Avatar/Avatar.stories.tsx"),
require("../lib/elements/Button/Button.stories.tsx"),
require("../lib/elements/Checkbox/Checkbox.stories.tsx"),
require("../lib/elements/Collapse/Collapse.stories.tsx"),
require("../lib/elements/Input/Input.stories.tsx"),
require("../lib/elements/Separator/Separator.stories.tsx"),
require("../lib/elements/Skeleton/Skeleton.stories.tsx"),
Expand Down
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
ruby 2.7.5
nodejs 16.10.0
nodejs 18.13.0
7 changes: 5 additions & 2 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
const plugins = [
["@babel/plugin-proposal-private-methods", { loose: true }],
"react-native-reanimated/plugin", // should be LAST
]

const presets = [
[
"module:metro-react-native-babel-preset",
Expand All @@ -7,6 +12,4 @@ const presets = [
["@babel/preset-react", { runtime: "automatic" }], // this is so `import React from "react"` is not needed.
]

const plugins = ["react-native-reanimated/plugin"]

module.exports = { presets, plugins }
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
global.__TEST__ = false

import { AppRegistry } from "react-native"
import { App } from "./src/App"
import { name as appName } from "./app.json"
Expand Down
8 changes: 4 additions & 4 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ PODS:
- React-jsinspector (0.70.6)
- React-logger (0.70.6):
- glog
- react-native-flipper (0.176.1):
- react-native-flipper (0.177.0):
- React-Core
- react-native-safe-area-context (4.4.1):
- RCT-Folly
Expand Down Expand Up @@ -382,7 +382,7 @@ PODS:
- React-Core
- RNReactNativeHapticFeedback (1.14.0):
- React-Core
- RNReanimated (2.13.0):
- RNReanimated (2.14.4):
- DoubleConversion
- FBLazyVector
- FBReactNativeSpec
Expand Down Expand Up @@ -622,7 +622,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: b4a65947391c658450151275aa406f2b8263178f
React-jsinspector: 60769e5a0a6d4b32294a2456077f59d0266f9a8b
React-logger: 1623c216abaa88974afce404dc8f479406bbc3a0
react-native-flipper: 7e4b1c3fe1a2eecbe7304e5ff6b89231b3ec61dc
react-native-flipper: ccf9059793e4b36cb4e6e5e54208a5e01acba248
react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a
React-perflogger: 8c79399b0500a30ee8152d0f9f11beae7fc36595
React-RCTActionSheet: 7316773acabb374642b926c19aef1c115df5c466
Expand All @@ -638,7 +638,7 @@ SPEC CHECKSUMS:
ReactCommon: 349be31adeecffc7986a0de875d7fb0dcf4e251c
RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60
RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c
RNReanimated: ce445c233a6ff5600223484a88ad5704945d972a
RNReanimated: 6668b0587bebd4b15dd849b99e5a9c70fc12ed95
RNSVG: d787d64ca06b9158e763ad2638a8c4edce00782a
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: 99caf8d5ab45e9d637ee6e0174ec16fbbb01bcfc
Expand Down
23 changes: 23 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = {
cacheDirectory: ".cache/jest",
moduleFileExtensions: ["ts", "tsx", "js"],
preset: "react-native",
rootDir: ".",
setupFilesAfterEnv: [
"jest-extended",
"@testing-library/jest-native/extend-expect",
"./lib/setupJest.ts",
],
testMatch: ["<rootDir>/lib/**/*.tests.(ts|tsx|js)"],
testEnvironment: "node",
testEnvironmentOptions: {
url: "http://localhost/",
},
transform: {
".*(ts|tsx|js|jsx)$": "babel-jest",
},
transformIgnorePatterns: [
"node_modules/(?!(react-native(-.*)?/(@react-native-community/.*))?|react-navigation|@react-navigation/.*)",
],
watchPlugins: ["jest-watch-typeahead/filename", "jest-watch-typeahead/testname"],
}
1 change: 1 addition & 0 deletions lib/Theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const Theme = ({
return <ThemeProvider theme={actualTheme}>{children}</ThemeProvider>
}

// TODO: make this stricter for types. only allow ColorStrict.
export interface ColorFuncOverload {
(colorNumber: undefined): undefined
(colorNumber: Color): string
Expand Down
211 changes: 211 additions & 0 deletions lib/elements/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { Button as RNButton } from "react-native"
import { useState } from "react"
import { Button, ButtonProps, CTAButton, FollowButton, LinkButton } from "."
import { Box, Flex, Spacer } from "../../atoms"
import { DataList, List } from "../../storybookHelpers"
import { BellIcon, LinkIcon } from "../../svgs"
import { Wrap } from "../../utils/Wrap"
import { NoUndefined } from "../../utils/types"
import { capitalize } from "lodash"
import { LinkText } from ".."

const sizes: Array<NoUndefined<ButtonProps["size"]>> = ["small", "large"]
const variants: Array<NoUndefined<ButtonProps["variant"]>> = [
"fillDark",
"fillLight",
"fillGray",
"fillSuccess",
"outline",
"outlineGray",
"outlineLight",
"text",
]

export default {
title: "Button",
component: Button,
}

export const Sizes = () => (
<DataList
data={sizes}
renderItem={({ item: size }) => (
<Button size={size} onPress={() => console.log(`tapped ${size}`)}>
{capitalize(size)}
</Button>
)}
/>
)

export const States = () => {
const [variant, setVariant] = useState<NoUndefined<ButtonProps["variant"]>>("fillDark")
return (
<List>
<Flex flexDirection="row" flexWrap="wrap" px="2">
{variants.map((variant) => (
<LinkText color="orange" onPress={() => setVariant(variant)} mr="2">
{variant}
</LinkText>
))}
</Flex>
<Button variant={variant} onPress={() => console.log(`tapped`)} longestText="Regular YEA">
Regular
</Button>
<Button variant={variant} onPress={() => console.log(`tapped`)} disabled>
Disabled
</Button>
<Button variant={variant} onPress={() => console.log(`tapped`)} loading>
Loading
</Button>
<Button variant={variant} onPress={() => console.log(`tapped`)} testOnly_pressed>
Pressed
</Button>
</List>
)
}

export const Variants = () => (
<DataList
data={variants}
renderItem={({ item: variant }) => (
<Wrap if={variant === "outlineLight" || variant === "fillLight"}>
<Flex backgroundColor="pink" p={10}>
<Wrap.Content>
<Button variant={variant} onPress={() => console.log(`tapped ${variant}`)}>
{variant}
</Button>
</Wrap.Content>
</Flex>
</Wrap>
)}
/>
)

export const VariantsLoading = () => (
<DataList
data={variants}
renderItem={({ item: variant }) => (
<Button variant={variant} loading onPress={() => console.log(`tapped ${variant}`)}>
{variant}
</Button>
)}
/>
)

export const VariantsDisabled = () => (
<DataList
data={variants}
renderItem={({ item: variant }) => (
<Wrap if={variant === "outlineLight"}>
<Flex backgroundColor="black100" p={10}>
<Wrap.Content>
<Button variant={variant} disabled onPress={() => console.log(`tapped ${variant}`)}>
{variant}
</Button>
</Wrap.Content>
</Flex>
</Wrap>
)}
/>
)

export const TheFollowButton = () => {
const [follow, setFollow] = useState(true)

return (
<List>
<FollowButton isFollowed={follow} onPress={() => setFollow((v) => !v)} />
</List>
)
}

export const TheCTAButton = () => (
<List>
<CTAButton onPress={() => console.log("pressed")}>cta button</CTAButton>
</List>
)

export const TheLinkButton = () => (
<List>
<LinkButton onPress={() => console.log("pressed")}>LinkButton</LinkButton>
</List>
)

export const Miscellaneous = () => (
<List>
<Button loading disabled>
loading and disabled
</Button>
<Button block>block</Button>
<Flex
backgroundColor="orange"
width={400}
height={80}
alignItems="center"
justifyContent="center"
>
<Button variant="fillLight" icon={<LinkIcon />}>
left icon
</Button>
</Flex>
<Button icon={<LinkIcon fill="white100" />} iconPosition="right">
right icon
</Button>
<Button size="small" icon={<LinkIcon fill="white100" />} iconPosition="right">
Right Icon Small
</Button>
<Button
variant="fillDark"
size="small"
icon={<BellIcon fill="white100" width="16px" height="16px" />}
>
Create Alert
</Button>
<Box flexDirection="row">
<Box width={2} height="100%" backgroundColor="green100" />
<Box>
<Button
size="small"
icon={<LinkIcon fill="white100" />}
iconPosition="right"
longestText="this is a very long text"
>
shortest text
</Button>
<Spacer y="1" />
<Button
size="small"
icon={<LinkIcon fill="white100" />}
iconPosition="right"
longestText="this is a very long text"
>
this is a very long text
</Button>
</Box>
<Box width={2} height="100%" backgroundColor="green100" />
</Box>
<Button icon={<LinkIcon fill="white100" />} block iconPosition="left-start">
left-start aligned icon
</Button>
</List>
)

export const Playground = () => {
const [loading, setLoading] = useState(false)
const [disabled, setDisabled] = useState(true)
const [block, setBlock] = useState(false)

return (
<>
<RNButton title="loading" onPress={() => setLoading((v) => !v)} />
<RNButton title="disabled" onPress={() => setDisabled((v) => !v)} />
<RNButton title="block" onPress={() => setBlock((v) => !v)} />
<List>
<Button loading={loading} disabled={disabled} block={block}>
loading {loading ? "true" : "false"}, disabled {disabled ? "true" : "false"}, block{" "}
{block ? "true" : "false"}
</Button>
</List>
</>
)
}
53 changes: 53 additions & 0 deletions lib/elements/Button/Button.tests.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { act, fireEvent, screen } from "@testing-library/react-native"
import { Button } from "."
import { Spinner } from ".."
import { renderWithWrappers } from "../../utils/tests/renderWithWrappers"

describe("Button", () => {
it("shows spinner if loading is true", () => {
const { UNSAFE_queryAllByType } = renderWithWrappers(<Button loading>wow</Button>)
expect(UNSAFE_queryAllByType(Spinner)).toHaveLength(1)
})

it("invokes the onClick callback", () => {
const onPress = jest.fn()

const { getByTestId } = renderWithWrappers(
<Button testID="the-button" onPress={onPress}>
wow
</Button>
)

fireEvent.press(getByTestId("the-button"))

expect(onPress).toHaveBeenCalled()
})

it("does not invoke the onClick callback if loading is true", () => {
const onPress = jest.fn()

const { getByTestId } = renderWithWrappers(
<Button testID="the-button" onPress={onPress} loading>
wow
</Button>
)

fireEvent.press(getByTestId("the-button"))

expect(onPress).not.toHaveBeenCalled()
})

it("does not invoke the onClick callback if disabled is true", () => {
const onPress = jest.fn()

const { getByTestId } = renderWithWrappers(
<Button testID="the-button" onPress={onPress} disabled>
wow
</Button>
)

fireEvent.press(getByTestId("the-button"))

expect(onPress).not.toHaveBeenCalled()
})
})
Loading