Skip to content

Commit a80bb28

Browse files
committed
style: update Notification component: add type and other props
1 parent 7e01362 commit a80bb28

2 files changed

Lines changed: 158 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Changelog
22

3-
## v3.0.0-rc.0
3+
## v3.0.0-rc
44

55
### Breaking Changes
66
- The library now internally uses `react-native-safe-area-context`. Make sure you have `react-native-safe-area-context` installed, and that `NotifierRoot/Wrapper` is wrapped by `SafeAreaProvider`.
@@ -23,12 +23,17 @@
2323
- Calling `showNotification` returns `update`, `hide`, `shake`, and `isVisible` functions for manipulating the notification.
2424
- You can mount multiple instances of `NotifierWrapper`/`NotifierRoot` and still control them using global `Notifier.*` methods. The most recently mounted instance is controlled first; if it unmounts, control reverts to the previously mounted instance.
2525
- It's possible to broadcast commands to all mounted instances of Notifier via `Notifier.broadcast.*`. This can be used, for example, to hide all notifications or clear the queue and hide them using `Notifier.broadcast.hideNotification()`.
26-
- Custom handling for safe area insets (based on `react-native-safe-area-context`'s `useSafeAreaInsets` hook) in all built-in components, plus a simple API for using the same insets in custom components. It also handles keyboard offset when a notification is displayed at a bottom `position`. All components receive an `offsets` object and a `ViewWithOffsets` component as props. Related parameters: `ignoreSafeAreaInsets`, `ignoreKeyboard`, `additionalKeyboardOffset`, `additionalOffsets`.
26+
- Custom handling for safe area insets (based on `react-native-safe-area-context`'s `useSafeAreaInsets` hook) in all built-in components, plus a simple API for using the same insets in custom components. It also handles keyboard offset when a notification is displayed at a bottom `position`. All components receive an `offsets` object and a `ViewWithOffsets` component as props. Related parameters: `ignoreSafeAreaInsets`, `ignoreKeyboard`, `ignoreKeyboardHeight`, `additionalKeyboardOffset`, `additionalOffsets`.
2727
- Using new `*AnimationConfig` parameters, it is now possible to run **Spring** animations with fully customizable configurations.
2828
- Additional TypeScript types have been exported, such as `NotifierComponentProps` (for base props in custom components), `AnimationFunction`, `AnimationFunctionParams`, `Position`, `Offsets`, `ViewWithOffsetsComponent`, `Direction`, `DuplicateBehavior`, and `SwipeDirection`.
2929
- New built-in component: `SimpleToast`.
3030
- All components receive a `hide` function and an `animationFunctionParams` object as props.
3131

32+
### Changed
33+
- **Alert component:** Renamed `alertType` prop to `type` for consistency with other components. The `alertType` prop remains available but will be deprecated, so please migrate to `type`.
34+
- **Notification component:** Changed default `borderRadius` from `5` to `8` and "description" `fontSize` from `14` to `15`.
35+
- **Notification component:** Introduced a `type` prop. When set to anything other than `'classic'`, an icon and left border will be displayed.
36+
3237
### Bug Fixes
3338
- When you mount `NotifierWrapper`/`NotifierRoot` with `omitGlobalMethodsHookup={true}` and then switch it to `false`, global methods now hook up correctly.
3439
- Fixed a jump in the appearing animation when very large notifications appear.
@@ -43,3 +48,4 @@ rnScreensOverlayViewStyle={{
4348
bottom: 0,
4449
}}
4550
```
51+
- When `useRNScreensOverlay` is `true`, `SafeAreaView` might not work correctly. Use `ViewWithOffsets` component that is coming though props into all **Custom Components**.

src/ui-components/Notification.tsx

Lines changed: 150 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,69 +11,139 @@ import {
1111
type StyleProp,
1212
} from 'react-native';
1313
import type { NotifierComponentProps } from '../types';
14-
import { commonStyles } from './common';
14+
import {
15+
backgroundColors,
16+
commonStyles,
17+
iconColors,
18+
icons,
19+
type Types,
20+
} from './common';
1521

1622
const s = StyleSheet.create({
1723
container: {
1824
backgroundColor: '#ffffff',
19-
borderRadius: 5,
25+
borderRadius: 8,
2026
margin: 10,
2127
paddingVertical: 10,
22-
paddingHorizontal: 10,
28+
paddingHorizontal: 15,
2329
flexDirection: 'row',
2430
alignItems: 'center',
31+
gap: 8,
32+
},
33+
borderWidth: {
34+
borderLeftWidth: 4,
35+
},
36+
containerWithIcon: {
37+
paddingLeft: 10,
2538
},
2639
image: {
2740
alignItems: 'center',
28-
marginRight: 5,
29-
borderRadius: 5,
41+
borderRadius: 8,
3042
height: 45,
3143
width: 45,
3244
},
33-
content: {
34-
flex: 1,
35-
marginHorizontal: 5,
45+
iconBackground: {
46+
borderRadius: 25,
47+
width: 50,
48+
height: 50,
49+
alignItems: 'center',
50+
justifyContent: 'center',
51+
alignSelf: 'flex-start',
52+
},
53+
icon: {
54+
width: 35,
55+
height: 35,
56+
},
57+
warnIcon: {
58+
top: -2,
59+
},
60+
textContainer: {
61+
flexShrink: 1,
3662
},
3763
title: {
38-
fontWeight: 'bold',
64+
fontWeight: '600',
3965
fontSize: 15,
4066
lineHeight: 25,
67+
color: '#45516F',
68+
},
69+
classicTitle: {
70+
fontWeight: 'bold',
4171
color: '#007BFF',
4272
},
4373
description: {
44-
fontSize: 14,
74+
fontSize: 15,
4575
lineHeight: 20,
76+
color: '#6D7686',
77+
},
78+
classicDescription: {
4679
color: '#444444',
4780
},
4881
});
4982

5083
export interface NotificationComponentProps extends NotifierComponentProps {
84+
/** If set, the icon, icon background color, and border color will be determined by the provided type.
85+
* - classic - uses the same style as it was in v2 and lower
86+
* - other value - adds icon, and border on the left side
87+
* @default null */
88+
type?: Types | 'classic';
89+
90+
/** When `true`, the title color is automatically derived from the `type` prop.
91+
* @default false */
92+
useTypeColorForTitle?: boolean;
93+
94+
/** When `true`, the description color is automatically derived from the `type` prop.
95+
* @default false */
96+
useTypeColorForDescription?: boolean;
97+
5198
/** Passed to `<Image />` as `source` param.
5299
* @default null */
53100
imageSource?: ImageSourcePropType;
54101

55-
/** The maximum number of lines to use for rendering title.
102+
/** The maximum number of lines for rendering the title text.
56103
* @default null */
57104
maxTitleLines?: number;
58105

59-
/** The maximum number of lines to use for rendering description.
106+
/** The maximum number of lines for rendering the description text.
60107
* @default null */
61108
maxDescriptionLines?: number;
62109

63-
/** A container of the component. Set it in case you use different SafeAreaView than the custom `ViewWithOffsets`
110+
/** A custom container component. If used, it replaces the default `ViewWithOffsets` provided by the library.
64111
* @default ViewWithOffsets */
65112
ContainerComponent?: React.ElementType;
66113

67-
/** The style to use for rendering title
114+
/** The icon source passed to the `<Image />` component as the `source` prop.
115+
* If not specified, a default icon is used based on the `type`.
116+
* @default depends on `type`
117+
* @example iconSource: require('./icons/success.png') */
118+
iconSource?: ImageSourcePropType;
119+
120+
/** Style for the outermost container of the toast.
121+
* @default null */
122+
safeAreaStyle?: StyleProp<ViewStyle>;
123+
124+
/** Style for the icon container, useful for adjusting background color or size.
125+
* @default null */
126+
iconContainerStyle?: StyleProp<TextStyle>;
127+
128+
/** Style for the icon `<Image />` itself, useful for adjusting icon color or size.
129+
* @default null
130+
* @example { tintColor: 'red' } */
131+
iconStyle?: StyleProp<ImageStyle>;
132+
133+
/** Style for the text container wrapping both title and description.
134+
* @default null */
135+
textContainerStyle?: StyleProp<TextStyle>;
136+
137+
/** Style for the title text.
68138
* @default null */
69139
titleStyle?: StyleProp<TextStyle>;
70140

71-
/** The style to use for rendering description
141+
/** Style for the description text.
72142
* @default null */
73143
descriptionStyle?: StyleProp<TextStyle>;
74144

75-
/** The style to use for notification container.
76-
* Might be useful to change background color, shadows, paddings or margins
145+
/** Style for the toast content container, often used to modify background color,
146+
* shadows, padding, or margin.
77147
* @default null */
78148
containerStyle?: StyleProp<ViewStyle>;
79149

@@ -93,24 +163,82 @@ export const NotificationComponent = ({
93163
maxTitleLines,
94164
maxDescriptionLines,
95165
containerStyle,
166+
type = 'classic',
167+
useTypeColorForTitle,
168+
useTypeColorForDescription,
169+
iconSource,
170+
safeAreaStyle,
171+
iconContainerStyle,
172+
iconStyle,
173+
textContainerStyle,
96174
ViewWithOffsets,
97175
}: NotificationComponentProps) => {
98176
const Container = ContainerComponent ?? ViewWithOffsets;
99177
return (
100-
<Container>
101-
<View style={[s.container, commonStyles.shadow, containerStyle]}>
178+
<Container style={safeAreaStyle}>
179+
<View
180+
style={[
181+
s.container,
182+
commonStyles.shadow,
183+
(type !== 'classic' || !!imageSource || !!iconSource) &&
184+
s.containerWithIcon,
185+
type !== 'classic' && s.borderWidth,
186+
type !== 'classic' && { borderColor: iconColors[type] },
187+
containerStyle,
188+
]}
189+
>
102190
{!!imageSource && (
103191
<Image style={[s.image, imageStyle]} source={imageSource} />
104192
)}
105-
<View style={s.content}>
193+
{(type !== 'classic' || !!iconSource) && (
194+
<View
195+
style={[
196+
s.iconBackground,
197+
type !== 'classic' && {
198+
backgroundColor: backgroundColors[type],
199+
},
200+
iconContainerStyle,
201+
]}
202+
>
203+
<Image
204+
style={[
205+
s.icon,
206+
type === 'warn' && s.warnIcon,
207+
type !== 'classic' && {
208+
tintColor: iconColors[type],
209+
},
210+
iconStyle,
211+
]}
212+
source={
213+
iconSource ?? (type !== 'classic' ? icons[type] : undefined)
214+
}
215+
/>
216+
</View>
217+
)}
218+
<View style={[s.textContainer, textContainerStyle]}>
106219
{!!title && (
107-
<Text style={[s.title, titleStyle]} numberOfLines={maxTitleLines}>
220+
<Text
221+
style={[
222+
s.title,
223+
titleStyle,
224+
type !== 'classic' &&
225+
useTypeColorForTitle && { color: iconColors[type] },
226+
type === 'classic' && s.classicTitle,
227+
]}
228+
numberOfLines={maxTitleLines}
229+
>
108230
{title}
109231
</Text>
110232
)}
111233
{!!description && (
112234
<Text
113-
style={[s.description, descriptionStyle]}
235+
style={[
236+
s.description,
237+
descriptionStyle,
238+
type !== 'classic' &&
239+
useTypeColorForDescription && { color: iconColors[type] },
240+
type === 'classic' && s.classicDescription,
241+
]}
114242
numberOfLines={maxDescriptionLines}
115243
>
116244
{description}

0 commit comments

Comments
 (0)