jfs-components 0.0.3 → 0.0.5

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.
Files changed (128) hide show
  1. package/lib/commonjs/Containers.js +16 -7
  2. package/lib/commonjs/Containers.js.map +1 -1
  3. package/lib/commonjs/components/Accordion/Accordion.js +217 -0
  4. package/lib/commonjs/components/Accordion/Accordion.js.map +1 -0
  5. package/lib/commonjs/components/Accordion/Accordion.mdx +123 -0
  6. package/lib/commonjs/components/ActionFooter/ActionFooter.mdx +1 -0
  7. package/lib/commonjs/components/ActionTile/ActionTile.js +93 -0
  8. package/lib/commonjs/components/ActionTile/ActionTile.js.map +1 -0
  9. package/lib/commonjs/components/ActionTile/ActionTile.mdx +54 -0
  10. package/lib/commonjs/components/ActionTile/index.js +14 -0
  11. package/lib/commonjs/components/ActionTile/index.js.map +1 -0
  12. package/lib/commonjs/components/CtaCard/CtaCard.js +122 -0
  13. package/lib/commonjs/components/CtaCard/CtaCard.js.map +1 -0
  14. package/lib/commonjs/components/CtaCard/CtaCard.mdx +65 -0
  15. package/lib/commonjs/components/CtaCard/index.js +14 -0
  16. package/lib/commonjs/components/CtaCard/index.js.map +1 -0
  17. package/lib/commonjs/components/Introduction.mdx +0 -1
  18. package/lib/commonjs/components/ThreadHero/ThreadHero.js +114 -0
  19. package/lib/commonjs/components/ThreadHero/ThreadHero.js.map +1 -0
  20. package/lib/commonjs/components/ThreadHero/ThreadHero.mdx +69 -0
  21. package/lib/commonjs/components/TransactionBubble/TransactionBubble.js +101 -0
  22. package/lib/commonjs/components/TransactionBubble/TransactionBubble.js.map +1 -0
  23. package/lib/commonjs/components/TransactionBubble/TransactionBubble.mdx +40 -0
  24. package/lib/commonjs/components/TransactionDetails/TransactionDetails.js +177 -0
  25. package/lib/commonjs/components/TransactionDetails/TransactionDetails.js.map +1 -0
  26. package/lib/commonjs/components/TransactionDetails/TransactionDetails.mdx +98 -0
  27. package/lib/commonjs/components/TransactionStatus/TransactionStatus.js +82 -0
  28. package/lib/commonjs/components/TransactionStatus/TransactionStatus.js.map +1 -0
  29. package/lib/commonjs/components/TransactionStatus/TransactionStatus.mdx +41 -0
  30. package/lib/commonjs/components/index.js +35 -0
  31. package/lib/commonjs/components/index.js.map +1 -1
  32. package/lib/commonjs/design-tokens/JFSThemeProvider.js +64 -0
  33. package/lib/commonjs/design-tokens/JFSThemeProvider.js.map +1 -0
  34. package/lib/commonjs/design-tokens/figma-variables-resolver.js +3 -9
  35. package/lib/commonjs/design-tokens/index.js +11 -0
  36. package/lib/commonjs/design-tokens/index.js.map +1 -1
  37. package/lib/commonjs/icons/registry.js +1 -1
  38. package/lib/module/Containers.js +15 -7
  39. package/lib/module/Containers.js.map +1 -1
  40. package/lib/module/components/Accordion/Accordion.js +212 -0
  41. package/lib/module/components/Accordion/Accordion.js.map +1 -0
  42. package/lib/module/components/Accordion/Accordion.mdx +123 -0
  43. package/lib/module/components/ActionFooter/ActionFooter.mdx +1 -0
  44. package/lib/module/components/ActionTile/ActionTile.js +88 -0
  45. package/lib/module/components/ActionTile/ActionTile.js.map +1 -0
  46. package/lib/module/components/ActionTile/ActionTile.mdx +54 -0
  47. package/lib/module/components/ActionTile/index.js +4 -0
  48. package/lib/module/components/ActionTile/index.js.map +1 -0
  49. package/lib/module/components/CtaCard/CtaCard.js +117 -0
  50. package/lib/module/components/CtaCard/CtaCard.js.map +1 -0
  51. package/lib/module/components/CtaCard/CtaCard.mdx +65 -0
  52. package/lib/module/components/CtaCard/index.js +4 -0
  53. package/lib/module/components/CtaCard/index.js.map +1 -0
  54. package/lib/module/components/Introduction.mdx +0 -1
  55. package/lib/module/components/ThreadHero/ThreadHero.js +109 -0
  56. package/lib/module/components/ThreadHero/ThreadHero.js.map +1 -0
  57. package/lib/module/components/ThreadHero/ThreadHero.mdx +69 -0
  58. package/lib/module/components/TransactionBubble/TransactionBubble.js +96 -0
  59. package/lib/module/components/TransactionBubble/TransactionBubble.js.map +1 -0
  60. package/lib/module/components/TransactionBubble/TransactionBubble.mdx +40 -0
  61. package/lib/module/components/TransactionDetails/TransactionDetails.js +174 -0
  62. package/lib/module/components/TransactionDetails/TransactionDetails.js.map +1 -0
  63. package/lib/module/components/TransactionDetails/TransactionDetails.mdx +98 -0
  64. package/lib/module/components/TransactionStatus/TransactionStatus.js +77 -0
  65. package/lib/module/components/TransactionStatus/TransactionStatus.js.map +1 -0
  66. package/lib/module/components/TransactionStatus/TransactionStatus.mdx +41 -0
  67. package/lib/module/components/index.js +5 -0
  68. package/lib/module/components/index.js.map +1 -1
  69. package/lib/module/design-tokens/JFSThemeProvider.js +57 -0
  70. package/lib/module/design-tokens/JFSThemeProvider.js.map +1 -0
  71. package/lib/module/design-tokens/index.js +1 -0
  72. package/lib/module/design-tokens/index.js.map +1 -1
  73. package/lib/module/icons/registry.js +1 -1
  74. package/lib/typescript/Containers.d.ts +2 -1
  75. package/lib/typescript/Containers.d.ts.map +1 -1
  76. package/lib/typescript/components/Accordion/Accordion.d.ts +58 -0
  77. package/lib/typescript/components/Accordion/Accordion.d.ts.map +1 -0
  78. package/lib/typescript/components/ActionTile/ActionTile.d.ts +26 -0
  79. package/lib/typescript/components/ActionTile/ActionTile.d.ts.map +1 -0
  80. package/lib/typescript/components/ActionTile/index.d.ts +2 -0
  81. package/lib/typescript/components/ActionTile/index.d.ts.map +1 -0
  82. package/lib/typescript/components/CtaCard/CtaCard.d.ts +61 -0
  83. package/lib/typescript/components/CtaCard/CtaCard.d.ts.map +1 -0
  84. package/lib/typescript/components/CtaCard/index.d.ts +2 -0
  85. package/lib/typescript/components/CtaCard/index.d.ts.map +1 -0
  86. package/lib/typescript/components/ThreadHero/ThreadHero.d.ts +21 -0
  87. package/lib/typescript/components/ThreadHero/ThreadHero.d.ts.map +1 -0
  88. package/lib/typescript/components/TransactionBubble/TransactionBubble.d.ts +24 -0
  89. package/lib/typescript/components/TransactionBubble/TransactionBubble.d.ts.map +1 -0
  90. package/lib/typescript/components/TransactionDetails/TransactionDetails.d.ts +57 -0
  91. package/lib/typescript/components/TransactionDetails/TransactionDetails.d.ts.map +1 -0
  92. package/lib/typescript/components/TransactionStatus/TransactionStatus.d.ts +16 -0
  93. package/lib/typescript/components/TransactionStatus/TransactionStatus.d.ts.map +1 -0
  94. package/lib/typescript/components/index.d.ts +5 -0
  95. package/lib/typescript/components/index.d.ts.map +1 -1
  96. package/lib/typescript/design-tokens/JFSThemeProvider.d.ts +44 -0
  97. package/lib/typescript/design-tokens/JFSThemeProvider.d.ts.map +1 -0
  98. package/lib/typescript/design-tokens/index.d.ts +1 -0
  99. package/lib/typescript/design-tokens/index.d.ts.map +1 -1
  100. package/lib/typescript/icons/registry.d.ts +1 -1
  101. package/package.json +3 -4
  102. package/src/Containers.tsx +15 -0
  103. package/src/components/.token-metadata.json +161 -0
  104. package/src/components/Accordion/Accordion.mdx +123 -0
  105. package/src/components/Accordion/Accordion.tsx +279 -0
  106. package/src/components/ActionFooter/ActionFooter.mdx +1 -0
  107. package/src/components/ActionTile/ActionTile.mdx +54 -0
  108. package/src/components/ActionTile/ActionTile.tsx +100 -0
  109. package/src/components/ActionTile/index.ts +1 -0
  110. package/src/components/CtaCard/CtaCard.mdx +65 -0
  111. package/src/components/CtaCard/CtaCard.tsx +185 -0
  112. package/src/components/CtaCard/index.ts +1 -0
  113. package/src/components/Divider/Divider.tsx +1 -0
  114. package/src/components/Introduction.mdx +0 -1
  115. package/src/components/NavArrow/NavArrow.tsx +1 -0
  116. package/src/components/ThreadHero/ThreadHero.mdx +69 -0
  117. package/src/components/ThreadHero/ThreadHero.tsx +124 -0
  118. package/src/components/TransactionBubble/TransactionBubble.mdx +40 -0
  119. package/src/components/TransactionBubble/TransactionBubble.tsx +113 -0
  120. package/src/components/TransactionDetails/TransactionDetails.mdx +98 -0
  121. package/src/components/TransactionDetails/TransactionDetails.tsx +236 -0
  122. package/src/components/TransactionStatus/TransactionStatus.mdx +41 -0
  123. package/src/components/TransactionStatus/TransactionStatus.tsx +94 -0
  124. package/src/components/index.ts +5 -0
  125. package/src/design-tokens/JFSThemeProvider.tsx +79 -0
  126. package/src/design-tokens/index.ts +1 -0
  127. package/src/icons/registry.ts +1 -1
  128. package/src/Containers.ts +0 -8
