Skip to content

Commit

Permalink
[improvement]
Browse files Browse the repository at this point in the history
1. change Props naming
2. changed behavior
	 Previously, only the transparency of the button was adjusted depending on the state but now the actual position is adjusted.
3. Change state management.
	Previously, the active was managed as a "state", modified to manage it as a "props".
4.  path name changed
	FloatingActionButtonWrapper> FAB
  • Loading branch information
Juyeong-Byeon committed Sep 7, 2021
1 parent 0982887 commit 6bddf3d
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 135 deletions.
128 changes: 128 additions & 0 deletions main/FAB/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import {Animated, Easing, StyleProp, View, ViewStyle} from 'react-native';
import {ButtonSize, IconButton} from '../IconButton';
import {DoobooTheme, withTheme} from '../theme';
import {Icon, IconName} from '../Icon';
import React, {ReactElement, useEffect, useRef, useState} from 'react';

import styled from '@emotion/native';

export const StyledIcon = styled(Icon)`
color: ${({theme}) => theme.textContrast};
`;

const FABItemWrapper = styled.View`
margin: 10px;
`;

export interface FABItem {
icon: IconName;
id: string;
}

export interface FABProps<Item extends FABItem> {
isActive: boolean;
ItemList: Item[];
onPressFAB: () => void;
onPressListItem: (item?: Item) => void;
renderFAB?: () => ReactElement;
renderFabItem?: (item: Item, idx: number) => ReactElement;
size: ButtonSize;
style?: StyleProp<ViewStyle>;
}

function FloatingActionButtons<Item extends FABItem = FABItem>({
isActive,
theme,
ItemList,
onPressFAB,
onPressListItem,
renderFAB,
renderFabItem,
size = 'large',
style,
}: FABProps<Item> & {
theme: DoobooTheme;
}): ReactElement {
const fadeAnim = useRef(new Animated.Value(0));

useEffect(() => {
return Animated.timing(fadeAnim.current, {
toValue: isActive ? 1 : 0,
useNativeDriver: true,
easing: Easing.quad,
duration: 200,
}).start();
}, [fadeAnim, isActive]);

useEffect(() => {
Animated.timing(fadeAnim.current, {
toValue: 1,
duration: 200,
easing: Easing.linear,
useNativeDriver: true,
}).start();
}, [fadeAnim]);

return (
<View
style={[
{
position: 'absolute',
right: 10,
bottom: 10,
zIndex: 999,
flex: 1,
},
style,
]}>
<Animated.View>
{isActive &&
ItemList.map((item, idx) => {
return (
<FABItemWrapper
key={item.id}
style={{
position: 'absolute',
transform: [{translateY: -80 * (idx + 1)}],
}}>
{renderFabItem ? (
renderFabItem(item, idx)
) : (
<IconButton
testID={item.id}
size={size}
icon={
<StyledIcon theme={theme} size={24} name={item.icon} />
}
onPress={() => onPressListItem(item)}
/>
)}
</FABItemWrapper>
);
})}
</Animated.View>
<FABItemWrapper>
<Animated.View>
{renderFAB ? (
renderFAB()
) : (
<IconButton
testID={'main_fab'}
size={size}
icon={
isActive ? (
<StyledIcon size={24} name="cross-light" />
) : (
<StyledIcon size={24} name="add-light" />
)
}
onPress={onPressFAB}
/>
)}
</Animated.View>
</FABItemWrapper>
</View>
);
}

export const FAB = withTheme(FloatingActionButtons);
120 changes: 0 additions & 120 deletions main/FloatingActionButtonWrapper/index.tsx

This file was deleted.

38 changes: 30 additions & 8 deletions main/__tests__/FAB.test.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,54 @@
import {FAB, FABItem, FABProps} from '../../main';
import {fireEvent, render} from '@testing-library/react-native';
import React, {ReactElement} from 'react';
import {RenderAPI, fireEvent, render} from '@testing-library/react-native';

import {ReactElement} from 'react';
import {IconButton} from '../IconButton';
import {View} from 'react-native';
import {createComponent} from '../../test/testUtils';

const Component = (props: FABProps<FABItem>): ReactElement =>
createComponent(<FAB {...props} />);

describe('[FAB]', () => {
it('test mainFAB onPress callback', async () => {
it('should render', async () => {
let count = 0;
let item1: FABItem = {icon: 'bell-solid', id: 'item1'};
let item: FABItem = {icon: 'bell-solid', id: 'item1'};
let resItem: FABItem;

const {getByTestId} = render(
Component({
ButtonList: [item1],
ItemList: [item],
isActive: true,
size: 'large',
onPressListItem: (item1) => {
onPressListItem: (item) => {
count += 1;
resItem = item1;
resItem = item;
},
onPressFAB: () => {},
}),
);

expect(count).toBe(0);
fireEvent.press(getByTestId('item1'));
expect(count).toBe(1);
expect(resItem.id).toBe(item1.id);
expect(resItem.id).toBe(item.id);
});

it('should render customFAB', async () => {
const testingLib = render(
Component({
ItemList: [{icon: 'bell-solid', id: 'item1'}],
isActive: true,
size: 'large',
onPressListItem: (item1) => {},
onPressFAB: () => {},
renderFAB: () => <View />,
renderFabItem: (item, idx) => <View />,
}),
);

const json = testingLib.toJSON();

expect(json).toBeTruthy();
});
});
2 changes: 1 addition & 1 deletion main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export * from './Accordion';
export * from './StatusBarBrightness';
export * from './SwitchToggle';
export * from './theme';
export * from './FloatingActionButtonWrapper';
export * from './FAB';
13 changes: 7 additions & 6 deletions stories/dooboo-ui/FloatingActionButton/FABStory.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {FC} from 'react';
import React, {FC, useState} from 'react';
import {SafeAreaView, View} from 'react-native';
import {useTheme, withTheme} from '../../../main/theme/ThemeProvider';

Expand All @@ -13,7 +13,7 @@ const StoryContainer = styled.View`
`;

const FABContainer: FC = () => {
const {theme} = useTheme();
const [active, setActive] = useState<boolean>(false);

const [fontsLoaded] = useFonts({
IcoMoon: require('../../../main/Icon/doobooui.ttf'),
Expand All @@ -23,16 +23,17 @@ const FABContainer: FC = () => {

return (
<StoryContainer>
<SafeAreaView style={{width: '100%', height: '100%'}}>
<SafeAreaView style={{display: 'flex', width: '100%', height: '100%'}}>
<FAB
size="medium"
theme={theme}
ButtonList={[
isActive={active}
onPressFAB={() => setActive((prev) => !prev)}
ItemList={[
{id: 'search', icon: 'home-light'},
{id: 'like', icon: 'like-light'},
]}
onPressListItem={(item) => {
console.log(item.id);
console.log(item);
}}
/>
</SafeAreaView>
Expand Down

0 comments on commit 6bddf3d

Please sign in to comment.