@idealyst/components 1.2.14 → 1.2.16

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 (50) hide show
  1. package/package.json +3 -3
  2. package/src/Accordion/Accordion.web.tsx +1 -1
  3. package/src/Alert/Alert.native.tsx +1 -1
  4. package/src/Alert/Alert.web.tsx +1 -1
  5. package/src/Badge/Badge.web.tsx +6 -2
  6. package/src/Badge/types.ts +5 -0
  7. package/src/Button/Button.native.tsx +3 -3
  8. package/src/Button/Button.web.tsx +5 -1
  9. package/src/Button/types.ts +5 -0
  10. package/src/Card/Card.web.tsx +4 -1
  11. package/src/Card/types.ts +5 -0
  12. package/src/Dialog/Dialog.native.tsx +1 -1
  13. package/src/Divider/Divider.web.tsx +2 -2
  14. package/src/Icon/Icon.web.tsx +2 -2
  15. package/src/Image/Image.styles.tsx +5 -5
  16. package/src/Image/Image.web.tsx +3 -3
  17. package/src/List/List.native.tsx +1 -2
  18. package/src/List/List.web.tsx +1 -2
  19. package/src/List/ListSection.web.tsx +3 -3
  20. package/src/Menu/Menu.web.tsx +8 -10
  21. package/src/Menu/MenuItem.web.tsx +1 -1
  22. package/src/Popover/Popover.web.tsx +1 -1
  23. package/src/Pressable/Pressable.web.tsx +1 -1
  24. package/src/Progress/Progress.styles.tsx +76 -30
  25. package/src/Progress/Progress.web.tsx +13 -15
  26. package/src/SVGImage/SVGImage.web.tsx +1 -1
  27. package/src/Select/Select.web.tsx +2 -2
  28. package/src/Slider/Slider.styles.tsx +131 -44
  29. package/src/Slider/Slider.web.tsx +22 -22
  30. package/src/Text/Text.web.tsx +29 -3
  31. package/src/Text/types.ts +14 -1
  32. package/src/TextArea/TextArea.styles.tsx +96 -57
  33. package/src/TextArea/TextArea.web.tsx +19 -28
  34. package/src/Tooltip/Tooltip.web.tsx +3 -3
  35. package/src/Video/Video.styles.tsx +3 -3
  36. package/src/Video/Video.web.tsx +1 -1
  37. package/src/View/View.styles.tsx +2 -2
  38. package/src/View/View.web.tsx +95 -9
  39. package/src/View/types.ts +5 -1
  40. package/src/examples/ViewExamples.tsx +34 -0
  41. package/src/extensions/index.ts +0 -7
  42. package/src/hooks/useMergeRefs.ts +12 -6
  43. package/src/utils/accessibility/keyboardPatterns.ts +4 -0
  44. package/src/utils/accessibility/types.ts +5 -1
  45. package/src/utils/accessibility/useAnnounce.ts +1 -1
  46. package/src/utils/accessibility/useKeyboardNavigation.ts +1 -1
  47. package/src/utils/index.ts +0 -3
  48. package/src/utils/viewStyleProps.ts +2 -0
  49. package/src/extensions/applyExtension.ts +0 -210
  50. package/src/utils/buildSizeVariants.ts +0 -16
