Skip to content

Commit

Permalink
Merge pull request #23 from gunnartorfis/cancel
Browse files Browse the repository at this point in the history
feat: cancel button
  • Loading branch information
gunnartorfis authored Sep 7, 2024
2 parents 313f5fe + 0c5892b commit 0d93453
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 86 deletions.
2 changes: 1 addition & 1 deletion docs/docs/sonner.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
| unstyled |||
| actionButtonStyles |||
| cancelButtonStyles |||
| cancel | ||
| cancel | ||
| action as JSX |||
| loading |||
| Headless |||
Expand Down
49 changes: 32 additions & 17 deletions docs/docs/toast.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ toast('My action toast', {
});
```

### Cancel

Renders a cancel button with a callback function. The cancel object should contain a label and an `onClick` function. The cancel button and its label can be customized with the `cancelButtonStyles` and `cancelButtonTextStyles` params, respectively.

```jsx
toast('My cancel toast', {
cancel: {
label: 'Cancel',
onClick: () => console.log('Cancel!'),
},
});
```

### Promises

The toast.promise function can be used to display a toast message while a promise is in progress, and update the message based on the promise's success or failure.
Expand Down Expand Up @@ -153,20 +166,22 @@ toast.dismiss();

## API Reference

| Property | Description | Default |
| :----------------- | :----------------------------------------------------------------------------------------------------: | -----------: |
| description | Toast's description, renders underneath the title. | `-` |
| closeButton | Adds a close button. | `false` |
| invert | Dark toast in light mode and vice versa. | `false` |
| important | Control the sensitivity of the toast for screen readers | `false` |
| duration | Time in milliseconds that should elapse before automatically closing the toast. | `4000` |
| position | Position of the toast. | `top-center` |
| dismissible | If `false`, it'll prevent the user from dismissing the toast. | `true` |
| icon | Icon displayed in front of toast's text, aligned vertically. | `-` |
| action | Renders a primary button, clicking it will close the toast. | `-` |
| id | Custom id for the toast. | `-` |
| onDismiss | The function gets called when either the close button is clicked, or the toast is swiped. | `-` |
| onAutoClose | Function that gets called when the toast disappears automatically after it's timeout (duration` prop). | `-` |
| unstyled | Removes the default styling, which allows for easier customization. | `false` |
| actionButtonStyles | Styles for the action button | `{}` |
| cancelButtonStyles | Styles for the cancel button | `{}` |
| Property | Description | Default |
| :--------------------- | :----------------------------------------------------------------------------------------------------: | -----------: |
| description | Toast's description, renders underneath the title. | `-` |
| closeButton | Adds a close button. | `false` |
| invert | Dark toast in light mode and vice versa. | `false` |
| important | Control the sensitivity of the toast for screen readers | `false` |
| duration | Time in milliseconds that should elapse before automatically closing the toast. | `4000` |
| position | Position of the toast. | `top-center` |
| dismissible | If `false`, it'll prevent the user from dismissing the toast. | `true` |
| icon | Icon displayed in front of toast's text, aligned vertically. | `-` |
| action | Renders a primary button, clicking it will close the toast. | `-` |
| id | Custom id for the toast. | `-` |
| onDismiss | The function gets called when either the close button is clicked, or the toast is swiped. | `-` |
| onAutoClose | Function that gets called when the toast disappears automatically after it's timeout (duration` prop). | `-` |
| unstyled | Removes the default styling, which allows for easier customization. | `false` |
| actionButtonStyles | Styles for the action button | `{}` |
| actionButtonTextStyles | Styles for the action button text | `{}` |
| cancelButtonStyles | Styles for the cancel button | `{}` |
| cancelButtonTextStyles | Styles for the cancel button text | `{}` |
41 changes: 26 additions & 15 deletions example/src/ToastDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ export const ToastDemo: React.FC = () => {
}}
/>
),
actionButtonStyle: {
borderStyle: 'dashed',
borderColor: 'black',
borderWidth: 2,
borderRadius: 2,
paddingVertical: 6,
paddingHorizontal: 10,
marginTop: 8,
alignSelf: 'center',
},
actionButtonTextStyle: {
fontSize: 14,
color: 'black',
textAlign: 'center',
},
styles: {
toastContainer: {
paddingHorizontal: 16,
Expand Down Expand Up @@ -126,21 +141,6 @@ export const ToastDemo: React.FC = () => {
color: '#000000',
marginBottom: 10,
},
actionButton: {
borderStyle: 'dashed',
borderColor: 'black',
borderWidth: 2,
borderRadius: 2,
paddingVertical: 6,
paddingHorizontal: 10,
marginTop: 8,
alignSelf: 'center',
},
actionButtonText: {
fontSize: 14,
color: 'black',
textAlign: 'center',
},
closeButton: {
backgroundColor: '#DD3C14',
borderRadius: 2,
Expand Down Expand Up @@ -243,6 +243,17 @@ export const ToastDemo: React.FC = () => {
toast.error('Custom icon');
}}
/>
<Button
title="Cancel"
onPress={() => {
toast('My cancel toast', {
cancel: {
label: 'Cancel',
onPress: () => console.log('Cancel!'),
},
});
}}
/>
</ScrollView>
);
};
Expand Down
142 changes: 97 additions & 45 deletions src/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import * as React from 'react';
import { ActivityIndicator, Pressable, Text, View } from 'react-native';
import Animated from 'react-native-reanimated';
import { ANIMATION_DURATION, useToastLayoutAnimations } from './animations';
import { toastDefaultValues } from './constants';
import { useToastContext } from './context';
import { ToastSwipeHandler } from './gestures';
import { cn } from './tailwind-utils';
import { type ToastProps } from './types';
import { useColors } from './use-colors';
import { toastDefaultValues } from './constants';
import { cn } from './tailwind-utils';

