Skip to content

Commit

Permalink
Merge pull request Expensify#32439 from software-mansion-labs/wave8/t…
Browse files Browse the repository at this point in the history
…op-bar-search-no-usage

[Wave8] Search Input component
  • Loading branch information
Hayata Suenaga authored Dec 15, 2023
2 parents 48e771d + d1dac19 commit 668af1c
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 2 deletions.
62 changes: 62 additions & 0 deletions src/components/Search.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';
import {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import {PressableWithFeedback} from './Pressable';
import Text from './Text';
import Tooltip from './Tooltip';

type SearchProps = {
// Callback fired when component is pressed
onPress: (event?: GestureResponderEvent | KeyboardEvent) => void;

// Text explaining what the user can search for
placeholder?: string;

// Text showing up in a tooltip when component is hovered
tooltip?: string;

// Styles to apply on the outer element
style?: StyleProp<ViewStyle>;
};

function Search({onPress, placeholder, tooltip, style}: SearchProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

return (
<Tooltip text={tooltip ?? translate('common.search')}>
<PressableWithFeedback
accessibilityLabel={tooltip ?? translate('common.search')}
role={CONST.ROLE.BUTTON}
onPress={onPress}
style={styles.searchPressable}
>
{({hovered}) => (
<View style={[styles.searchContainer, hovered && styles.searchContainerHovered, style]}>
<Icon
src={Expensicons.MagnifyingGlass}
width={variables.iconSizeSmall}
height={variables.iconSizeSmall}
/>
<Text
style={styles.searchInputStyle}
numberOfLines={1}
>
{placeholder ?? translate('common.searchWithThreeDots')}
</Text>
</View>
)}
</PressableWithFeedback>
</Tooltip>
);
}

Search.displayName = 'Search';

export type {SearchProps};
export default Search;
3 changes: 2 additions & 1 deletion src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export default {
optional: 'Optional',
new: 'New',
search: 'Search',
searchWithThreeDots: 'Search...',
next: 'Next',
previous: 'Previous',
goBack: 'Go back',
Expand Down Expand Up @@ -497,7 +498,7 @@ export default {
},
},
sidebarScreen: {
buttonSearch: 'Search',
buttonSearch: 'Search for something...',
buttonMySettings: 'My settings',
fabNewChat: 'Start chat',
fabNewChatExplained: 'Start chat (Floating action)',
Expand Down
3 changes: 2 additions & 1 deletion src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export default {
optional: 'Opcional',
new: 'Nuevo',
search: 'Buscar',
searchWithThreeDots: 'Buscar...',
next: 'Siguiente',
previous: 'Anterior',
goBack: 'Volver',
Expand Down Expand Up @@ -490,7 +491,7 @@ export default {
},
},
sidebarScreen: {
buttonSearch: 'Buscar',
buttonSearch: 'Busca algo...',
buttonMySettings: 'Mi configuración',
fabNewChat: 'Iniciar chat',
fabNewChatExplained: 'Iniciar chat (Acción flotante)',
Expand Down
42 changes: 42 additions & 0 deletions src/stories/Search.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import Search, {SearchProps} from '@components/Search';

/**
* We use the Component Story Format for writing stories. Follow the docs here:
*
* https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format
*/
const story = {
title: 'Components/Search',
component: Search,
};

type StoryType = typeof Template & {args?: Partial<SearchProps>};

function Template(args: SearchProps) {
// eslint-disable-next-line react/jsx-props-no-spreading
return <Search {...args} />;
}

// Arguments can be passed to the component by binding
// See: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Default: StoryType = Template.bind({});
Default.args = {
onPress: () => alert('Pressed'),
};

const CustomPlaceholderAndTooltip: StoryType = Template.bind({});
CustomPlaceholderAndTooltip.args = {
placeholder: 'Search for a specific thing...',
tooltip: 'Custom tooltip text',
onPress: () => alert('This component has custom placeholder text. Also custom tooltip text when hovered.'),
};

const CustomBackground: StoryType = Template.bind({});
CustomBackground.args = {
onPress: () => alert('This component has custom styles applied'),
style: {backgroundColor: 'darkgreen'},
};

export default story;
export {Default, CustomPlaceholderAndTooltip, CustomBackground};
25 changes: 25 additions & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3028,6 +3028,31 @@ const styles = (theme: ThemeColors) =>
flex: 1,
},

searchPressable: {
height: 40,
},

searchContainer: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
gap: 8,
paddingHorizontal: 24,
backgroundColor: theme.highlightBG,
borderRadius: variables.componentBorderRadiusRounded,
},

searchContainerHovered: {
backgroundColor: theme.border,
},

searchInputStyle: {
color: colors.productDark800,
fontSize: 13,
lineHeight: 16,
width: '100%',
},

threeDotsPopoverOffset: (windowWidth: number) =>
({
...getPopOverVerticalOffset(60),
Expand Down

0 comments on commit 668af1c

Please sign in to comment.