From 145ee0a61ad26dfb03423dd8ec7374d18b26b83b Mon Sep 17 00:00:00 2001 From: jvogt23 Date: Sat, 21 Feb 2026 19:02:31 -0600 Subject: [PATCH 1/2] Added Callout and WarningCallout objects --- Components/Callout.tsx | 40 ++++++++++++++++++++++++++ Components/WarningCallout.tsx | 54 +++++++++++++++++++++++++++++++++++ Themes/Themes.ts | 3 ++ 3 files changed, 97 insertions(+) create mode 100644 Components/Callout.tsx create mode 100644 Components/WarningCallout.tsx diff --git a/Components/Callout.tsx b/Components/Callout.tsx new file mode 100644 index 0000000..6a32fc8 --- /dev/null +++ b/Components/Callout.tsx @@ -0,0 +1,40 @@ +import React, { useMemo } from 'react'; +import { ColorValue, StyleSheet, View } from 'react-native'; +import { useTheme } from '../Themes/ThemeContextProvider'; + +type CalloutProps = { + title: React.ReactNode; + children: React.ReactNode; + backgroundColor?: ColorValue; + borderColor?: ColorValue; + padding?: number; +}; + +function Callout(props: CalloutProps) { + const {currentTheme} = useTheme() + const styles = useMemo(() => StyleSheet.create({ + container: { + borderRadius: 8, + width: '100%', + backgroundColor: props.backgroundColor ?? currentTheme.background, + borderColor: props.borderColor, + borderWidth: props.borderColor ? 1 : 0, + padding: props.padding ?? 8, + }, + title: { + marginBottom: 4, + flexDirection: 'row', + alignItems: 'center', + }, + }), [props.backgroundColor, props.borderColor, props.padding, currentTheme]); + return ( + + {props.title} + {props.children} + + ); +} + +export default Callout; diff --git a/Components/WarningCallout.tsx b/Components/WarningCallout.tsx new file mode 100644 index 0000000..e28ec5e --- /dev/null +++ b/Components/WarningCallout.tsx @@ -0,0 +1,54 @@ +import MaterialDesignIcons from '@react-native-vector-icons/material-design-icons'; +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import { Colors } from '../Themes/Colors'; +import { useTheme } from '../Themes/ThemeContextProvider'; +import Callout from './Callout'; + +type WarningCalloutProps = { + titleText: string; + body: React.ReactNode; + padding?: number; +}; + +function WarningCallout(props: WarningCalloutProps) { + const {currentTheme} = useTheme(); + + const backgroundColor = currentTheme.warningSubtle; + const borderColor = Colors.warningLightMuted; + + return ( + + + {props.titleText} + + } + backgroundColor={backgroundColor} + borderColor={borderColor} + padding={props.padding} + > + {props.body} + + ); + +} + +export default WarningCallout; + +const styles = StyleSheet.create({ + header: { + flexDirection: 'row', + alignItems: 'center', + }, + title: { + marginLeft: 8, + fontSize: 18, // ≈ titleLarge + fontWeight: '600', + }, +}); \ No newline at end of file diff --git a/Themes/Themes.ts b/Themes/Themes.ts index 858150f..8628d99 100644 --- a/Themes/Themes.ts +++ b/Themes/Themes.ts @@ -37,6 +37,7 @@ export type Theme = { surfaceContainerHigh: ColorValue; surfaceContainerHighest: ColorValue; success: ColorValue; + warningSubtle: ColorValue; }; export const LightMode: Theme = { @@ -76,6 +77,7 @@ export const LightMode: Theme = { surfaceContainerHigh: Colors.surfaceContainerHighLight, surfaceContainerHighest: Colors.surfaceContainerHighestLight, success: Colors.success, + warningSubtle: Colors.warningLightSubtle, }; export const DarkMode: Theme = { @@ -115,4 +117,5 @@ export const DarkMode: Theme = { surfaceContainerHigh: Colors.surfaceContainerHighDark, surfaceContainerHighest: Colors.surfaceContainerHighestDark, success: Colors.success, + warningSubtle: Colors.warningDarkSubtle, }; From 41d46361bd3732584d7b41992bbe6821be9e5ace Mon Sep 17 00:00:00 2001 From: jvogt23 Date: Sat, 21 Feb 2026 19:15:11 -0600 Subject: [PATCH 2/2] Linter appeasement --- Components/Callout.tsx | 44 +++++++++++++++----------- Components/WarningCallout.tsx | 59 +++++++++++++++++------------------ 2 files changed, 54 insertions(+), 49 deletions(-) diff --git a/Components/Callout.tsx b/Components/Callout.tsx index 6a32fc8..d79e724 100644 --- a/Components/Callout.tsx +++ b/Components/Callout.tsx @@ -11,26 +11,32 @@ type CalloutProps = { }; function Callout(props: CalloutProps) { - const {currentTheme} = useTheme() - const styles = useMemo(() => StyleSheet.create({ - container: { - borderRadius: 8, - width: '100%', - backgroundColor: props.backgroundColor ?? currentTheme.background, - borderColor: props.borderColor, - borderWidth: props.borderColor ? 1 : 0, - padding: props.padding ?? 8, - }, - title: { - marginBottom: 4, - flexDirection: 'row', - alignItems: 'center', - }, - }), [props.backgroundColor, props.borderColor, props.padding, currentTheme]); + const { currentTheme } = useTheme(); + + // This rule is needed because style sheets in a useMemo are not + // detected by eslint normally. + /* eslint react-native/no-unused-styles: off */ + const styles = useMemo( + () => + StyleSheet.create({ + container: { + backgroundColor: props.backgroundColor ?? currentTheme.background, + borderColor: props.borderColor, + borderRadius: 8, + borderWidth: props.borderColor ? 1 : 0, + padding: props.padding ?? 8, + width: '100%', + }, + title: { + alignItems: 'center', + flexDirection: 'row', + marginBottom: 4, + }, + }), + [props.backgroundColor, props.borderColor, props.padding, currentTheme], + ); return ( - + {props.title} {props.children} diff --git a/Components/WarningCallout.tsx b/Components/WarningCallout.tsx index e28ec5e..3c34e1b 100644 --- a/Components/WarningCallout.tsx +++ b/Components/WarningCallout.tsx @@ -6,49 +6,48 @@ import { useTheme } from '../Themes/ThemeContextProvider'; import Callout from './Callout'; type WarningCalloutProps = { - titleText: string; - body: React.ReactNode; - padding?: number; + titleText: string; + body: React.ReactNode; + padding?: number; }; function WarningCallout(props: WarningCalloutProps) { - const {currentTheme} = useTheme(); + const { currentTheme } = useTheme(); - const backgroundColor = currentTheme.warningSubtle; - const borderColor = Colors.warningLightMuted; - - return ( - - - {props.titleText} - - } - backgroundColor={backgroundColor} - borderColor={borderColor} - padding={props.padding} - > - {props.body} - - ); + const backgroundColor = currentTheme.warningSubtle; + const borderColor = Colors.warningLightMuted; + return ( + + + {props.titleText} + + } + backgroundColor={backgroundColor} + borderColor={borderColor} + padding={props.padding} + > + {props.body} + + ); } export default WarningCallout; const styles = StyleSheet.create({ header: { - flexDirection: 'row', alignItems: 'center', + flexDirection: 'row', }, title: { - marginLeft: 8, - fontSize: 18, // ≈ titleLarge + fontSize: 18, fontWeight: '600', + marginLeft: 8, }, -}); \ No newline at end of file +});