diff --git a/package.json b/package.json index ab11023..dbb4e3f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@observation.org/react-native-components", - "version": "1.79.0", + "version": "1.80.0", "main": "src/index.ts", "exports": { ".": "./src/index.ts", diff --git a/src/components/FilterButton.tsx b/src/components/FilterButton.tsx new file mode 100644 index 0000000..a7a49c1 --- /dev/null +++ b/src/components/FilterButton.tsx @@ -0,0 +1,77 @@ +import React from 'react' +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native' + +import { Icon } from '@observation.org/react-native-components' +import { rounded } from '@observation.org/react-native-components/styles' + +import { Theme, useStyles, useTheme } from '../theme' + +type FilterButtonProps = { + disabled?: boolean + activeFilters?: number + label: string + onPress?: () => void +} + +const FilterButton = ({ activeFilters = 0, label, onPress }: FilterButtonProps) => { + const theme = useTheme() + const styles = useStyles(createStyles) + + const backgroundColor = activeFilters > 0 ? theme.color.primary50 : theme.color.background.system.surfaceBase + return ( + + + + + + {label} + {activeFilters > 0 && ( + + {activeFilters} + + )} + + + ) +} + +export default FilterButton + +const createStyles = (theme: Theme) => + StyleSheet.create({ + container: { + ...rounded.normal, + borderWidth: 2, + borderColor: theme.color.border.system.brand, + height: 32, + justifyContent: 'center', + alignItems: 'center', + }, + title: { + textAlignVertical: 'center', + ...theme.font.small, + color: theme.color.text.system.brand, + }, + titleContainer: { + marginHorizontal: theme.margin.half, + flexDirection: 'row', + }, + iconContainerStyle: { + justifyContent: 'center', + paddingRight: theme.margin.half, + }, + activeFilterContainer: { + ...rounded.normal, + marginLeft: theme.margin.half, + width: theme.icon.size.xl, + height: theme.icon.size.xl, + backgroundColor: theme.color.background.system.brand, + justifyContent: 'center', + alignItems: 'center', + }, + activeFilter: { + textAlignVertical: 'center', + ...theme.font.small, + color: theme.color.text.system.staticWhite, + }, + }) diff --git a/src/components/__tests__/FilterButton.test.tsx b/src/components/__tests__/FilterButton.test.tsx new file mode 100644 index 0000000..9cde643 --- /dev/null +++ b/src/components/__tests__/FilterButton.test.tsx @@ -0,0 +1,37 @@ +import React from 'react' + +import { describe, expect, jest, test } from '@jest/globals' +import { fireEvent, render } from '@testing-library/react-native' + +import FilterButton from '../FilterButton' + +describe('FilterButton', () => { + describe('Rendering', () => { + test('Default props', () => { + const { toJSON } = render() + expect(toJSON()).toMatchSnapshot() + }) + + test('Enabled', () => { + const { getByText, toJSON } = render() + expect(getByText('Filter')).toBeTruthy() + expect(getByText('3')).toBeTruthy() + expect(toJSON()).toMatchSnapshot() + }) + + test('No active filters', () => { + const { queryByText, toJSON } = render() + expect(queryByText('0')).toBeNull() + expect(toJSON()).toMatchSnapshot() + }) + }) + + describe('Interaction', () => { + test('Calls onPress when pressed', () => { + const onPress = jest.fn() + const { getByText } = render() + fireEvent.press(getByText('Filter')) + expect(onPress).toHaveBeenCalled() + }) + }) +}) diff --git a/src/components/__tests__/__snapshots__/FilterButton.test.tsx.snap b/src/components/__tests__/__snapshots__/FilterButton.test.tsx.snap new file mode 100644 index 0000000..90bb9a0 --- /dev/null +++ b/src/components/__tests__/__snapshots__/FilterButton.test.tsx.snap @@ -0,0 +1,286 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`FilterButton Rendering Default props 1`] = ` + + + + + + + Filter + + + +`; + +exports[`FilterButton Rendering Enabled 1`] = ` + + + + + + + Filter + + + + 3 + + + + +`; + +exports[`FilterButton Rendering No active filters 1`] = ` + + + + + + + Filter + + + +`; diff --git a/src/index.ts b/src/index.ts index b605483..e64cefc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ import ContentImage from './components/ContentImage' import Date from './components/Date' import Disclose from './components/Disclose' import DocumentLink from './components/DocumentLink' +import FilterButton from './components/FilterButton' import IconButton from './components/IconButton' import IconText from './components/IconText' import IconView from './components/IconView' @@ -52,6 +53,7 @@ export { Date, Disclose, DocumentLink, + FilterButton, IconButton, IconText, IconView,