+4
-6
src/components/Button.tsx
+4
-6
src/components/Button.tsx
···
7
7
Pressable,
8
8
type PressableProps,
9
9
type StyleProp,
10
-
StyleSheet,
11
10
type TargetedEvent,
12
11
type TextProps,
13
12
type TextStyle,
···
512
511
[state, variant, color, size, disabled],
513
512
)
514
513
515
-
const flattenedBaseStyles = flatten([baseStyles, style])
516
-
517
514
return (
518
515
<PressableComponent
519
516
role="button"
···
533
530
a.align_center,
534
531
a.justify_center,
535
532
a.curve_continuous,
536
-
flattenedBaseStyles,
533
+
baseStyles,
534
+
style,
537
535
...(state.hovered || state.pressed
538
-
? [hoverStyles, flatten(hoverStyleProp)]
536
+
? [hoverStyles, hoverStyleProp]
539
537
: []),
540
538
]}
541
539
onPressIn={onPressIn}
···
726
724
baseStyles.push(a.text_xs, a.leading_snug, a.font_semi_bold)
727
725
}
728
726
729
-
return StyleSheet.flatten(baseStyles)
727
+
return flatten(baseStyles)
730
728
}, [t, variant, color, size, disabled])
731
729
}
732
730
+4
-4
src/components/Dialog/index.web.tsx
+4
-4
src/components/Dialog/index.web.tsx
···
16
16
import {logger} from '#/logger'
17
17
import {useA11y} from '#/state/a11y'
18
18
import {useDialogStateControlContext} from '#/state/dialogs'
19
-
import {atoms as a, flatten, useBreakpoints, useTheme, web} from '#/alf'
19
+
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
20
20
import {Button, ButtonIcon} from '#/components/Button'
21
21
import {Context} from '#/components/Dialog/context'
22
22
import {
···
180
180
onClick={stopPropagation}
181
181
onStartShouldSetResponder={_ => true}
182
182
onTouchEnd={stopPropagation}
183
-
style={flatten([
183
+
style={[
184
184
a.relative,
185
185
a.rounded_md,
186
186
a.w_full,
···
195
195
},
196
196
!reduceMotionEnabled && a.zoom_fade_in,
197
197
style,
198
-
])}>
198
+
]}>
199
199
<DismissableLayer.DismissableLayer
200
200
onInteractOutside={preventDefault}
201
201
onFocusOutside={preventDefault}
···
244
244
contentContainerStyle={[a.h_full, a.px_0, webInnerContentContainerStyle]}>
245
245
<FlatList
246
246
ref={ref}
247
-
style={[a.h_full, gtMobile ? a.px_2xl : a.px_xl, flatten(style)]}
247
+
style={[a.h_full, gtMobile ? a.px_2xl : a.px_xl, style]}
248
248
{...props}
249
249
/>
250
250
{footer}
+1
-1
src/components/FeedCard.tsx
+1
-1
src/components/FeedCard.tsx
+2
-11
src/components/IconCircle.tsx
+2
-11
src/components/IconCircle.tsx
···
2
2
3
3
import {
4
4
atoms as a,
5
-
flatten,
6
5
type TextStyleProp,
7
6
useTheme,
8
7
type ViewStyleProp,
···
33
32
height: size === 'lg' ? 52 : 64,
34
33
backgroundColor: t.palette.primary_50,
35
34
},
36
-
flatten(style),
35
+
style,
37
36
]}>
38
-
<Icon
39
-
size={size}
40
-
style={[
41
-
{
42
-
color: t.palette.primary_500,
43
-
},
44
-
flatten(iconStyle),
45
-
]}
46
-
/>
37
+
<Icon size={size} style={[{color: t.palette.primary_500}, iconStyle]} />
47
38
</View>
48
39
)
49
40
}
+1
-1
src/components/LabelingServiceCard/index.tsx
+1
-1
src/components/LabelingServiceCard/index.tsx
+1
-1
src/components/Link.tsx
+1
-1
src/components/Link.tsx
+2
-2
src/components/Lists.tsx
+2
-2
src/components/Lists.tsx
···
5
5
6
6
import {cleanError} from '#/lib/strings/errors'
7
7
import {CenteredView} from '#/view/com/util/Views'
8
-
import {atoms as a, flatten, useBreakpoints, useTheme} from '#/alf'
8
+
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
9
9
import {Button, ButtonText} from '#/components/Button'
10
10
import {Error} from '#/components/Error'
11
11
import {Loader} from '#/components/Loader'
···
43
43
a.pb_lg,
44
44
t.atoms.border_contrast_low,
45
45
{height: height ?? 180, paddingTop: 30},
46
-
flatten(style),
46
+
style,
47
47
]}>
48
48
{isFetchingNextPage ? (
49
49
<Loader size="xl" />
+2
-7
src/components/Loader.tsx
+2
-7
src/components/Loader.tsx
···
7
7
withTiming,
8
8
} from 'react-native-reanimated'
9
9
10
-
import {atoms as a, flatten, useTheme} from '#/alf'
10
+
import {atoms as a, useTheme} from '#/alf'
11
11
import {type Props, useCommonSVGProps} from '#/components/icons/common'
12
12
import {Loader_Stroke2_Corner0_Rounded as Icon} from '#/components/icons/Loader'
13
13
···
37
37
]}>
38
38
<Icon
39
39
{...props}
40
-
style={[
41
-
a.absolute,
42
-
a.inset_0,
43
-
t.atoms.text_contrast_high,
44
-
flatten(props.style),
45
-
]}
40
+
style={[a.absolute, a.inset_0, t.atoms.text_contrast_high, props.style]}
46
41
/>
47
42
</Animated.View>
48
43
)
+2
-2
src/components/Loader.web.tsx
+2
-2
src/components/Loader.web.tsx
···
1
1
import {View} from 'react-native'
2
2
3
-
import {atoms as a, flatten, useTheme} from '#/alf'
3
+
import {atoms as a, useTheme} from '#/alf'
4
4
import {type Props, useCommonSVGProps} from '#/components/icons/common'
5
5
import {Loader_Stroke2_Corner0_Rounded as Icon} from '#/components/icons/Loader'
6
6
···
24
24
a.absolute,
25
25
a.inset_0,
26
26
t.atoms.text_contrast_high,
27
-
flatten(props.style),
27
+
props.style,
28
28
]}
29
29
/>
30
30
</div>
+6
-6
src/components/PolicyUpdateOverlay/Overlay.tsx
+6
-6
src/components/PolicyUpdateOverlay/Overlay.tsx
···
5
5
useSafeAreaInsets,
6
6
} from 'react-native-safe-area-context'
7
7
import {LinearGradient} from 'expo-linear-gradient'
8
+
import {utils} from '@bsky.app/alf'
8
9
9
10
import {isAndroid, isNative} from '#/platform/detection'
10
11
import {useA11y} from '#/state/a11y'
11
-
import {atoms as a, flatten, useBreakpoints, useTheme, web} from '#/alf'
12
-
import {transparentifyColor} from '#/alf/util/colorGeneration'
12
+
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
13
13
import {FocusScope} from '#/components/FocusScope'
14
14
import {LockScroll} from '#/components/LockScroll'
15
15
···
47
47
) : (
48
48
<LinearGradient
49
49
colors={[
50
-
transparentifyColor(t.atoms.bg.backgroundColor, 0),
50
+
utils.alpha(t.atoms.bg.backgroundColor, 0),
51
51
t.atoms.bg.backgroundColor,
52
52
t.atoms.bg.backgroundColor,
53
53
]}
···
97
97
]}>
98
98
<LinearGradient
99
99
colors={[
100
-
transparentifyColor(t.atoms.bg.backgroundColor, 0),
100
+
utils.alpha(t.atoms.bg.backgroundColor, 0),
101
101
t.atoms.bg.backgroundColor,
102
102
]}
103
103
start={[0.5, 0]}
···
113
113
role="dialog"
114
114
aria-role="dialog"
115
115
aria-label={label}
116
-
style={flatten([
116
+
style={[
117
117
a.relative,
118
118
a.w_full,
119
119
a.p_2xl,
···
128
128
maxWidth: 420,
129
129
}),
130
130
],
131
-
])}>
131
+
]}>
132
132
{children}
133
133
</View>
134
134
</FocusScope>
+8
-7
src/components/PostControls/index.tsx
+8
-7
src/components/PostControls/index.tsx
···
1
-
import {memo, useState} from 'react'
1
+
import {memo, useMemo, useState} from 'react'
2
2
import {type StyleProp, View, type ViewStyle} from 'react-native'
3
3
import {
4
4
type AppBskyFeedDefs,
···
25
25
useProgressGuideControls,
26
26
} from '#/state/shell/progress-guide'
27
27
import * as Toast from '#/view/com/util/Toast'
28
-
import {atoms as a, flatten, useBreakpoints} from '#/alf'
28
+
import {atoms as a, useBreakpoints} from '#/alf'
29
29
import {Reply as Bubble} from '#/components/icons/Reply'
30
30
import {useFormatPostStatCount} from '#/components/PostControls/util'
31
31
import {BookmarkButton} from './BookmarkButton'
···
188
188
})
189
189
}
190
190
191
-
const secondaryControlSpacingStyles = flatten([
192
-
{gap: 0}, // default, we want `gap` to be defined on the resulting object
193
-
variant !== 'compact' && a.gap_xs,
194
-
(big || gtPhone) && a.gap_sm,
195
-
])
191
+
const secondaryControlSpacingStyles = useMemo(() => {
192
+
let gap = 0 // default, we want `gap` to be defined on the resulting object
193
+
if (variant !== 'compact') gap = a.gap_xs.gap
194
+
if (big || gtPhone) gap = a.gap_sm.gap
195
+
return {gap}
196
+
}, [variant, big, gtPhone])
196
197
197
198
return (
198
199
<View
+1
-1
src/components/ProfileCard.tsx
+1
-1
src/components/ProfileCard.tsx
+3
-7
src/components/RichText.tsx
+3
-7
src/components/RichText.tsx
···
48
48
[value],
49
49
)
50
50
51
-
const flattenedStyle = flatten(style)
52
-
const plainStyles = [a.leading_snug, flattenedStyle]
53
-
const interactiveStyles = [
54
-
a.leading_snug,
55
-
flatten(interactiveStyle),
56
-
flattenedStyle,
57
-
]
51
+
const plainStyles = [a.leading_snug, style]
52
+
const interactiveStyles = [plainStyles, interactiveStyle]
58
53
59
54
const {text, facets} = richText
60
55
61
56
if (!facets?.length) {
62
57
if (isOnlyEmoji(text)) {
58
+
const flattenedStyle = flatten(style)
63
59
const fontSize =
64
60
(flattenedStyle.fontSize ?? a.text_sm.fontSize) * emojiMultiplier
65
61
return (
+4
-4
src/components/Tooltip/index.web.tsx
+4
-4
src/components/Tooltip/index.web.tsx
···
1
1
import {Children, createContext, useContext, useMemo} from 'react'
2
2
import {View} from 'react-native'
3
+
import {utils} from '@bsky.app/alf'
3
4
import {Popover} from 'radix-ui'
4
5
5
6
import {atoms as a, flatten, select, useTheme} from '#/alf'
6
-
import {transparentifyColor} from '#/alf/util/colorGeneration'
7
7
import {
8
8
ARROW_SIZE,
9
9
BUBBLE_MAX_WIDTH,
···
80
80
{
81
81
minWidth: 'max-content',
82
82
boxShadow: select(t.name, {
83
-
light: `0 0 24px ${transparentifyColor(t.palette.black, 0.2)}`,
84
-
dark: `0 0 24px ${transparentifyColor(t.palette.black, 0.2)}`,
85
-
dim: `0 0 24px ${transparentifyColor(t.palette.black, 0.2)}`,
83
+
light: `0 0 24px ${utils.alpha(t.palette.black, 0.2)}`,
84
+
dark: `0 0 24px ${utils.alpha(t.palette.black, 0.2)}`,
85
+
dim: `0 0 24px ${utils.alpha(t.palette.black, 0.2)}`,
86
86
}),
87
87
},
88
88
])}>
+3
-3
src/components/Typography.tsx
+3
-3
src/components/Typography.tsx
···
1
1
import {UITextView} from 'react-native-uitextview'
2
2
3
3
import {logger} from '#/logger'
4
-
import {atoms, flatten, useAlf, useTheme, web} from '#/alf'
4
+
import {atoms, useAlf, useTheme, web} from '#/alf'
5
5
import {
6
6
childHasEmoji,
7
7
normalizeTextStyles,
···
26
26
}: TextProps) {
27
27
const {fonts, flags} = useAlf()
28
28
const t = useTheme()
29
-
const s = normalizeTextStyles([atoms.text_sm, t.atoms.text, flatten(style)], {
29
+
const s = normalizeTextStyles([atoms.text_sm, t.atoms.text, style], {
30
30
fontScale: fonts.scaleMultiplier,
31
31
fontFamily: fonts.family,
32
32
flags,
···
84
84
<Text
85
85
{...attr}
86
86
{...rest}
87
-
style={[atoms.text_md, atoms.leading_normal, flatten(style)]}
87
+
style={[atoms.text_md, atoms.leading_relaxed, style]}
88
88
/>
89
89
)
90
90
}
+3
-3
src/components/WelcomeModal.tsx
+3
-3
src/components/WelcomeModal.tsx
···
8
8
import {logger} from '#/logger'
9
9
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
10
10
import {Logo} from '#/view/icons/Logo'
11
-
import {atoms as a, flatten, useBreakpoints, web} from '#/alf'
11
+
import {atoms as a, useBreakpoints, web} from '#/alf'
12
12
import {Button, ButtonText} from '#/components/Button'
13
13
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
14
14
import {Text} from '#/components/Typography'
···
78
78
]}>
79
79
<FocusScope.FocusScope asChild loop trapped>
80
80
<View
81
-
style={flatten([
81
+
style={[
82
82
{
83
83
maxWidth: 800,
84
84
maxHeight: 600,
···
89
89
a.rounded_lg,
90
90
a.overflow_hidden,
91
91
a.zoom_in,
92
-
])}>
92
+
]}>
93
93
<ImageBackground
94
94
source={welcomeModalBg}
95
95
style={[a.flex_1, a.justify_center]}
+2
-2
src/components/dms/EmojiReactionPicker.web.tsx
+2
-2
src/components/dms/EmojiReactionPicker.web.tsx
···
134
134
accessibilityRole="button"
135
135
role="button"
136
136
onPress={() => setExpanded(true)}
137
-
style={flatten([
137
+
style={[
138
138
a.rounded_full,
139
139
{height: 34, width: 34},
140
140
a.justify_center,
141
141
a.align_center,
142
-
])}>
142
+
]}>
143
143
<DotGridIcon size="lg" style={t.atoms.text_contrast_medium} />
144
144
</Pressable>
145
145
</DropdownMenu.Item>
+1
-1
src/components/dms/ReportDialog.tsx
+1
-1
src/components/dms/ReportDialog.tsx
+2
-3
src/components/forms/Toggle.tsx
+2
-3
src/components/forms/Toggle.tsx
···
6
6
import {isNative} from '#/platform/detection'
7
7
import {
8
8
atoms as a,
9
-
flatten,
10
9
native,
11
10
type TextStyleProp,
12
11
useTheme,
···
233
232
onPressOut={onPressOut}
234
233
onFocus={onFocus}
235
234
onBlur={onBlur}
236
-
style={[a.flex_row, a.align_center, a.gap_sm, flatten(style)]}>
235
+
style={[a.flex_row, a.align_center, a.gap_sm, style]}>
237
236
{typeof children === 'function' ? children(state) : children}
238
237
</Pressable>
239
238
</ItemContext.Provider>
···
260
259
native({
261
260
paddingTop: 2,
262
261
}),
263
-
flatten(style),
262
+
style,
264
263
]}>
265
264
{children}
266
265
</Text>
+1
-1
src/components/icons/TEMPLATE.tsx
+1
-1
src/components/icons/TEMPLATE.tsx
+3
-3
src/screens/Messages/components/MessageInput.web.tsx
+3
-3
src/screens/Messages/components/MessageInput.web.tsx
···
1
1
import React from 'react'
2
-
import {Pressable, StyleSheet, View} from 'react-native'
2
+
import {Pressable, View} from 'react-native'
3
3
import {msg} from '@lingui/macro'
4
4
import {useLingui} from '@lingui/react'
5
5
import Graphemer from 'graphemer'
···
19
19
type EmojiPickerPosition,
20
20
} from '#/view/com/composer/text-input/web/EmojiPicker'
21
21
import * as Toast from '#/view/com/util/Toast'
22
-
import {atoms as a, useTheme} from '#/alf'
22
+
import {atoms as a, flatten, useTheme} from '#/alf'
23
23
import {Button} from '#/components/Button'
24
24
import {useSharedInputStyles} from '#/components/forms/TextField'
25
25
import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji'
···
199
199
</Button>
200
200
<TextareaAutosize
201
201
ref={textAreaRef}
202
-
style={StyleSheet.flatten([
202
+
style={flatten([
203
203
a.flex_1,
204
204
a.px_sm,
205
205
a.border_0,
+2
-11
src/screens/Onboarding/Layout.tsx
+2
-11
src/screens/Onboarding/Layout.tsx
···
10
10
import {Context} from '#/screens/Onboarding/state'
11
11
import {
12
12
atoms as a,
13
-
flatten,
14
13
native,
15
14
type TextStyleProp,
16
15
tokens,
···
228
227
}: React.PropsWithChildren<TextStyleProp>) {
229
228
return (
230
229
<Text
231
-
style={[
232
-
a.pb_sm,
233
-
a.text_4xl,
234
-
a.font_semi_bold,
235
-
a.leading_tight,
236
-
flatten(style),
237
-
]}>
230
+
style={[a.pb_sm, a.text_4xl, a.font_semi_bold, a.leading_tight, style]}>
238
231
{children}
239
232
</Text>
240
233
)
···
245
238
style,
246
239
}: React.PropsWithChildren<TextStyleProp>) {
247
240
const t = useTheme()
248
-
return (
249
-
<P style={[t.atoms.text_contrast_medium, flatten(style)]}>{children}</P>
250
-
)
241
+
return <P style={[t.atoms.text_contrast_medium, style]}>{children}</P>
251
242
}
+1
-1
src/screens/Profile/components/ProfileFeedHeader.tsx
+1
-1
src/screens/Profile/components/ProfileFeedHeader.tsx
+1
-1
src/screens/ProfileList/components/Header.tsx
+1
-1
src/screens/ProfileList/components/Header.tsx
···
200
200
</ProfileSubpageHeader>
201
201
{descriptionRT ? (
202
202
<View style={[a.px_lg, a.pt_sm, a.pb_sm, a.gap_md]}>
203
-
<RichText value={descriptionRT} style={[a.text_md, a.leading_snug]} />
203
+
<RichText value={descriptionRT} style={[a.text_md]} />
204
204
</View>
205
205
) : null}
206
206
</>
+1
-3
src/screens/StarterPack/StarterPackScreen.tsx
+1
-3
src/screens/StarterPack/StarterPackScreen.tsx
···
458
458
</ProfileSubpageHeader>
459
459
{!hasSession || richText || joinedAllTimeCount >= 25 ? (
460
460
<View style={[a.px_lg, a.pt_md, a.pb_sm, a.gap_md]}>
461
-
{richText ? (
462
-
<RichText value={richText} style={[a.text_md, a.leading_snug]} />
463
-
) : null}
461
+
{richText ? <RichText value={richText} style={[a.text_md]} /> : null}
464
462
{!hasSession ? (
465
463
<Button
466
464
label={_(msg`Join Bluesky`)}
+1
-1
src/screens/VideoFeed/index.tsx
+1
-1
src/screens/VideoFeed/index.tsx
+2
-2
src/view/com/util/images/ImageLayoutGrid.tsx
+2
-2
src/view/com/util/images/ImageLayoutGrid.tsx
···
1
1
import React from 'react'
2
-
import {type StyleProp, StyleSheet, View, type ViewStyle} from 'react-native'
2
+
import {type StyleProp, View, type ViewStyle} from 'react-native'
3
3
import {type AnimatedRef, useAnimatedRef} from 'react-native-reanimated'
4
4
import {type AppBskyEmbedImages} from '@atproto/api'
5
5
···
224
224
if (corners.includes('bottomRight')) {
225
225
styles.push({borderBottomRightRadius: 0})
226
226
}
227
-
return StyleSheet.flatten(styles)
227
+
return styles
228
228
}
+3
-2
src/view/icons/Logo.tsx
+3
-2
src/view/icons/Logo.tsx
···
1
1
import React from 'react'
2
-
import {StyleSheet, type TextProps} from 'react-native'
2
+
import {type TextProps} from 'react-native'
3
3
import Svg, {
4
4
Defs,
5
5
LinearGradient,
···
12
12
13
13
import {colors} from '#/lib/styles'
14
14
import {useKawaiiMode} from '#/state/preferences/kawaii'
15
+
import {flatten} from '#/alf'
15
16
16
17
const ratio = 57 / 64
17
18
···
23
24
export const Logo = React.forwardRef(function LogoImpl(props: Props, ref) {
24
25
const {fill, ...rest} = props
25
26
const gradient = fill === 'sky'
26
-
const styles = StyleSheet.flatten(props.style)
27
+
const styles = flatten(props.style)
27
28
const _fill = gradient ? 'url(#sky)' : fill || styles?.color || colors.blue3
28
29
// @ts-ignore it's fiiiiine
29
30
const size = parseInt(rest.width || 32)