export const Toast: React.FC<ToastProps> = ({
id,
Expand All @@ -19,10 +19,19 @@ export const Toast: React.FC<ToastProps> = ({
duration: durationProps,
variant,
action,
cancel,
onDismiss,
onAutoClose,
dismissible = toastDefaultValues.dismissible,
closeButton: closeButtonProps,
actionButtonStyle,
actionButtonTextStyle,
actionButtonClassName,
actionButtonTextClassName,
cancelButtonStyle,
cancelButtonTextStyle,
cancelButtonClassName,
cancelButtonTextClassName,
style,
className,
classNames,
Expand Down Expand Up @@ -216,62 +225,105 @@ export const Toast: React.FC<ToastProps> = ({
{description}
</Text>
) : null}
{action ? (
<Pressable
onPress={action.onPress}
className={cn(
classNamesCtx.actionButton,
classNames?.actionButton
)}
style={[
unstyled
? undefined
: {
marginTop: 16,
flexGrow: 0,
alignSelf: 'flex-start',
borderRadius: 999,
borderWidth: 1,
borderColor: colors['border-secondary'],
paddingHorizontal: 8,
paddingVertical: 4,
borderCurve: 'continuous',
backgroundColor: colors['background-secondary'],
},
stylesCtx?.actionButton,
styles?.actionButton,
]}
>
<Text
numberOfLines={1}
<View
style={[
unstyled || (!action && !cancel)
? undefined
: {
flexDirection: 'row',
alignItems: 'center',
gap: 16,
marginTop: 16,
},
stylesCtx.buttons,
styles?.buttons,
]}
className={cn(classNamesCtx.buttons, classNames?.buttons)}
>
{action ? (
<Pressable
onPress={action.onPress}
className={actionButtonClassName}
style={[
unstyled
? undefined
: {
fontSize: 14,
lineHeight: 20,
fontWeight: '600',
flexGrow: 0,
alignSelf: 'flex-start',
color: colors['text-primary'],
borderRadius: 999,
borderWidth: 1,
borderColor: colors['border-secondary'],
paddingHorizontal: 8,
paddingVertical: 4,
borderCurve: 'continuous',
backgroundColor: colors['background-secondary'],
},
stylesCtx.actionButtonText,
styles?.actionButtonText,
actionButtonStyle,
]}
className={cn(
classNamesCtx?.actionButtonText,
classNames?.actionButtonText
)}
>
{action.label}
</Text>
</Pressable>
) : null}
<Text
numberOfLines={1}
style={[
unstyled
? undefined
: {
fontSize: 14,
lineHeight: 20,
fontWeight: '600',
alignSelf: 'flex-start',
color: colors['text-primary'],
},
actionButtonTextStyle,
]}
className={actionButtonTextClassName}
>
{action.label}
</Text>
</Pressable>
) : null}
{cancel ? (
<Pressable
onPress={() => {
cancel.onPress();
onDismiss?.(id);
}}
className={cancelButtonClassName}
style={[
unstyled
? undefined
: {
flexGrow: 0,
},
cancelButtonStyle,
]}
>
<Text
numberOfLines={1}
style={[
unstyled
? undefined
: {
fontSize: 14,
lineHeight: 20,
fontWeight: '600',
alignSelf: 'flex-start',
color: colors['text-secondary'],
},
cancelButtonTextStyle,
]}
className={cancelButtonTextClassName}
>
{cancel.label}
</Text>
</Pressable>
) : null}
</View>
</View>
{closeButton && dismissible ? (
<Pressable
onPress={() => onDismiss?.(id)}
hitSlop={10}
style={[stylesCtx?.closeButton, styles?.closeButton]}
style={[stylesCtx.closeButton, styles?.closeButton]}
className={cn(classNamesCtx.closeButton, classNames?.closeButton)}
>
<X
Expand Down
18 changes: 10 additions & 8 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ type StyleProps = {
toastContent?: string;
title?: string;
description?: string;
actionButton?: string;
actionButtonText?: string;
buttons?: string;
closeButton?: string;
closeButtonIcon?: string;
};
Expand All @@ -21,8 +20,7 @@ type StyleProps = {
toastContent?: ViewStyle;
title?: TextStyle;
description?: TextStyle;
actionButton?: ViewStyle;
actionButtonText?: TextStyle;
buttons?: ViewStyle;
closeButton?: ViewStyle;
closeButtonIcon?: ViewStyle;
};
Expand Down Expand Up @@ -66,10 +64,14 @@ export type ToastProps = StyleProps & {
onDismiss?: (id: string) => void;
onAutoClose?: (id: string) => void;
promiseOptions?: PromiseOptions;
actionButtonStyles?: ViewStyle;
actionButtonTextStyles?: TextStyle;
closeButtonStyles?: ViewStyle;
closeButtonTextStyles?: TextStyle;
actionButtonStyle?: ViewStyle;
actionButtonTextStyle?: TextStyle;
actionButtonClassName?: string;
actionButtonTextClassName?: string;
cancelButtonStyle?: ViewStyle;
cancelButtonTextStyle?: TextStyle;
cancelButtonClassName?: string;
cancelButtonTextClassName?: string;
};

type ExternalToast = Omit<
Expand Down

0 comments on commit 0d93453

Please sign in to comment.