From 0bc2b8e9ad45dfa284bfd817dec286d11ec67066 Mon Sep 17 00:00:00 2001 From: Barry van Veen Date: Tue, 30 Jun 2026 13:24:44 +0200 Subject: [PATCH 1/3] FilterButton component --- src/components/FilterButton.tsx | 77 +++++ .../__tests__/FilterButton.test.tsx | 37 +++ .../__snapshots__/FilterButton.test.tsx.snap | 286 ++++++++++++++++++ src/index.ts | 2 + 4 files changed, 402 insertions(+) create mode 100644 src/components/FilterButton.tsx create mode 100644 src/components/__tests__/FilterButton.test.tsx create mode 100644 src/components/__tests__/__snapshots__/FilterButton.test.tsx.snap diff --git a/src/components/FilterButton.tsx b/src/components/FilterButton.tsx new file mode 100644 index 0000000..d4c1d51 --- /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..7d24141 --- /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, From 37498f1f65d4915e5b6336a6c7b33723c9d0d934 Mon Sep 17 00:00:00 2001 From: Barry van Veen Date: Wed, 1 Jul 2026 15:12:41 +0200 Subject: [PATCH 2/3] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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", From 1a87d84a9e51ca6f2a176bd81ec119cefb0db3b2 Mon Sep 17 00:00:00 2001 From: Barry van Veen Date: Thu, 2 Jul 2026 11:01:48 +0200 Subject: [PATCH 3/3] Fix icon size --- src/components/FilterButton.tsx | 2 +- .../__tests__/__snapshots__/FilterButton.test.tsx.snap | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/FilterButton.tsx b/src/components/FilterButton.tsx index d4c1d51..a7a49c1 100644 --- a/src/components/FilterButton.tsx +++ b/src/components/FilterButton.tsx @@ -22,7 +22,7 @@ const FilterButton = ({ activeFilters = 0, label, onPress }: FilterButtonProps) - + {label} {activeFilters > 0 && ( diff --git a/src/components/__tests__/__snapshots__/FilterButton.test.tsx.snap b/src/components/__tests__/__snapshots__/FilterButton.test.tsx.snap index 7d24141..90bb9a0 100644 --- a/src/components/__tests__/__snapshots__/FilterButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/FilterButton.test.tsx.snap @@ -62,7 +62,7 @@ exports[`FilterButton Rendering Default props 1`] = ` @@ -147,7 +147,7 @@ exports[`FilterButton Rendering Enabled 1`] = ` @@ -262,7 +262,7 @@ exports[`FilterButton Rendering No active filters 1`] = `