@space-uy/pulsar-ui 0.11.1 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
 
3
3
  import { StyleSheet, View } from 'react-native';
4
+ import Animated, { interpolate, useAnimatedStyle } from 'react-native-reanimated';
4
5
  import Text from "./Text.js";
5
6
  import IconButton from "./IconButton.js";
6
7
  import useTheme from "../hooks/useTheme.js";
7
8
  import meassures from "../theme/meassures.js";
8
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
10
+ const DEFAULT_COLLAPSE_THRESHOLD = 80;
9
11
  const HEADER_BASE_HEIGHT = 52;
10
12
  export default function Header({
11
13
  title,
@@ -14,7 +16,9 @@ export default function Header({
14
16
  rightButton,
15
17
  style,
16
18
  useInsets = true,
17
- children
19
+ children,
20
+ scrollY,
21
+ collapseThreshold = DEFAULT_COLLAPSE_THRESHOLD
18
22
  }) {
19
23
  const {
20
24
  colors,
@@ -22,6 +26,35 @@ export default function Header({
22
26
  } = useTheme();
23
27
  const topInset = useInsets ? theme.insets?.top || 0 : 0;
24
28
  const isSecondary = variant === 'secondary';
29
+ const isCollapsible = isSecondary && scrollY != null;
30
+ const animatedHeaderStyle = useAnimatedStyle(() => {
31
+ if (!isCollapsible || scrollY == null) return {};
32
+ const progress = interpolate(scrollY.value, [0, collapseThreshold], [0, 1], 'clamp');
33
+ return {
34
+ paddingBottom: interpolate(progress, [0, 1], [12, 0])
35
+ };
36
+ }, [isCollapsible, collapseThreshold]);
37
+ const animatedTitleRowStyle = useAnimatedStyle(() => {
38
+ if (!isCollapsible || scrollY == null) return {};
39
+ const progress = interpolate(scrollY.value, [0, collapseThreshold], [0, 1], 'clamp');
40
+ // Estimate: h1 fontSize 24 + line height ~16 + paddingTop 4 = ~44px
41
+ const titleRowHeight = 44;
42
+ return {
43
+ opacity: interpolate(progress, [0, 1], [1, 0]),
44
+ height: interpolate(progress, [0, 1], [titleRowHeight, 0]),
45
+ overflow: 'hidden',
46
+ transform: [{
47
+ translateY: interpolate(progress, [0, 1], [0, -16])
48
+ }]
49
+ };
50
+ }, [isCollapsible, collapseThreshold]);
51
+ const animatedSmallTitleStyle = useAnimatedStyle(() => {
52
+ if (!isCollapsible || scrollY == null) return {};
53
+ const progress = interpolate(scrollY.value, [0, collapseThreshold], [0, 1], 'clamp');
54
+ return {
55
+ opacity: interpolate(progress, [0, 1], [0, 1])
56
+ };
57
+ }, [isCollapsible, collapseThreshold]);
25
58
  const renderButton = button => {
26
59
  return /*#__PURE__*/_jsx(IconButton, {
27
60
  iconName: button.iconName,
@@ -32,20 +65,29 @@ export default function Header({
32
65
  rounded: button.rounded
33
66
  });
34
67
  };
35
- return /*#__PURE__*/_jsxs(View, {
36
- style: [styles.header, {
37
- backgroundColor: colors.background,
38
- borderBottomColor: colors.border,
39
- paddingTop: topInset
40
- }, isSecondary && styles.headerSecondary, !!children && styles.paddingBottom, style],
68
+ const showSmallTitleInBar = !isSecondary || isCollapsible;
69
+ const showBigTitleRow = isSecondary;
70
+ const headerContent = /*#__PURE__*/_jsxs(_Fragment, {
41
71
  children: [/*#__PURE__*/_jsxs(View, {
42
- style: [styles.headerContent, isSecondary && styles.headerContentSecondary],
72
+ style: [styles.headerContent, isSecondary && !isCollapsible && styles.headerContentSecondary, isCollapsible && styles.headerContentSecondary],
43
73
  children: [/*#__PURE__*/_jsx(View, {
44
74
  style: [styles.slot, styles.leftSlot],
45
75
  children: leftButton && renderButton(leftButton)
46
- }), !isSecondary && /*#__PURE__*/_jsx(View, {
76
+ }), showSmallTitleInBar && /*#__PURE__*/_jsx(View, {
47
77
  style: styles.titleContainer,
48
- children: /*#__PURE__*/_jsx(Text, {
78
+ pointerEvents: "none",
79
+ children: isCollapsible ? /*#__PURE__*/_jsx(Animated.View, {
80
+ style: [styles.titleContainer, animatedSmallTitleStyle],
81
+ children: /*#__PURE__*/_jsx(Text, {
82
+ variant: "h3",
83
+ style: [styles.title, {
84
+ color: colors.foreground
85
+ }],
86
+ numberOfLines: 1,
87
+ ellipsizeMode: "tail",
88
+ children: title
89
+ })
90
+ }) : /*#__PURE__*/_jsx(Text, {
49
91
  variant: "h3",
50
92
  style: [styles.title, {
51
93
  color: colors.foreground
@@ -58,10 +100,21 @@ export default function Header({
58
100
  style: [styles.slot, styles.rightSlot],
59
101
  children: rightButton && renderButton(rightButton)
60
102
  })]
61
- }), isSecondary && /*#__PURE__*/_jsx(View, {
103
+ }), showBigTitleRow && (isCollapsible ? /*#__PURE__*/_jsx(Animated.View, {
104
+ style: [styles.titleRow, animatedTitleRowStyle],
105
+ children: /*#__PURE__*/_jsx(Text, {
106
+ variant: "h1",
107
+ style: [styles.titleSecondary, {
108
+ color: colors.foreground
109
+ }],
110
+ numberOfLines: 1,
111
+ ellipsizeMode: "tail",
112
+ children: title
113
+ })
114
+ }) : /*#__PURE__*/_jsx(View, {
62
115
  style: styles.titleRow,
63
116
  children: /*#__PURE__*/_jsx(Text, {
64
- variant: "h2",
117
+ variant: "h1",
65
118
  style: [styles.titleSecondary, {
66
119
  color: colors.foreground
67
120
  }],
@@ -69,7 +122,22 @@ export default function Header({
69
122
  ellipsizeMode: "tail",
70
123
  children: title
71
124
  })
72
- }), children]
125
+ }))]
126
+ });
127
+ const staticHeaderStyle = [styles.header, {
128
+ backgroundColor: colors.background,
129
+ borderBottomColor: colors.border,
130
+ paddingTop: topInset
131
+ }, isSecondary && !isCollapsible && styles.headerSecondary, isCollapsible && styles.headerSecondary, !!children && styles.paddingBottom, style];
132
+ if (isCollapsible) {
133
+ return /*#__PURE__*/_jsxs(Animated.View, {
134
+ style: [staticHeaderStyle, animatedHeaderStyle],
135
+ children: [headerContent, children]
136
+ });
137
+ }
138
+ return /*#__PURE__*/_jsxs(View, {
139
+ style: staticHeaderStyle,
140
+ children: [headerContent, children]
73
141
  });
74
142
  }
75
143
  const styles = StyleSheet.create({
@@ -1 +1 @@
1
- {"version":3,"names":["StyleSheet","View","Text","IconButton","useTheme","meassures","jsx","_jsx","jsxs","_jsxs","HEADER_BASE_HEIGHT","Header","title","variant","leftButton","rightButton","style","useInsets","children","colors","theme","topInset","insets","top","isSecondary","renderButton","button","iconName","size","onPress","disabled","rounded","styles","header","backgroundColor","background","borderBottomColor","border","paddingTop","headerSecondary","paddingBottom","headerContent","headerContentSecondary","slot","leftSlot","titleContainer","color","foreground","numberOfLines","ellipsizeMode","rightSlot","titleRow","titleSecondary","create","borderBottomWidth","paddingHorizontal","height","flexDirection","alignItems","justifyContent","width","medium","flex","textAlign","marginHorizontal"],"sourceRoot":"../../../src","sources":["components/Header.tsx"],"mappings":";;AACA,SAASA,UAAU,EAAEC,IAAI,QAAwC,cAAc;AAE/E,OAAOC,IAAI,MAAM,WAAQ;AACzB,OAAOC,UAAU,MAAM,iBAAc;AAGrC,OAAOC,QAAQ,MAAM,sBAAmB;AAExC,OAAOC,SAAS,MAAM,uBAAoB;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAsB3C,MAAMC,kBAAkB,GAAG,EAAE;AAE7B,eAAe,SAASC,MAAMA,CAAC;EAC7BC,KAAK;EACLC,OAAO,GAAG,SAAS;EACnBC,UAAU;EACVC,WAAW;EACXC,KAAK;EACLC,SAAS,GAAG,IAAI;EAChBC;AACK,CAAC,EAAE;EACR,MAAM;IAAEC,MAAM;IAAEC;EAAM,CAAC,GAAGhB,QAAQ,CAAC,CAAC;EACpC,MAAMiB,QAAQ,GAAGJ,SAAS,GAAGG,KAAK,CAACE,MAAM,EAAEC,GAAG,IAAI,CAAC,GAAG,CAAC;EACvD,MAAMC,WAAW,GAAGX,OAAO,KAAK,WAAW;EAE3C,MAAMY,YAAY,GAAIC,MAAyB,IAAK;IAClD,oBACEnB,IAAA,CAACJ,UAAU;MACTwB,QAAQ,EAAED,MAAM,CAACC,QAAS;MAC1Bd,OAAO,EAAEa,MAAM,CAACb,OAAO,IAAI,aAAc;MACzCe,IAAI,EAAC,QAAQ;MACbC,OAAO,EAAEH,MAAM,CAACG,OAAQ;MACxBC,QAAQ,EAAEJ,MAAM,CAACI,QAAS;MAC1BC,OAAO,EAAEL,MAAM,CAACK;IAAQ,CACzB,CAAC;EAEN,CAAC;EAED,oBACEtB,KAAA,CAACR,IAAI;IACHe,KAAK,EAAE,CACLgB,MAAM,CAACC,MAAM,EACb;MACEC,eAAe,EAAEf,MAAM,CAACgB,UAAU;MAClCC,iBAAiB,EAAEjB,MAAM,CAACkB,MAAM;MAChCC,UAAU,EAAEjB;IACd,CAAC,EACDG,WAAW,IAAIQ,MAAM,CAACO,eAAe,EACrC,CAAC,CAACrB,QAAQ,IAAIc,MAAM,CAACQ,aAAa,EAClCxB,KAAK,CACL;IAAAE,QAAA,gBAEFT,KAAA,CAACR,IAAI;MACHe,KAAK,EAAE,CACLgB,MAAM,CAACS,aAAa,EACpBjB,WAAW,IAAIQ,MAAM,CAACU,sBAAsB,CAC5C;MAAAxB,QAAA,gBAEFX,IAAA,CAACN,IAAI;QAACe,KAAK,EAAE,CAACgB,MAAM,CAACW,IAAI,EAAEX,MAAM,CAACY,QAAQ,CAAE;QAAA1B,QAAA,EACzCJ,UAAU,IAAIW,YAAY,CAACX,UAAU;MAAC,CACnC,CAAC,EACN,CAACU,WAAW,iBACXjB,IAAA,CAACN,IAAI;QAACe,KAAK,EAAEgB,MAAM,CAACa,cAAe;QAAA3B,QAAA,eACjCX,IAAA,CAACL,IAAI;UACHW,OAAO,EAAC,IAAI;UACZG,KAAK,EAAE,CAACgB,MAAM,CAACpB,KAAK,EAAE;YAAEkC,KAAK,EAAE3B,MAAM,CAAC4B;UAAW,CAAC,CAAE;UACpDC,aAAa,EAAE,CAAE;UACjBC,aAAa,EAAC,MAAM;UAAA/B,QAAA,EAEnBN;QAAK,CACF;MAAC,CACH,CACP,eACDL,IAAA,CAACN,IAAI;QAACe,KAAK,EAAE,CAACgB,MAAM,CAACW,IAAI,EAAEX,MAAM,CAACkB,SAAS,CAAE;QAAAhC,QAAA,EAC1CH,WAAW,IAAIU,YAAY,CAACV,WAAW;MAAC,CACrC,CAAC;IAAA,CACH,CAAC,EACNS,WAAW,iBACVjB,IAAA,CAACN,IAAI;MAACe,KAAK,EAAEgB,MAAM,CAACmB,QAAS;MAAAjC,QAAA,eAC3BX,IAAA,CAACL,IAAI;QACHW,OAAO,EAAC,IAAI;QACZG,KAAK,EAAE,CAACgB,MAAM,CAACoB,cAAc,EAAE;UAAEN,KAAK,EAAE3B,MAAM,CAAC4B;QAAW,CAAC,CAAE;QAC7DC,aAAa,EAAE,CAAE;QACjBC,aAAa,EAAC,MAAM;QAAA/B,QAAA,EAEnBN;MAAK,CACF;IAAC,CACH,CACP,EACAM,QAAQ;EAAA,CACL,CAAC;AAEX;AAEA,MAAMc,MAAM,GAAGhC,UAAU,CAACqD,MAAM,CAAC;EAC/BpB,MAAM,EAAE;IAAEqB,iBAAiB,EAAE,CAAC;IAAEC,iBAAiB,EAAE;EAAG,CAAC;EACvDhB,eAAe,EAAE;IAAEC,aAAa,EAAE;EAAG,CAAC;EACtCC,aAAa,EAAE;IACbe,MAAM,EAAE9C,kBAAkB;IAC1B+C,aAAa,EAAE,KAAK;IACpBC,UAAU,EAAE;EACd,CAAC;EACDhB,sBAAsB,EAAE;IAAEiB,cAAc,EAAE;EAAgB,CAAC;EAC3DhB,IAAI,EAAE;IAAEiB,KAAK,EAAEvD,SAAS,CAACqB,MAAM,CAACmC,MAAM;IAAEF,cAAc,EAAE;EAAS,CAAC;EAClEf,QAAQ,EAAE;IAAEc,UAAU,EAAE;EAAa,CAAC;EACtCb,cAAc,EAAE;IAAEiB,IAAI,EAAE,CAAC;IAAEJ,UAAU,EAAE,QAAQ;IAAEC,cAAc,EAAE;EAAS,CAAC;EAC3E/C,KAAK,EAAE;IAAEmD,SAAS,EAAE,QAAQ;IAAEC,gBAAgB,EAAE;EAAE,CAAC;EACnDb,QAAQ,EAAE;IAAEI,iBAAiB,EAAE,CAAC;IAAEjB,UAAU,EAAE;EAAE,CAAC;EACjDc,cAAc,EAAE;IAAEW,SAAS,EAAE;EAAO,CAAC;EACrCb,SAAS,EAAE;IAAEQ,UAAU,EAAE;EAAW,CAAC;EACrClB,aAAa,EAAE;IAAEA,aAAa,EAAE;EAAG;AACrC,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["StyleSheet","View","Animated","interpolate","useAnimatedStyle","Text","IconButton","useTheme","meassures","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","DEFAULT_COLLAPSE_THRESHOLD","HEADER_BASE_HEIGHT","Header","title","variant","leftButton","rightButton","style","useInsets","children","scrollY","collapseThreshold","colors","theme","topInset","insets","top","isSecondary","isCollapsible","animatedHeaderStyle","progress","value","paddingBottom","animatedTitleRowStyle","titleRowHeight","opacity","height","overflow","transform","translateY","animatedSmallTitleStyle","renderButton","button","iconName","size","onPress","disabled","rounded","showSmallTitleInBar","showBigTitleRow","headerContent","styles","headerContentSecondary","slot","leftSlot","titleContainer","pointerEvents","color","foreground","numberOfLines","ellipsizeMode","rightSlot","titleRow","titleSecondary","staticHeaderStyle","header","backgroundColor","background","borderBottomColor","border","paddingTop","headerSecondary","create","borderBottomWidth","paddingHorizontal","flexDirection","alignItems","justifyContent","width","medium","flex","textAlign","marginHorizontal"],"sourceRoot":"../../../src","sources":["components/Header.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,6 @@
1
1
  import { type PropsWithChildren } from 'react';
2
2
  import { type ViewStyle, type StyleProp } from 'react-native';
3
+ import { type SharedValue } from 'react-native-reanimated';
3
4
  import { type IconName } from './Icon';
4
5
  import type { ButtonVariant } from './ButtonContainer';
5
6
  export type HeaderVariant = 'default' | 'secondary';
@@ -17,7 +18,11 @@ type Props = PropsWithChildren & {
17
18
  rightButton?: HeaderButtonProps;
18
19
  style?: StyleProp<ViewStyle>;
19
20
  useInsets?: boolean;
21
+ /** When set with variant="secondary", header animates from large title to compact as user scrolls (iOS-style). Pass the scroll view's contentOffset.y (e.g. from useAnimatedScrollHandler). */
22
+ scrollY?: SharedValue<number>;
23
+ /** Scroll offset at which the header is fully collapsed. Ignored when scrollY is not provided. */
24
+ collapseThreshold?: number;
20
25
  };
21
- export default function Header({ title, variant, leftButton, rightButton, style, useInsets, children, }: Props): import("react/jsx-runtime").JSX.Element;
26
+ export default function Header({ title, variant, leftButton, rightButton, style, useInsets, children, scrollY, collapseThreshold, }: Props): import("react/jsx-runtime").JSX.Element;
22
27
  export {};
23
28
  //# sourceMappingURL=Header.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../../src/components/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAoB,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAIhF,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAKvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,CAAC;AAEpD,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,OAAO,aAAa,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,KAAK,KAAK,GAAG,iBAAiB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAIF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,KAAK,EACL,OAAmB,EACnB,UAAU,EACV,WAAW,EACX,KAAK,EACL,SAAgB,EAChB,QAAQ,GACT,EAAE,KAAK,2CAwEP"}
1
+ {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../../src/components/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAoB,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAChF,OAAiB,EAGf,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAKvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,CAAC;AAIpD,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,OAAO,aAAa,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,KAAK,KAAK,GAAG,iBAAiB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+LAA+L;IAC/L,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B,kGAAkG;IAClG,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAIF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,KAAK,EACL,OAAmB,EACnB,UAAU,EACV,WAAW,EACX,KAAK,EACL,SAAgB,EAChB,QAAQ,EACR,OAAO,EACP,iBAA8C,GAC/C,EAAE,KAAK,2CAoKP"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@space-uy/pulsar-ui",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "react native ui kit for spacedev",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",
@@ -1,5 +1,10 @@
1
1
  import { type PropsWithChildren } from 'react';
2
2
  import { StyleSheet, View, type ViewStyle, type StyleProp } from 'react-native';
3
+ import Animated, {
4
+ interpolate,
5
+ useAnimatedStyle,
6
+ type SharedValue,
7
+ } from 'react-native-reanimated';
3
8
 
4
9
  import Text from './Text';
5
10
  import IconButton from './IconButton';
@@ -12,6 +17,8 @@ import type { ButtonVariant } from './ButtonContainer';
12
17
 
13
18
  export type HeaderVariant = 'default' | 'secondary';
14
19
 
20
+ const DEFAULT_COLLAPSE_THRESHOLD = 80;
21
+
15
22
  type HeaderButtonProps = {
16
23
  iconName: IconName;
17
24
  onPress?: () => void;
@@ -27,6 +34,10 @@ type Props = PropsWithChildren & {
27
34
  rightButton?: HeaderButtonProps;
28
35
  style?: StyleProp<ViewStyle>;
29
36
  useInsets?: boolean;
37
+ /** When set with variant="secondary", header animates from large title to compact as user scrolls (iOS-style). Pass the scroll view's contentOffset.y (e.g. from useAnimatedScrollHandler). */
38
+ scrollY?: SharedValue<number>;
39
+ /** Scroll offset at which the header is fully collapsed. Ignored when scrollY is not provided. */
40
+ collapseThreshold?: number;
30
41
  };
31
42
 
32
43
  const HEADER_BASE_HEIGHT = 52;
@@ -39,10 +50,57 @@ export default function Header({
39
50
  style,
40
51
  useInsets = true,
41
52
  children,
53
+ scrollY,
54
+ collapseThreshold = DEFAULT_COLLAPSE_THRESHOLD,
42
55
  }: Props) {
43
56
  const { colors, theme } = useTheme();
44
57
  const topInset = useInsets ? theme.insets?.top || 0 : 0;
45
58
  const isSecondary = variant === 'secondary';
59
+ const isCollapsible = isSecondary && scrollY != null;
60
+
61
+ const animatedHeaderStyle = useAnimatedStyle(() => {
62
+ if (!isCollapsible || scrollY == null) return {};
63
+ const progress = interpolate(
64
+ scrollY.value,
65
+ [0, collapseThreshold],
66
+ [0, 1],
67
+ 'clamp'
68
+ );
69
+ return {
70
+ paddingBottom: interpolate(progress, [0, 1], [12, 0]),
71
+ };
72
+ }, [isCollapsible, collapseThreshold]);
73
+
74
+ const animatedTitleRowStyle = useAnimatedStyle(() => {
75
+ if (!isCollapsible || scrollY == null) return {};
76
+ const progress = interpolate(
77
+ scrollY.value,
78
+ [0, collapseThreshold],
79
+ [0, 1],
80
+ 'clamp'
81
+ );
82
+ // Estimate: h1 fontSize 24 + line height ~16 + paddingTop 4 = ~44px
83
+ const titleRowHeight = 44;
84
+ return {
85
+ opacity: interpolate(progress, [0, 1], [1, 0]),
86
+ height: interpolate(progress, [0, 1], [titleRowHeight, 0]),
87
+ overflow: 'hidden' as const,
88
+ transform: [{ translateY: interpolate(progress, [0, 1], [0, -16]) }],
89
+ };
90
+ }, [isCollapsible, collapseThreshold]);
91
+
92
+ const animatedSmallTitleStyle = useAnimatedStyle(() => {
93
+ if (!isCollapsible || scrollY == null) return {};
94
+ const progress = interpolate(
95
+ scrollY.value,
96
+ [0, collapseThreshold],
97
+ [0, 1],
98
+ 'clamp'
99
+ );
100
+ return {
101
+ opacity: interpolate(progress, [0, 1], [0, 1]),
102
+ };
103
+ }, [isCollapsible, collapseThreshold]);
46
104
 
47
105
  const renderButton = (button: HeaderButtonProps) => {
48
106
  return (
@@ -57,57 +115,104 @@ export default function Header({
57
115
  );
58
116
  };
59
117
 
60
- return (
61
- <View
62
- style={[
63
- styles.header,
64
- {
65
- backgroundColor: colors.background,
66
- borderBottomColor: colors.border,
67
- paddingTop: topInset,
68
- },
69
- isSecondary && styles.headerSecondary,
70
- !!children && styles.paddingBottom,
71
- style,
72
- ]}
73
- >
118
+ const showSmallTitleInBar = !isSecondary || isCollapsible;
119
+ const showBigTitleRow = isSecondary;
120
+
121
+ const headerContent = (
122
+ <>
74
123
  <View
75
124
  style={[
76
125
  styles.headerContent,
77
- isSecondary && styles.headerContentSecondary,
126
+ isSecondary && !isCollapsible && styles.headerContentSecondary,
127
+ isCollapsible && styles.headerContentSecondary,
78
128
  ]}
79
129
  >
80
130
  <View style={[styles.slot, styles.leftSlot]}>
81
131
  {leftButton && renderButton(leftButton)}
82
132
  </View>
83
- {!isSecondary && (
84
- <View style={styles.titleContainer}>
133
+ {showSmallTitleInBar && (
134
+ <View style={styles.titleContainer} pointerEvents="none">
135
+ {isCollapsible ? (
136
+ <Animated.View
137
+ style={[styles.titleContainer, animatedSmallTitleStyle]}
138
+ >
139
+ <Text
140
+ variant="h3"
141
+ style={[styles.title, { color: colors.foreground }]}
142
+ numberOfLines={1}
143
+ ellipsizeMode="tail"
144
+ >
145
+ {title}
146
+ </Text>
147
+ </Animated.View>
148
+ ) : (
149
+ <Text
150
+ variant="h3"
151
+ style={[styles.title, { color: colors.foreground }]}
152
+ numberOfLines={1}
153
+ ellipsizeMode="tail"
154
+ >
155
+ {title}
156
+ </Text>
157
+ )}
158
+ </View>
159
+ )}
160
+ <View style={[styles.slot, styles.rightSlot]}>
161
+ {rightButton && renderButton(rightButton)}
162
+ </View>
163
+ </View>
164
+ {showBigTitleRow &&
165
+ (isCollapsible ? (
166
+ <Animated.View style={[styles.titleRow, animatedTitleRowStyle]}>
167
+ <Text
168
+ variant="h1"
169
+ style={[styles.titleSecondary, { color: colors.foreground }]}
170
+ numberOfLines={1}
171
+ ellipsizeMode="tail"
172
+ >
173
+ {title}
174
+ </Text>
175
+ </Animated.View>
176
+ ) : (
177
+ <View style={styles.titleRow}>
85
178
  <Text
86
- variant="h3"
87
- style={[styles.title, { color: colors.foreground }]}
179
+ variant="h1"
180
+ style={[styles.titleSecondary, { color: colors.foreground }]}
88
181
  numberOfLines={1}
89
182
  ellipsizeMode="tail"
90
183
  >
91
184
  {title}
92
185
  </Text>
93
186
  </View>
94
- )}
95
- <View style={[styles.slot, styles.rightSlot]}>
96
- {rightButton && renderButton(rightButton)}
97
- </View>
98
- </View>
99
- {isSecondary && (
100
- <View style={styles.titleRow}>
101
- <Text
102
- variant="h2"
103
- style={[styles.titleSecondary, { color: colors.foreground }]}
104
- numberOfLines={1}
105
- ellipsizeMode="tail"
106
- >
107
- {title}
108
- </Text>
109
- </View>
110
- )}
187
+ ))}
188
+ </>
189
+ );
190
+
191
+ const staticHeaderStyle = [
192
+ styles.header,
193
+ {
194
+ backgroundColor: colors.background,
195
+ borderBottomColor: colors.border,
196
+ paddingTop: topInset,
197
+ },
198
+ isSecondary && !isCollapsible && styles.headerSecondary,
199
+ isCollapsible && styles.headerSecondary,
200
+ !!children && styles.paddingBottom,
201
+ style,
202
+ ];
203
+
204
+ if (isCollapsible) {
205
+ return (
206
+ <Animated.View style={[staticHeaderStyle, animatedHeaderStyle]}>
207
+ {headerContent}
208
+ {children}
209
+ </Animated.View>
210
+ );
211
+ }
212
+
213
+ return (
214
+ <View style={staticHeaderStyle}>
215
+ {headerContent}
111
216
  {children}
112
217
  </View>
113
218
  );