@@ -0,0 +1,100 @@
1
+ import React from 'react'
2
+ import { View, Text, type ViewStyle, type TextStyle, TouchableOpacity } from 'react-native'
3
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
+ import IconCapsule from '../IconCapsule/IconCapsule'
5
+
6
+ export type ActionTileProps = {
7
+ /** Label text, e.g. "Cards" */
8
+ label?: string
9
+ /**
10
+ * Icon component slot.
11
+ * Expects an IconCapsule or compatible component.
12
+ * Modes will be passed to this slot if it's a valid React element.
13
+ */
14
+ icon?: React.ReactNode
15
+ /** Modes for design token resolution */
16
+ modes?: Record<string, any>
17
+ /** Optional container style */
18
+ style?: ViewStyle
19
+ /** Callback when tile is pressed */
20
+ onPress?: () => void
21
+ }
22
+
23
+ /**
24
+ * ActionTile component from Figma design.
25
+ * Displays an icon (defaulting to IconCapsule) and a label.
26
+ *
27
+ * @component
28
+ */
29
+ export default function ActionTile({
30
+ label = 'Cards',
31
+ icon,
32
+ modes = {},
33
+ style,
34
+ onPress,
35
+ }: ActionTileProps) {
36
+ // Resolve tokens
37
+ const backgroundColor = getVariableByName('actionTile/background', modes) || '#ffffff'
38
+ const gap = Number(getVariableByName('actionTile/gap', modes)) || 8
39
+ const paddingHorizontal = Number(getVariableByName('actionTile/padding/horizontal', modes)) || 12
40
+ const paddingVertical = Number(getVariableByName('actionTile/padding/vertical', modes)) || 16
41
+ const radius = Number(getVariableByName('actionTile/radius', modes)) || 16
42
+
43
+ // Text tokens
44
+ const textColor = getVariableByName('actionTile/foreground', modes) || '#0d0d0f'
45
+ const fontSize = Number(getVariableByName('actionTile/fontSize', modes)) || 14
46
+ const fontFamily = getVariableByName('actionTile/fontFamily', modes) || 'JioType Var'
47
+ const fontWeightStr = getVariableByName('actionTile/fontWeight', modes) || '500'
48
+ const lineHeight = Number(getVariableByName('actionTile/lineHeight', modes)) || 17
49
+
50
+ const containerStyle: ViewStyle = {
51
+ backgroundColor,
52
+ borderRadius: radius,
53
+ paddingHorizontal,
54
+ paddingVertical,
55
+ gap,
56
+ width: 168, // Fixed width from design
57
+ height: 90, // Fixed height from design
58
+ alignItems: 'flex-start',
59
+ // ensure content stretches if needed, though design implies fixed size block
60
+ ...style,
61
+ }
62
+
63
+ const textStyle: TextStyle = {
64
+ color: textColor,
65
+ fontSize,
66
+ fontFamily,
67
+ fontWeight: fontWeightStr as any, // Cast to any or TextStyle fontWeight enum if needed
68
+ lineHeight,
69
+ }
70
+
71
+ // Handle Icon Slot: Pass modes safely
72
+ const renderIcon = () => {
73
+ if (React.isValidElement(icon)) {
74
+ // Pass modes down to the slot child
75
+ return React.cloneElement(icon as React.ReactElement<any>, { modes })
76
+ }
77
+ // Default fallback if no icon prop is provided, matching design default
78
+ if (!icon) {
79
+ return <IconCapsule modes={modes} />
80
+ }
81
+ return icon
82
+ }
83
+
84
+ const Content = (
85
+ <View style={containerStyle}>
86
+ {renderIcon()}
87
+ <Text style={textStyle}>{label}</Text>
88
+ </View>
89
+ )
90
+
91
+ if (onPress) {
92
+ return (
93
+ <TouchableOpacity onPress={onPress}>
94
+ {Content}
95
+ </TouchableOpacity>
96
+ )
97
+ }
98
+
99
+ return Content
100
+ }
@@ -0,0 +1 @@
1
+ export { default } from './ActionTile'
@@ -0,0 +1,65 @@
1
+ import { Meta, Story, Canvas, PureArgsTable as ArgsTable } from '@storybook/addon-docs/blocks';
2
+ import * as CtaCardStories from './CtaCard.stories';
3
+ import CtaCard from './CtaCard';
4
+
5
+ <Meta of={CtaCardStories} />
6
+
7
+ # CtaCard
8
+
9
+ `CtaCard` is a component used to display a Call-to-Action with an icon, title, body text, and a button.
10
+ It is designed to be flexible, allowing content to be passed via props or fully customized via slots.
11
+
12
+
13
+ ## Available Collections and Modes
14
+
15
+ This component does not use any design token collections with multiple modes.
16
+ ## Usage
17
+
18
+ ```tsx
19
+ import { CtaCard } from 'jfs-components'; // Adjust import based on your package structure
20
+
21
+ // Basic Usage
22
+ <CtaCard
23
+ title="Lets create your UPI ID"
24
+ body="Send and receive money securely."
25
+ iconName="ic_upi_number"
26
+ buttonLabel="Get started"
27
+ onPressButton={() => console.log('Pressed')}
28
+ />
29
+
30
+ // Using Slots
31
+ <CtaCard
32
+ titleSlot={<CustomTitle />}
33
+ buttonSlot={<CustomButton />}
34
+ />
35
+ ```
36
+
37
+ <Canvas>
38
+ <Story of={CtaCardStories.Default} />
39
+ </Canvas>
40
+
41
+ ## Props
42
+
43
+ <ArgsTable of={CtaCard} />
44
+
45
+
46
+ ## Design Tokens
47
+
48
+ This component uses the following design tokens, resolved through `getVariableByName`:
49
+
50
+ - **`ctaCard/background`**
51
+ - **`ctaCard/body/color`**
52
+ - **`ctaCard/body/fontFamily`**
53
+ - **`ctaCard/body/fontSize`**
54
+ - **`ctaCard/body/lineHeight`**
55
+ - **`ctaCard/content/gap`**
56
+ - **`ctaCard/gap`**
57
+ - **`ctaCard/padding/horizontal`**
58
+ - **`ctaCard/padding/vertical`**
59
+ - **`ctaCard/radius`**
60
+ - **`ctaCard/title/color`**
61
+ - **`ctaCard/title/fontFamily`**
62
+ - **`ctaCard/title/fontSize`**
63
+ - **`ctaCard/title/lineHeight`**
64
+
65
+ All tokens support mode-based theming through the `modes` prop.
@@ -0,0 +1,185 @@
1
+ import React from 'react';
2
+ import { View, Text, type StyleProp, type ViewStyle, type TextStyle } from 'react-native';
3
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
4
+ import IconCapsule from '../IconCapsule/IconCapsule';
5
+ import Button from '../Button/Button';
6
+
7
+ type CtaCardProps = {
8
+ /**
9
+ * Title text for the card
10
+ */
11
+ title?: string;
12
+ /**
13
+ * Body text for the card
14
+ */
15
+ body?: string;
16
+ /**
17
+ * Name of the icon to display in the IconCapsule (if iconSlot is not provided)
18
+ */
19
+ iconName?: string;
20
+ /**
21
+ * Label for the button (if buttonSlot is not provided)
22
+ */
23
+ buttonLabel?: string;
24
+ /**
25
+ * Callback for the button press (if buttonSlot is not provided)
26
+ */
27
+ onPressButton?: () => void;
28
+ /**
29
+ * Modes object for design token resolution
30
+ */
31
+ modes?: Record<string, any>;
32
+ /**
33
+ * Optional custom slot for the icon area.
34
+ * If provided, overrides the default IconCapsule.
35
+ * `modes` will be automatically passed to this slot if it's a valid React element.
36
+ */
37
+ iconSlot?: React.ReactNode;
38
+ /**
39
+ * Optional custom slot for the title area.
40
+ * If provided, overrides the default title Text.
41
+ * `modes` will be automatically passed to this slot if it's a valid React element.
42
+ */
43
+ titleSlot?: React.ReactNode;
44
+ /**
45
+ * Optional custom slot for the body area.
46
+ * If provided, overrides the default body Text.
47
+ * `modes` will be automatically passed to this slot if it's a valid React element.
48
+ */
49
+ bodySlot?: React.ReactNode;
50
+ /**
51
+ * Optional custom slot for the button area.
52
+ * If provided, overrides the default Button.
53
+ * `modes` will be automatically passed to this slot if it's a valid React element.
54
+ */
55
+ buttonSlot?: React.ReactNode;
56
+
57
+ style?: StyleProp<ViewStyle>;
58
+ };
59
+
60
+ /**
61
+ * CtaCard component that maps directly to the Figma design using design tokens.
62
+ *
63
+ * @component
64
+ */
65
+ function CtaCard({
66
+ title = "Lets create your UPI ID",
67
+ body = "Send and receive money securely.",
68
+ iconName = "ic_upi_number",
69
+ buttonLabel = "Get started",
70
+ onPressButton,
71
+ modes = {},
72
+ iconSlot,
73
+ titleSlot,
74
+ bodySlot,
75
+ buttonSlot,
76
+ style,
77
+ }: CtaCardProps) {
78
+ // --- Token Resolution ---
79
+ // Container
80
+ const backgroundColor = getVariableByName('ctaCard/background', modes) || '#0078ad';
81
+ const radius = getVariableByName('ctaCard/radius', modes) || 16;
82
+ const paddingHorizontal = getVariableByName('ctaCard/padding/horizontal', modes) || 20;
83
+ const paddingVertical = getVariableByName('ctaCard/padding/vertical', modes) || 23;
84
+ const gap = getVariableByName('ctaCard/gap', modes) || 16;
85
+
86
+ // Content Wrap
87
+ const contentGap = getVariableByName('ctaCard/content/gap', modes) || 8;
88
+
89
+ // Title Text
90
+ const titleColor = getVariableByName('ctaCard/title/color', modes) || '#ffffff';
91
+ const titleFontFamily = getVariableByName('ctaCard/title/fontFamily', modes) || 'JioType Var';
92
+ const titleFontSize = getVariableByName('ctaCard/title/fontSize', modes) || 23;
93
+ const titleLineHeight = getVariableByName('ctaCard/title/lineHeight', modes) || 23;
94
+
95
+ // Body Text
96
+ const bodyColor = getVariableByName('ctaCard/body/color', modes) || '#ffffff';
97
+ const bodyFontFamily = getVariableByName('ctaCard/body/fontFamily', modes) || 'JioType Var';
98
+ const bodyFontSize = getVariableByName('ctaCard/body/fontSize', modes) || 14;
99
+ const bodyLineHeight = getVariableByName('ctaCard/body/lineHeight', modes) || 17;
100
+
101
+ // --- Styles ---
102
+ const containerStyle: ViewStyle = {
103
+ backgroundColor,
104
+ borderRadius: radius,
105
+ paddingHorizontal,
106
+ paddingVertical,
107
+ gap,
108
+ alignItems: 'flex-start',
109
+ width: '100%', // Adjust based on layout needs, usually cards take full width available
110
+ overflow: 'hidden',
111
+ };
112
+
113
+ const contentWrapStyle: ViewStyle = {
114
+ gap: contentGap,
115
+ alignItems: 'flex-start',
116
+ width: '100%',
117
+ };
118
+
119
+ const titleStyle: TextStyle = {
120
+ color: titleColor,
121
+ fontFamily: titleFontFamily,
122
+ fontSize: titleFontSize,
123
+ lineHeight: titleLineHeight,
124
+ fontWeight: '900', // "Black" in Figma often maps to 900
125
+ };
126
+
127
+ const bodyStyle: TextStyle = {
128
+ color: bodyColor,
129
+ fontFamily: bodyFontFamily,
130
+ fontSize: bodyFontSize,
131
+ lineHeight: bodyLineHeight,
132
+ fontWeight: '400', // Regular
133
+ };
134
+
135
+ // --- Slot Helper ---
136
+ // Helper to clone element with modes if no modes are already present on it (standard in this library)
137
+ const renderSlot = (slot: React.ReactNode) => {
138
+ if (React.isValidElement(slot)) {
139
+ return React.cloneElement(slot as React.ReactElement<any>, {
140
+ modes: { ...modes, ...(slot as any).props.modes },
141
+ });
142
+ }
143
+ return slot;
144
+ };
145
+
146
+ return (
147
+ <View style={[containerStyle, style]}>
148
+ <View style={contentWrapStyle}>
149
+ {/* Icon Slot */}
150
+ {iconSlot ? (
151
+ renderSlot(iconSlot)
152
+ ) : (
153
+ <IconCapsule iconName={iconName} modes={modes} />
154
+ )}
155
+
156
+ {/* Title Slot */}
157
+ {titleSlot ? (
158
+ renderSlot(titleSlot)
159
+ ) : (
160
+ <Text style={titleStyle}>{title}</Text>
161
+ )}
162
+
163
+ {/* Body Slot */}
164
+ {bodySlot ? (
165
+ renderSlot(bodySlot)
166
+ ) : (
167
+ <Text style={bodyStyle}>{body}</Text>
168
+ )}
169
+ </View>
170
+
171
+ {/* Button Slot - placed outside content wrap based on Figma structure (flex-col gap=16) */}
172
+ {buttonSlot ? (
173
+ renderSlot(buttonSlot)
174
+ ) : (
175
+ <Button
176
+ label={buttonLabel}
177
+ onPress={onPressButton}
178
+ modes={modes}
179
+ />
180
+ )}
181
+ </View>
182
+ );
183
+ }
184
+
185
+ export default CtaCard;
@@ -0,0 +1 @@
1
+ export { default } from './CtaCard';
@@ -89,3 +89,4 @@ function Divider({
89
89
 
90
90
  export default Divider
91
91
 
92
+
@@ -95,7 +95,6 @@ When creating new components:
95
95
 
96
96
  - [Storybook Documentation](https://storybook.js.org/)
97
97
  - [React Native Storybook](https://github.com/storybookjs/react-native)
98
- - [Styled Components](https://styled-components.com/)
99
98
 
100
99
  ---
101
100
 
@@ -106,3 +106,4 @@ function NavArrow({
106
106
 
107
107
  export default NavArrow
108
108
 
109
+
@@ -0,0 +1,69 @@
1
+ import { Meta, Story, Canvas, PureArgsTable as ArgsTable } from '@storybook/addon-docs/blocks';
2
+ import * as ThreadHeroStories from './ThreadHero.stories';
3
+ import ThreadHero from './ThreadHero';
4
+
5
+ <Meta of={ThreadHeroStories} />
6
+
7
+ # ThreadHero
8
+
9
+ The `ThreadHero` component displays a central user identity with an avatar, title, subtitle, and an optional caption.
10
+
11
+
12
+ ## Available Collections and Modes
13
+
14
+ This component does not use any design token collections with multiple modes.
15
+ ## Usage
16
+
17
+ ```tsx
18
+ import ThreadHero from './ThreadHero';
19
+ import Avatar from '../Avatar/Avatar';
20
+
21
+ <ThreadHero
22
+ title="Subhash Rajan"
23
+ subtitle="Banking name: SHIVASHANKAR RAJAN"
24
+ caption="+91 00000 00000"
25
+ renderAvatar={<Avatar size="small" initials="SR" />}
26
+ />
27
+ ```
28
+
29
+ ## Props
30
+
31
+ <ArgsTable of={ThreadHero} />
32
+
33
+ ## Stories
34
+
35
+ ### Default
36
+
37
+ <Canvas>
38
+ <Story of={ThreadHeroStories.Default} />
39
+ </Canvas>
40
+
41
+ ### Without Caption
42
+
43
+ <Canvas>
44
+ <Story of={ThreadHeroStories.WithoutCaption} />
45
+ </Canvas>
46
+
47
+ ## Design Tokens
48
+
49
+ This component uses the following design tokens, resolved through `getVariableByName`:
50
+
51
+ - **`threadHero/caption/color`**
52
+ - **`threadHero/caption/fontFamily`**
53
+ - **`threadHero/caption/fontSize`**
54
+ - **`threadHero/caption/fontWeight`**
55
+ - **`threadHero/caption/lineHeight`**
56
+ - **`threadHero/details/gap`**
57
+ - **`threadHero/gap`**
58
+ - **`threadHero/subtitle/color`**
59
+ - **`threadHero/subtitle/fontFamily`**
60
+ - **`threadHero/subtitle/fontSize`**
61
+ - **`threadHero/subtitle/fontWeight`**
62
+ - **`threadHero/subtitle/lineHeight`**
63
+ - **`threadHero/title/color`**
64
+ - **`threadHero/title/fontFamily`**
65
+ - **`threadHero/title/fontSize`**
66
+ - **`threadHero/title/fontWeight`**
67
+ - **`threadHero/title/lineHeight`**
68
+
69
+ All tokens support mode-based theming through the `modes` prop.
@@ -0,0 +1,124 @@
1
+ import React, { isValidElement, cloneElement, type ReactNode } from 'react'
2
+ import { View, Text, type ViewStyle, type TextStyle } from 'react-native'
3
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
+
5
+ export type ThreadHeroProps = {
6
+ /** Title text, e.g. "Subhash Rajan" */
7
+ title?: string
8
+ /** Subtitle text, e.g. "Banking name: SHIVASHANKAR RAJAN" */
9
+ subtitle?: string
10
+ /** Optional caption text below the details, e.g. "+91 00000 00000" */
11
+ caption?: string
12
+ /** Slot for Avatar component */
13
+ renderAvatar?: ReactNode
14
+ /** Modes for design token resolution */
15
+ modes?: Record<string, any>
16
+ /** Optional container style */
17
+ style?: ViewStyle
18
+ }
19
+
20
+ /**
21
+ * ThreadHero component displaying a central identity with avatar, title, subtitle, and caption.
22
+ */
23
+ export default function ThreadHero({
24
+ title = 'Subhash Rajan',
25
+ subtitle = 'Banking name: SHIVASHANKAR RAJAN',
26
+ caption,
27
+ renderAvatar,
28
+ modes = {},
29
+ style,
30
+ }: ThreadHeroProps) {
31
+ // Container Gaps
32
+ const containerGap = Number(getVariableByName('threadHero/gap', modes)) || 8
33
+ const detailsGap = Number(getVariableByName('threadHero/details/gap', modes)) || 2
34
+
35
+ // Title Styles
36
+ const titleColor = getVariableByName('threadHero/title/color', modes) || '#191b1e'
37
+ const titleFontSize = Number(getVariableByName('threadHero/title/fontSize', modes)) || 16
38
+ const titleFontFamily = getVariableByName('threadHero/title/fontFamily', modes) || 'System'
39
+ const titleLineHeight = Number(getVariableByName('threadHero/title/lineHeight', modes)) || 20
40
+ const titleFontWeight = getVariableByName('threadHero/title/fontWeight', modes) || '600'
41
+
42
+ // Subtitle Styles
43
+ const subtitleColor = getVariableByName('threadHero/subtitle/color', modes) || '#5d5d61'
44
+ const subtitleFontSize = Number(getVariableByName('threadHero/subtitle/fontSize', modes)) || 12
45
+ const subtitleFontFamily = getVariableByName('threadHero/subtitle/fontFamily', modes) || 'System'
46
+ const subtitleLineHeight = Number(getVariableByName('threadHero/subtitle/lineHeight', modes)) || 18
47
+ const subtitleFontWeight = getVariableByName('threadHero/subtitle/fontWeight', modes) || '500'
48
+
49
+ // Caption Styles
50
+ const captionColor = getVariableByName('threadHero/caption/color', modes) || '#5d5d61'
51
+ const captionFontSize = Number(getVariableByName('threadHero/caption/fontSize', modes)) || 12
52
+ const captionFontFamily = getVariableByName('threadHero/caption/fontFamily', modes) || 'System'
53
+ const captionLineHeight = Number(getVariableByName('threadHero/caption/lineHeight', modes)) || 18
54
+ const captionFontWeight = getVariableByName('threadHero/caption/fontWeight', modes) || '500'
55
+
56
+ // Styles
57
+ const containerStyle: ViewStyle = {
58
+ flexDirection: 'column',
59
+ alignItems: 'center',
60
+ gap: containerGap,
61
+ ...style,
62
+ }
63
+
64
+ const detailsStyle: ViewStyle = {
65
+ flexDirection: 'column',
66
+ alignItems: 'center',
67
+ gap: detailsGap,
68
+ width: '100%',
69
+ }
70
+
71
+ const titleStyle: TextStyle = {
72
+ color: titleColor,
73
+ fontSize: titleFontSize,
74
+ fontFamily: titleFontFamily,
75
+ lineHeight: titleLineHeight,
76
+ fontWeight: titleFontWeight as any,
77
+ textAlign: 'center',
78
+ minWidth: '100%',
79
+ }
80
+
81
+ const subtitleStyle: TextStyle = {
82
+ color: subtitleColor,
83
+ fontSize: subtitleFontSize,
84
+ fontFamily: subtitleFontFamily,
85
+ lineHeight: subtitleLineHeight,
86
+ fontWeight: subtitleFontWeight as any,
87
+ textAlign: 'center',
88
+ minWidth: '100%',
89
+ }
90
+
91
+ const captionStyle: TextStyle = {
92
+ color: captionColor,
93
+ fontSize: captionFontSize,
94
+ fontFamily: captionFontFamily,
95
+ lineHeight: captionLineHeight,
96
+ fontWeight: captionFontWeight as any,
97
+ textAlign: 'center',
98
+ width: '100%',
99
+ }
100
+
101
+ // Process Avatar Slot to inject modes
102
+ const avatarContent = isValidElement(renderAvatar)
103
+ ? cloneElement(renderAvatar as React.ReactElement<any>, { modes })
104
+ : renderAvatar
105
+
106
+ return (
107
+ <View style={containerStyle}>
108
+ <View style={detailsStyle}>
109
+ {avatarContent}
110
+ {title ? <Text style={titleStyle}>{title}</Text> : null}
111
+ {subtitle ? (
112
+ <Text style={subtitleStyle} numberOfLines={1} ellipsizeMode="tail">
113
+ {subtitle}
114
+ </Text>
115
+ ) : null}
116
+ </View>
117
+ {caption ? (
118
+ <Text style={captionStyle} numberOfLines={1} ellipsizeMode="tail">
119
+ {caption}
120
+ </Text>
121
+ ) : null}
122
+ </View>
123
+ )
124
+ }
@@ -0,0 +1,40 @@
1
+ import { Meta, Story, Canvas, PureArgsTable as ArgsTable } from '@storybook/addon-docs/blocks';
2
+ import * as TransactionBubbleStories from './TransactionBubble.stories';
3
+ import TransactionBubble from './TransactionBubble';
4
+
5
+ <Meta of={TransactionBubbleStories} />
6
+
7
+ # TransactionBubble
8
+
9
+ TransactionBubble component with design-token-driven styling.
10
+
11
+ ## Available Collections and Modes
12
+
13
+ This component does not use any design token collections with multiple modes.
14
+ ## Usage
15
+
16
+ <Canvas>
17
+ <Story of={TransactionBubbleStories.Default} />
18
+ </Canvas>
19
+
20
+ ## Props
21
+
22
+ <ArgsTable of={TransactionBubble} />
23
+
24
+ ## Design Tokens
25
+
26
+ This component uses the following design tokens, resolved through `getVariableByName`:
27
+
28
+ - **`transactionBubble/background`**
29
+ - **`transactionBubble/border/color`**
30
+ - **`transactionBubble/border/size`**
31
+ - **`transactionBubble/description/color`**
32
+ - **`transactionBubble/description/fontFamily`**
33
+ - **`transactionBubble/description/fontSize`**
34
+ - **`transactionBubble/description/lineHeight`**
35
+ - **`transactionBubble/gap`**
36
+ - **`transactionBubble/padding`**
37
+ - **`transactionBubble/radius`**
38
+ - **`transactionBubble/statusWrap/height`**
39
+
40
+ All tokens support mode-based theming through the `modes` prop.