@@ -258,7 +258,7 @@ const Select = forwardRef<HTMLDivElement, SelectProps>(({
258
258
  </div>
259
259
  <PositionedPortal
260
260
  open={isOpen}
261
- anchor={triggerRef}
261
+ anchor={triggerRef as React.RefObject<HTMLElement>}
262
262
  placement="bottom-start"
263
263
  offset={4}
264
264
  onClickOutside={handleClose}
@@ -280,12 +280,12 @@ const Select = forwardRef<HTMLDivElement, SelectProps>(({
280
280
  {searchable && (
281
281
  <div {...getWebProps([searchContainerStyle])}>
282
282
  <input
283
+ {...getWebProps([searchInputStyle])}
283
284
  ref={searchInputRef}
284
285
  type="text"
285
286
  placeholder="Search options..."
286
287
  value={searchTerm}
287
288
  onChange={handleSearchChange}
288
- {...getWebProps([searchInputStyle])}
289
289
  />
290
290
  </div>
291
291
  )}
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Slider styles using defineStyle with dynamic props.
2
+ * Slider styles using static styles with variants.
3
3
  */
4
4
  import { StyleSheet } from 'react-native-unistyles';
5
- import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
5
+ import { defineStyle, ThemeStyleWrapper, CompoundVariants } from '@idealyst/theme';
6
6
  import type { Theme as BaseTheme, Intent, Size } from '@idealyst/theme';
7
7
  import { ViewStyleSize } from '../utils/viewStyleProps';
8
8
 
@@ -12,20 +12,47 @@ void StyleSheet;
12
12
  // Wrap theme for $iterator support
13
13
  type Theme = ThemeStyleWrapper<BaseTheme>;
14
14
 
15
- export type SliderDynamicProps = {
16
- size?: Size;
17
- intent?: Intent;
18
- disabled?: boolean;
15
+ export type SliderVariants = {
16
+ size: Size;
17
+ intent: Intent;
18
+ disabled: boolean;
19
19
  margin?: ViewStyleSize;
20
20
  marginVertical?: ViewStyleSize;
21
21
  marginHorizontal?: ViewStyleSize;
22
22
  };
23
23
 
24
+ // Create intent variants dynamically from theme
25
+ function createIntentVariants(theme: Theme) {
26
+ const variants: Record<string, object> = {};
27
+ for (const intent in theme.intents) {
28
+ variants[intent] = {};
29
+ }
30
+ return variants;
31
+ }
32
+
33
+ // Create compound variants for intent-specific styles
34
+ function createSliderCompoundVariants(theme: Theme): CompoundVariants<keyof SliderVariants> {
35
+ const compoundVariants: CompoundVariants<keyof SliderVariants> = [];
36
+
37
+ for (const intent in theme.intents) {
38
+ const intentValue = theme.intents[intent as Intent];
39
+
40
+ // filledTrack intent colors are handled inline since they need per-element targeting
41
+ // thumb border color by intent
42
+ compoundVariants.push({
43
+ intent,
44
+ styles: {},
45
+ });
46
+ }
47
+
48
+ return compoundVariants;
49
+ }
50
+
24
51
  /**
25
- * Slider styles with intent/disabled handling.
52
+ * Slider styles with static styles and variants.
26
53
  */
27
54
  export const sliderStyles = defineStyle('Slider', (theme: Theme) => ({
28
- container: (_props: SliderDynamicProps) => ({
55
+ container: {
29
56
  gap: 4,
30
57
  paddingVertical: 8,
31
58
  variants: {
@@ -39,44 +66,67 @@ export const sliderStyles = defineStyle('Slider', (theme: Theme) => ({
39
66
  marginHorizontal: theme.sizes.$view.padding,
40
67
  },
41
68
  },
42
- }),
69
+ },
43
70
 
44
- sliderWrapper: (_props: SliderDynamicProps) => ({
71
+ sliderWrapper: {
45
72
  position: 'relative' as const,
46
73
  paddingVertical: 4,
47
- }),
74
+ },
48
75
 
49
- track: ({ disabled = false }: SliderDynamicProps) => ({
76
+ track: {
50
77
  backgroundColor: theme.colors.surface.tertiary,
51
78
  borderRadius: 9999,
52
79
  position: 'relative' as const,
53
- opacity: disabled ? 0.5 : 1,
54
80
  variants: {
55
81
  size: {
56
82
  height: theme.sizes.$slider.trackHeight,
57
83
  },
84
+ disabled: {
85
+ true: {
86
+ opacity: 0.5,
87
+ _web: {
88
+ cursor: 'not-allowed',
89
+ },
90
+ },
91
+ false: {
92
+ opacity: 1,
93
+ _web: {
94
+ cursor: 'pointer',
95
+ },
96
+ },
97
+ },
58
98
  },
59
- _web: {
60
- cursor: disabled ? 'not-allowed' : 'pointer',
61
- },
62
- }),
99
+ },
63
100
 
64
- filledTrack: ({ intent = 'primary' }: SliderDynamicProps) => ({
101
+ filledTrack: {
65
102
  position: 'absolute' as const,
66
103
  height: '100%',
67
104
  borderRadius: 9999,
68
105
  top: 0,
69
106
  left: 0,
70
- backgroundColor: theme.intents[intent].primary,
71
- }),
107
+ variants: {
108
+ intent: createIntentVariants(theme),
109
+ },
110
+ compoundVariants: (() => {
111
+ const cv: CompoundVariants<keyof SliderVariants> = [];
112
+ for (const intent in theme.intents) {
113
+ cv.push({
114
+ intent,
115
+ styles: {
116
+ backgroundColor: theme.intents[intent as Intent].primary,
117
+ },
118
+ });
119
+ }
120
+ return cv;
121
+ })(),
122
+ },
72
123
 
73
- thumb: ({ intent = 'primary', disabled = false }: SliderDynamicProps) => ({
124
+ thumb: {
74
125
  position: 'absolute' as const,
75
126
  backgroundColor: theme.colors.surface.primary,
76
127
  borderRadius: 9999,
77
128
  borderWidth: 2,
78
129
  borderStyle: 'solid' as const,
79
- borderColor: theme.intents[intent].primary,
80
130
  top: '50%',
81
131
  display: 'flex' as const,
82
132
  alignItems: 'center' as const,
@@ -86,35 +136,59 @@ export const sliderStyles = defineStyle('Slider', (theme: Theme) => ({
86
136
  shadowOpacity: 0.2,
87
137
  shadowRadius: 4,
88
138
  elevation: 2,
89
- opacity: disabled ? 0.6 : 1,
90
139
  variants: {
91
140
  size: {
92
141
  width: theme.sizes.$slider.thumbSize,
93
142
  height: theme.sizes.$slider.thumbSize,
94
143
  },
144
+ intent: createIntentVariants(theme),
145
+ disabled: {
146
+ true: {
147
+ opacity: 0.6,
148
+ _web: {
149
+ cursor: 'not-allowed',
150
+ },
151
+ },
152
+ false: {
153
+ opacity: 1,
154
+ _web: {
155
+ cursor: 'grab',
156
+ },
157
+ },
158
+ },
95
159
  },
160
+ compoundVariants: (() => {
161
+ const cv: CompoundVariants<keyof SliderVariants> = [];
162
+ for (const intent in theme.intents) {
163
+ cv.push({
164
+ intent,
165
+ styles: {
166
+ borderColor: theme.intents[intent as Intent].primary,
167
+ },
168
+ });
169
+ }
170
+ return cv;
171
+ })(),
96
172
  _web: {
97
173
  boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)',
98
174
  transform: 'translate(-50%, -50%)',
99
175
  transition: 'transform 0.15s ease, box-shadow 0.2s ease',
100
- cursor: disabled ? 'not-allowed' : 'grab',
101
- _hover: disabled ? {} : { transform: 'translate(-50%, -50%) scale(1.05)' },
102
- _active: disabled ? {} : { cursor: 'grabbing', transform: 'translate(-50%, -50%) scale(1.1)' },
176
+ _hover: { transform: 'translate(-50%, -50%) scale(1.05)' },
177
+ _active: { cursor: 'grabbing', transform: 'translate(-50%, -50%) scale(1.1)' },
103
178
  },
104
- }),
179
+ },
105
180
 
106
- thumbActive: (_props: SliderDynamicProps) => ({
181
+ thumbActive: {
107
182
  _web: {
108
183
  transform: 'translate(-50%, -50%) scale(1.1)',
109
184
  },
110
- }),
185
+ },
111
186
 
112
- thumbIcon: ({ intent = 'primary' }: SliderDynamicProps) => ({
187
+ thumbIcon: {
113
188
  display: 'flex' as const,
114
189
  alignItems: 'center' as const,
115
190
  justifyContent: 'center' as const,
116
191
  flexShrink: 0,
117
- color: theme.intents[intent].primary,
118
192
  variants: {
119
193
  size: {
120
194
  width: theme.sizes.$slider.thumbIconSize,
@@ -124,36 +198,49 @@ export const sliderStyles = defineStyle('Slider', (theme: Theme) => ({
124
198
  minHeight: theme.sizes.$slider.thumbIconSize,
125
199
  maxHeight: theme.sizes.$slider.thumbIconSize,
126
200
  },
201
+ intent: createIntentVariants(theme),
127
202
  },
128
- }),
203
+ compoundVariants: (() => {
204
+ const cv: CompoundVariants<keyof SliderVariants> = [];
205
+ for (const intent in theme.intents) {
206
+ cv.push({
207
+ intent,
208
+ styles: {
209
+ color: theme.intents[intent as Intent].primary,
210
+ },
211
+ });
212
+ }
213
+ return cv;
214
+ })(),
215
+ },
129
216
 
130
- valueLabel: (_props: SliderDynamicProps) => ({
217
+ valueLabel: {
131
218
  fontSize: 12,
132
219
  fontWeight: '600' as const,
133
220
  color: theme.colors.text.primary,
134
221
  textAlign: 'center' as const,
135
- }),
222
+ },
136
223
 
137
- minMaxLabels: (_props: SliderDynamicProps) => ({
224
+ minMaxLabels: {
138
225
  flexDirection: 'row' as const,
139
226
  justifyContent: 'space-between' as const,
140
227
  marginTop: 4,
141
- }),
228
+ },
142
229
 
143
- minMaxLabel: (_props: SliderDynamicProps) => ({
230
+ minMaxLabel: {
144
231
  fontSize: 12,
145
232
  color: theme.colors.text.secondary,
146
- }),
233
+ },
147
234
 
148
- marks: (_props: SliderDynamicProps) => ({
235
+ marks: {
149
236
  position: 'absolute' as const,
150
237
  width: '100%',
151
238
  height: '100%',
152
239
  top: 0,
153
240
  left: 0,
154
- }),
241
+ },
155
242
 
156
- mark: (_props: SliderDynamicProps) => ({
243
+ mark: {
157
244
  position: 'absolute' as const,
158
245
  width: 2,
159
246
  backgroundColor: theme.colors.border.secondary,
@@ -166,9 +253,9 @@ export const sliderStyles = defineStyle('Slider', (theme: Theme) => ({
166
253
  _web: {
167
254
  transform: 'translate(-50%, -50%)',
168
255
  },
169
- }),
256
+ },
170
257
 
171
- markLabel: (_props: SliderDynamicProps) => ({
258
+ markLabel: {
172
259
  position: 'absolute' as const,
173
260
  fontSize: 10,
174
261
  color: theme.colors.text.secondary,
@@ -178,5 +265,5 @@ export const sliderStyles = defineStyle('Slider', (theme: Theme) => ({
178
265
  transform: 'translateX(-50%)',
179
266
  whiteSpace: 'nowrap',
180
267
  },
181
- }),
268
+ },
182
269
  }));
@@ -5,7 +5,7 @@ import type { SliderProps } from './types';
5
5
  import { IconSvg } from '../Icon/IconSvg/IconSvg.web';
6
6
  import { isIconName } from '../Icon/icon-resolver';
7
7
  import useMergeRefs from '../hooks/useMergeRefs';
8
- import { getWebRangeAriaProps, generateAccessibilityId, SLIDER_KEYS } from '../utils/accessibility';
8
+ import { getWebRangeAriaProps, generateAccessibilityId, SLIDER_KEYS, matchesKey } from '../utils/accessibility';
9
9
 
10
10
  /**
11
11
  * Range slider for selecting numeric values within a min/max range.
@@ -55,20 +55,21 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
55
55
  // Apply variants
56
56
  sliderStyles.useVariants({
57
57
  size,
58
+ intent,
58
59
  disabled,
59
60
  margin,
60
61
  marginVertical,
61
62
  marginHorizontal,
62
63
  });
63
64
 
64
- const containerProps = getWebProps([(sliderStyles.container as any)({}), style as any]);
65
- const wrapperProps = getWebProps([sliderStyles.sliderWrapper]);
66
- const trackProps = getWebProps([(sliderStyles.track as any)({})]);
67
- const thumbIconProps = getWebProps([(sliderStyles.thumbIcon as any)({ intent })]);
68
- const valueLabelProps = getWebProps([sliderStyles.valueLabel]);
69
- const minMaxLabelsProps = getWebProps([sliderStyles.minMaxLabels]);
70
- const minMaxLabelProps = getWebProps([sliderStyles.minMaxLabel]);
71
- const marksProps = getWebProps([sliderStyles.marks]);
65
+ const containerProps = getWebProps([sliderStyles.container as any, style as any]);
66
+ const wrapperProps = getWebProps([sliderStyles.sliderWrapper as any]);
67
+ const trackProps = getWebProps([sliderStyles.track as any]);
68
+ const thumbIconProps = getWebProps([sliderStyles.thumbIcon as any]);
69
+ const valueLabelProps = getWebProps([sliderStyles.valueLabel as any]);
70
+ const minMaxLabelsProps = getWebProps([sliderStyles.minMaxLabels as any]);
71
+ const minMaxLabelProps = getWebProps([sliderStyles.minMaxLabel as any]);
72
+ const marksProps = getWebProps([sliderStyles.marks as any]);
72
73
 
73
74
  const clampValue = useCallback((val: number) => {
74
75
  const clampedValue = Math.min(Math.max(val, min), max);
@@ -138,26 +139,25 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
138
139
  const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
139
140
  if (disabled) return;
140
141
 
141
- const key = e.key;
142
142
  let newValue = value;
143
143
  const largeStep = (max - min) / 10; // 10% of range for PageUp/PageDown
144
144
 
145
- if (SLIDER_KEYS.increase.includes(key)) {
145
+ if (matchesKey(e, SLIDER_KEYS.increase)) {
146
146
  e.preventDefault();
147
147
  newValue = clampValue(value + step);
148
- } else if (SLIDER_KEYS.decrease.includes(key)) {
148
+ } else if (matchesKey(e, SLIDER_KEYS.decrease)) {
149
149
  e.preventDefault();
150
150
  newValue = clampValue(value - step);
151
- } else if (SLIDER_KEYS.min.includes(key)) {
151
+ } else if (matchesKey(e, SLIDER_KEYS.min)) {
152
152
  e.preventDefault();
153
153
  newValue = min;
154
- } else if (SLIDER_KEYS.max.includes(key)) {
154
+ } else if (matchesKey(e, SLIDER_KEYS.max)) {
155
155
  e.preventDefault();
156
156
  newValue = max;
157
- } else if (key === 'PageUp') {
157
+ } else if (matchesKey(e, SLIDER_KEYS.increaseLarge)) {
158
158
  e.preventDefault();
159
159
  newValue = clampValue(value + largeStep);
160
- } else if (key === 'PageDown') {
160
+ } else if (matchesKey(e, SLIDER_KEYS.decreaseLarge)) {
161
161
  e.preventDefault();
162
162
  newValue = clampValue(value - largeStep);
163
163
  }
@@ -215,10 +215,10 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
215
215
  const percentage = ((value - min) / (max - min)) * 100;
216
216
 
217
217
  // Dynamic styles with percentage
218
- const filledTrackProps = getWebProps([(sliderStyles.filledTrack as any)({ intent }), { width: `${percentage}%` }]);
218
+ const filledTrackProps = getWebProps([sliderStyles.filledTrack as any, { width: `${percentage}%` }]);
219
219
  const thumbProps = getWebProps([
220
- (sliderStyles.thumb as any)({ intent, disabled }),
221
- isDragging && sliderStyles.thumbActive,
220
+ sliderStyles.thumb as any,
221
+ isDragging && (sliderStyles.thumbActive as any),
222
222
  { left: `${percentage}%` }
223
223
  ]);
224
224
 
@@ -269,8 +269,8 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
269
269
  <div {...marksProps}>
270
270
  {marks.map((mark) => {
271
271
  const markPercentage = ((mark.value - min) / (max - min)) * 100;
272
- const markProps = getWebProps([sliderStyles.mark, { left: `${markPercentage}%` }]);
273
- const markLabelProps = getWebProps([sliderStyles.markLabel, { left: `${markPercentage}%` }]);
272
+ const markProps = getWebProps([sliderStyles.mark as any, { left: `${markPercentage}%` }]);
273
+ const markLabelProps = getWebProps([sliderStyles.markLabel as any, { left: `${markPercentage}%` }]);
274
274
  return (
275
275
  <div key={mark.value}>
276
276
  <div {...markProps} />
@@ -287,8 +287,8 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
287
287
 
288
288
  {/* Thumb */}
289
289
  <div
290
- ref={thumbRef}
291
290
  {...thumbProps}
291
+ ref={thumbRef}
292
292
  >
293
293
  {renderIcon()}
294
294
  </div>
@@ -1,20 +1,43 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import { getWebProps } from 'react-native-unistyles/web';
3
- import { TextProps } from './types';
3
+ import type { Typography, Size } from '@idealyst/theme';
4
+ import { TextProps, TextSizeVariant } from './types';
4
5
  import { textStyles } from './Text.styles';
5
6
  import useMergeRefs from '../hooks/useMergeRefs';
6
7
 
8
+ // Map Size values to Typography values
9
+ const SIZE_TO_TYPOGRAPHY: Record<Size, Typography> = {
10
+ 'xs': 'caption',
11
+ 'sm': 'body2',
12
+ 'md': 'body1',
13
+ 'lg': 'subtitle1',
14
+ 'xl': 'h5',
15
+ '2xl': 'h4',
16
+ '3xl': 'h3',
17
+ };
18
+
19
+ // Convert TextSizeVariant to Typography (handles both Size and Typography values)
20
+ function resolveTypography(value: TextSizeVariant | undefined): Typography {
21
+ if (!value) return 'body1';
22
+ // If it's a Size value, map it to Typography
23
+ if (value in SIZE_TO_TYPOGRAPHY) {
24
+ return SIZE_TO_TYPOGRAPHY[value as Size];
25
+ }
26
+ // Otherwise it's already a Typography value
27
+ return value as Typography;
28
+ }
29
+
7
30
  /**
8
31
  * Typography component for displaying text with predefined styles and semantic variants.
9
32
  * Supports multiple typography scales, colors, weights, and alignments.
10
33
  */
11
34
  const Text = forwardRef<HTMLSpanElement, TextProps>(({
12
35
  children,
13
- typography = 'body1',
36
+ typography: typographyProp,
37
+ size,
14
38
  weight,
15
39
  color = 'primary',
16
40
  align = 'left',
17
- pre = false,
18
41
  // Spacing variants from TextSpacingStyleProps
19
42
  gap,
20
43
  padding,
@@ -24,6 +47,9 @@ const Text = forwardRef<HTMLSpanElement, TextProps>(({
24
47
  testID,
25
48
  id,
26
49
  }, ref) => {
50
+ // size is an alias for typography - size takes precedence if both are set
51
+ const typography = resolveTypography(size ?? typographyProp);
52
+
27
53
  textStyles.useVariants({
28
54
  typography,
29
55
  weight,
package/src/Text/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Text, Typography } from '@idealyst/theme';
1
+ import { Text, Typography, Size } from '@idealyst/theme';
2
2
  import type { ReactNode } from 'react';
3
3
  import type { StyleProp, TextStyle } from 'react-native';
4
4
  import { TextSpacingStyleProps } from '../utils/viewStyleProps';
@@ -8,6 +8,12 @@ export type TextColorVariant = Text;
8
8
  export type TextWeightVariant = 'light' | 'normal' | 'medium' | 'semibold' | 'bold';
9
9
  export type TextAlignVariant = 'left' | 'center' | 'right';
10
10
  export type TextTypographyVariant = Typography;
11
+ /**
12
+ * Text size variant - accepts both Typography values and Size shorthand
13
+ * Typography: 'h1', 'h2', 'body1', 'caption', etc.
14
+ * Size: 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'
15
+ */
16
+ export type TextSizeVariant = Typography | Size;
11
17
 
12
18
  /**
13
19
  * Typography component for rendering text with consistent styling.
@@ -25,6 +31,13 @@ export interface TextProps extends TextSpacingStyleProps {
25
31
  */
26
32
  typography?: TextTypographyVariant;
27
33
 
34
+ /**
35
+ * Text size - accepts Typography names or Size shorthand.
36
+ * Typography: 'h1', 'h2', 'body1', 'caption', etc.
37
+ * Size: 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'
38
+ */
39
+ size?: TextSizeVariant;
40
+
28
41
  /**
29
42
  * The weight of the text.
30
43
  * Overrides the weight from typography if both are set.