Skip to content

Commit

Permalink
Merge pull request #99 from GetLuko/sami/feat/buttonsBar
Browse files Browse the repository at this point in the history
Feat : Add ButtonBar component
  • Loading branch information
hcourthias authored Aug 14, 2023
2 parents 995d05b + 6e7fb83 commit f4bae55
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 2 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/sandbox/e2e/visual_regressions_flow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ appId: ${APPID}
file: subflow/takeScreenshot.yaml
env:
COMPONENT: Button
- runFlow:
file: subflow/takeScreenshot.yaml
env:
COMPONENT: ButtonBar
- runFlow:
file: subflow/takeScreenshot.yaml
env:
Expand Down
49 changes: 49 additions & 0 deletions packages/sandbox/src/app/sandbox/docs/button-bar.doc.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Box, ButtonBar, ButtonProps } from '@getluko/streamline';
import React from 'react';

const buttonsArray: ButtonProps[] = [
{
text: 'One',
onPress: () => console.log('onPress One'),
iconName: 'Area',
size: 'mini',
},
{
text: 'Two',
onPress: () => console.log('onPress Two'),
iconName: 'Area',
size: 'mini',
},
{
text: 'Three',
onPress: () => console.log('onPress Three'),
iconName: 'Area',
size: 'mini',
},
{
text: 'Four',
onPress: () => console.log('onPress Four'),
iconName: 'Area',
size: 'mini',
},
{
text: 'Five',
onPress: () => console.log('onPress Five'),
iconName: 'Area',
size: 'mini',
},
];

