1- import * as React from 'react' ;
2- import { Animated , StyleSheet , useWindowDimensions } from 'react-native' ;
3- import type { StyleProp , TextStyle } from 'react-native' ;
1+ import type { StyleProp , TextProps , TextStyle } from 'react-native' ;
2+ import { StyleSheet } from 'react-native' ;
3+
4+ import Animated from 'react-native-reanimated' ;
45
56import { useInternalTheme } from '../core/theming' ;
7+ import { cornerFull } from '../theme/tokens/sys/shape' ;
68import type { ThemeProp } from '../types' ;
79
8- const defaultSize = 20 ;
10+ const SMALL_SIZE = 6 ;
11+ const LARGE_SIZE = 16 ;
12+ const MAX_LARGE_WIDTH = 36 ;
13+ const LARGE_PADDING = 4 ;
914
10- export type Props = React . ComponentProps < typeof Animated . Text > & {
15+ export type Props = TextProps & {
1116 /**
1217 * Whether the badge is visible
1318 */
@@ -16,12 +21,7 @@ export type Props = React.ComponentProps<typeof Animated.Text> & {
1621 * Content of the `Badge`.
1722 */
1823 children ?: string | number ;
19- /**
20- * Size of the `Badge`.
21- */
22- size ?: number ;
2324 style ?: StyleProp < TextStyle > ;
24- ref ?: React . RefObject < typeof Animated . Text > ;
2525 /**
2626 * @optional
2727 */
@@ -32,6 +32,10 @@ export type Props = React.ComponentProps<typeof Animated.Text> & {
3232 * Badges are small status descriptors for UI elements.
3333 * A badge consists of a small circle, typically containing a number or other short set of characters, that appears in proximity to another object.
3434 *
35+ * The badge is styled differently based on whether `children` is passed:
36+ * - Small dot when it doesn't have `children`
37+ * - Larger pill when it has `children`
38+ *
3539 * ## Usage
3640 * ```js
3741 * import * as React from 'react';
@@ -46,64 +50,52 @@ export type Props = React.ComponentProps<typeof Animated.Text> & {
4650 */
4751const Badge = ( {
4852 children,
49- size = defaultSize ,
5053 style,
5154 theme : themeOverrides ,
5255 visible = true ,
5356 ...rest
5457} : Props ) => {
5558 const theme = useInternalTheme ( themeOverrides ) ;
56- const { current : opacity } = React . useRef < Animated . Value > (
57- new Animated . Value ( visible ? 1 : 0 )
58- ) ;
59- const { fontScale } = useWindowDimensions ( ) ;
60-
61- const isFirstRendering = React . useRef < boolean > ( true ) ;
6259
6360 const {
6461 animation : { scale } ,
6562 } = theme ;
6663
67- React . useEffect ( ( ) => {
68- // Do not run animation on very first rendering
69- if ( isFirstRendering . current ) {
70- isFirstRendering . current = false ;
71- return ;
72- }
73-
74- Animated . timing ( opacity , {
75- toValue : visible ? 1 : 0 ,
76- duration : 150 * scale ,
77- useNativeDriver : true ,
78- } ) . start ( ) ;
79- } , [ visible , opacity , scale ] ) ;
80-
81- const { backgroundColor = theme . colors . error , ...restStyle } =
82- ( StyleSheet . flatten ( style ) || { } ) as TextStyle ;
83-
8464 const textColor = theme . colors . onError ;
8565
86- const borderRadius = size / 2 ;
66+ const isLarge = children != null ;
67+ const badgeSize = isLarge ? LARGE_SIZE : SMALL_SIZE ;
68+ const labelFont = theme . fonts . labelSmall ;
8769
88- const paddingHorizontal = 3 ;
70+ const transitionStyle = {
71+ opacity : visible ? 1 : 0 ,
72+ transitionDuration : 150 * scale ,
73+ transitionProperty : 'opacity' ,
74+ } ;
8975
9076 return (
9177 < Animated . Text
9278 numberOfLines = { 1 }
79+ allowFontScaling = { false }
9380 style = { [
81+ styles . container ,
82+ transitionStyle ,
9483 {
95- opacity,
96- backgroundColor,
84+ backgroundColor : theme . colors . error ,
9785 color : textColor ,
98- fontSize : size * 0.5 ,
99- lineHeight : size / fontScale ,
100- height : size ,
101- minWidth : size ,
102- borderRadius,
103- paddingHorizontal,
86+ borderRadius : cornerFull ,
87+ height : badgeSize ,
88+ minWidth : badgeSize ,
10489 } ,
105- styles . container ,
106- restStyle ,
90+ isLarge && [
91+ labelFont ,
92+ {
93+ lineHeight : LARGE_SIZE ,
94+ maxWidth : MAX_LARGE_WIDTH ,
95+ paddingHorizontal : LARGE_PADDING ,
96+ } ,
97+ ] ,
98+ style ,
10799 ] }
108100 { ...rest }
109101 >
0 commit comments