export const ButtonBarSandbox = () => {
return (
<Box>
<ButtonBar buttons={buttonsArray.slice(0, 1)} />
<ButtonBar buttons={buttonsArray.slice(0, 2)} />
<ButtonBar buttons={buttonsArray.slice(0, 3)} />
<ButtonBar buttons={buttonsArray.slice(0, 4)} />
<ButtonBar buttons={buttonsArray.slice(0, 5)} />
<ButtonBar buttons={buttonsArray.slice(0, 5)} isSkeleton />
<ButtonBar buttons={[]} />
</Box>
);
};
6 changes: 4 additions & 2 deletions packages/sandbox/src/app/sandbox/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ButtonBarSandbox } from './docs/button-bar.doc';
import { ButtonDockSandbox } from './docs/button-dock.doc';
import { ButtonIconSandbox } from './docs/button-icon.doc';
import { ButtonMiniSandbox } from './docs/button-mini.doc';
Expand All @@ -22,7 +23,7 @@ import { ListItemValueSandbox } from './docs/list-item-value.doc';
import { ListItemSandbox } from './docs/list-item.doc';
import { MarkdownSandbox } from './docs/markdown.doc';
import { NavigationBarProgressSandbox } from './docs/navigation-bar-progress.doc';
import {NavigationBarTrailSandbox} from "./docs/navigation-bar-trail.doc";
import { NavigationBarTrailSandbox } from './docs/navigation-bar-trail.doc';
import { NavigationTitleSandbox } from './docs/navigation-title.doc';
import { ProgressBarSandbox } from './docs/progress-bar.doc';
import { RadioSandbox } from './docs/radio.doc';
Expand Down Expand Up @@ -58,6 +59,7 @@ export const sandboxItems: SandBoxSectionType[] = [
{
title: 'Buttons',
items: [
{ title: 'ButtonBar', SandBox: ButtonBarSandbox },
{ title: 'Button', SandBox: ButtonSandbox },
{ title: 'ButtonIcon', SandBox: ButtonIconSandbox },
{ title: 'ButtonMini', SandBox: ButtonMiniSandbox },
Expand Down Expand Up @@ -118,7 +120,7 @@ export const sandboxItems: SandBoxSectionType[] = [
SandBox: NavigationBarProgressSandbox,
},
{ title: 'NavigationTitle', SandBox: NavigationTitleSandbox },
{ title: 'NavigationBarTrail', SandBox: NavigationBarTrailSandbox }
{ title: 'NavigationBarTrail', SandBox: NavigationBarTrailSandbox },
],
},
{
Expand Down
55 changes: 55 additions & 0 deletions packages/streamline/src/components/button-bar/button-bar.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { fireEvent } from '@testing-library/react-native';
import React from 'react';

import { renderWithProvider } from '../../testing/render-with-provider';
import { ButtonProps } from '../../types';
import { Button } from '../buttons/button/button';
import { ButtonBar } from './button-bar';

describe('ButtonBar', () => {
const buttons: ButtonProps[] = [
{ text: 'Button 1', iconName: 'Area', size: 'mini', onPress: jest.fn() },
{ text: 'Button 2', iconName: 'Area', size: 'mini', onPress: jest.fn() },
];

it('renders correctly with buttons', () => {
const { getByText } = renderWithProvider(<ButtonBar buttons={buttons} />);

buttons.forEach((button) => {
expect(getByText(button.text)).toBeTruthy();
});
});

it('fires the onPress function when a button is clicked', () => {
const { getByText } = renderWithProvider(<ButtonBar buttons={buttons} />);
const buttonToClick = getByText('Button 1');
fireEvent.press(buttonToClick);

expect(buttons[0].onPress).toHaveBeenCalled();
});

it('should render skeleton items when isSkeleton prop is true', () => {
// It is safe when it is used for props test
// https://github.com/callstack/react-native-testing-library/issues/427#issuecomment-654405308
const { UNSAFE_getAllByType } = renderWithProvider(
<ButtonBar buttons={[]} isSkeleton={true} testID="ButtonBar" />
);

const buttons = UNSAFE_getAllByType(Button);

expect(buttons.length).toBe(5);

buttons.forEach((button) => {
expect(button.props).toHaveProperty('isSkeleton', true);
});
});

it('does not scroll when isSkeleton is true', () => {
const { getByTestId } = renderWithProvider(
<ButtonBar buttons={[]} isSkeleton testID="ButtonBar" />
);
const scrollView = getByTestId('ButtonBar_container');

expect(scrollView.props).toHaveProperty('scrollEnabled', false);
});
});
51 changes: 51 additions & 0 deletions packages/streamline/src/components/button-bar/button-bar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { ScrollView } from 'react-native';

import { Box } from '../../primitives/box/box';
import { useStreamlineTheme } from '../../theme';
import { Button } from '../buttons/button/button';
import { ButtonProps } from '../buttons/button/button.types';

type Props = {
buttons: ButtonProps[];
isSkeleton?: boolean;
testID?: string;
};

export const ButtonBar = ({ buttons, isSkeleton = false, testID }: Props) => {
const { spacing } = useStreamlineTheme();

const skeletonItems: ButtonProps[] = Array(5)
.fill(0)
.map((_, index) => ({
iconName: 'Area',
text: `Skeleton${index}`,
size: 'mini',
}));

const buttonMenu =
buttons.length === 0 && isSkeleton ? skeletonItems : buttons;

return (
<ScrollView
testID={testID ? `${testID}_container` : undefined}
scrollEnabled={!isSkeleton}
horizontal={true}
showsHorizontalScrollIndicator={false}
contentContainerStyle={{ padding: spacing.md, flexDirection: 'row' }}
>
{buttonMenu.map((button, index) => (
<Box key={button.text} marginRight="md">
<Button
testID={testID ? `${testID}_button_${index}` : undefined}
appearance="secondary"
{...button}
isSkeleton={isSkeleton}
/>
</Box>
))}
</ScrollView>
);
};

export default ButtonBar;
1 change: 1 addition & 0 deletions packages/streamline/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export * from './components/switch/switch';
export * from './components/radio/radio';
export * from './components/spinner/spinner';
export * from './components/tag/tag';
export * from './components/button-bar/button-bar';
export * from './primitives/animated-box/animated-box';
export * from './primitives/box/box';
export * from './primitives/card/card';
Expand Down
1 change: 1 addition & 0 deletions packages/streamline/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { IconsName } from './primitives/icon/icon.types';
export * from './components/list-items/list-item-value/list-item-value.types';
export * from './components/list-items/list-item/list-item.types';
export * from './components/buttons/button/button.types';

export function isObjKey<T extends object>(key: any, obj: T): key is keyof T {
return key in obj;
Expand Down

0 comments on commit f4bae55

Please sign in to comment.