@idealyst/components 1.0.99 → 1.1.0

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 (106) hide show
  1. package/package.json +4 -4
  2. package/src/Accordion/Accordion.native.tsx +15 -0
  3. package/src/Accordion/Accordion.styles.tsx +17 -0
  4. package/src/Accordion/Accordion.web.tsx +15 -0
  5. package/src/Accordion/types.ts +2 -1
  6. package/src/Button/Button.native.tsx +55 -2
  7. package/src/Button/Button.styles.tsx +22 -0
  8. package/src/Button/Button.web.tsx +6 -2
  9. package/src/Button/types.ts +15 -0
  10. package/src/Card/Card.native.tsx +18 -5
  11. package/src/Card/Card.styles.tsx +123 -131
  12. package/src/Card/Card.web.tsx +17 -4
  13. package/src/Card/types.ts +3 -8
  14. package/src/Checkbox/Checkbox.native.tsx +7 -0
  15. package/src/Checkbox/Checkbox.styles.tsx +11 -0
  16. package/src/Checkbox/Checkbox.web.tsx +7 -0
  17. package/src/Checkbox/types.ts +2 -1
  18. package/src/Input/Input.native.tsx +7 -0
  19. package/src/Input/Input.styles.tsx +9 -0
  20. package/src/Input/Input.web.tsx +7 -0
  21. package/src/Input/types.ts +2 -1
  22. package/src/List/List.native.tsx +15 -0
  23. package/src/List/List.styles.tsx +17 -0
  24. package/src/List/List.web.tsx +15 -0
  25. package/src/List/types.ts +2 -1
  26. package/src/Pressable/Pressable.native.tsx +13 -1
  27. package/src/Pressable/Pressable.styles.tsx +24 -0
  28. package/src/Pressable/Pressable.web.tsx +24 -6
  29. package/src/Pressable/types.ts +3 -2
  30. package/src/RadioButton/RadioButton.native.tsx +7 -0
  31. package/src/RadioButton/RadioButton.styles.tsx +9 -0
  32. package/src/RadioButton/RadioButton.web.tsx +7 -0
  33. package/src/RadioButton/types.ts +2 -1
  34. package/src/Screen/Screen.native.tsx +25 -12
  35. package/src/Screen/Screen.styles.tsx +28 -16
  36. package/src/Screen/Screen.web.tsx +16 -3
  37. package/src/Screen/types.ts +4 -8
  38. package/src/Select/Select.native.tsx +7 -0
  39. package/src/Select/Select.styles.tsx +11 -0
  40. package/src/Select/Select.web.tsx +7 -0
  41. package/src/Select/types.ts +2 -1
  42. package/src/Slider/Slider.native.tsx +7 -0
  43. package/src/Slider/Slider.styles.tsx +11 -0
  44. package/src/Slider/Slider.web.tsx +7 -0
  45. package/src/Slider/types.ts +2 -1
  46. package/src/Switch/Switch.native.tsx +7 -0
  47. package/src/Switch/Switch.styles.tsx +11 -0
  48. package/src/Switch/Switch.web.tsx +7 -0
  49. package/src/Switch/types.ts +2 -1
  50. package/src/TabBar/TabBar.native.tsx +19 -1
  51. package/src/TabBar/TabBar.styles.tsx +17 -0
  52. package/src/TabBar/TabBar.web.tsx +20 -1
  53. package/src/TabBar/types.ts +2 -1
  54. package/src/Table/Table.native.tsx +15 -0
  55. package/src/Table/Table.styles.tsx +27 -0
  56. package/src/Table/Table.web.tsx +15 -0
  57. package/src/Table/types.ts +2 -1
  58. package/src/Text/Text.native.tsx +14 -3
  59. package/src/Text/Text.styles.tsx +36 -12
  60. package/src/Text/Text.web.tsx +15 -4
  61. package/src/Text/types.ts +15 -4
  62. package/src/TextArea/TextArea.native.tsx +7 -0
  63. package/src/TextArea/TextArea.styles.tsx +11 -0
  64. package/src/TextArea/TextArea.web.tsx +7 -0
  65. package/src/TextArea/types.ts +2 -1
  66. package/src/View/View.native.tsx +35 -12
  67. package/src/View/View.styles.tsx +78 -75
  68. package/src/View/View.web.tsx +18 -9
  69. package/src/View/types.ts +8 -23
  70. package/src/examples/AccordionExamples.tsx +32 -32
  71. package/src/examples/AlertExamples.tsx +42 -42
  72. package/src/examples/AvatarExamples.tsx +18 -18
  73. package/src/examples/BadgeExamples.tsx +30 -30
  74. package/src/examples/BreadcrumbExamples.tsx +64 -64
  75. package/src/examples/ButtonExamples.tsx +128 -16
  76. package/src/examples/CardExamples.tsx +28 -28
  77. package/src/examples/CheckboxExamples.tsx +25 -25
  78. package/src/examples/ChipExamples.tsx +17 -17
  79. package/src/examples/DialogExamples.tsx +17 -17
  80. package/src/examples/DividerExamples.tsx +21 -21
  81. package/src/examples/IconExamples.tsx +113 -113
  82. package/src/examples/ImageExamples.tsx +34 -34
  83. package/src/examples/InputExamples.tsx +20 -20
  84. package/src/examples/LinkExamples.tsx +23 -23
  85. package/src/examples/ListExamples.tsx +42 -42
  86. package/src/examples/MenuExamples.tsx +15 -15
  87. package/src/examples/PopoverExamples.tsx +23 -23
  88. package/src/examples/ProgressExamples.tsx +41 -41
  89. package/src/examples/RadioButtonExamples.tsx +21 -21
  90. package/src/examples/SVGImageExamples.tsx +25 -25
  91. package/src/examples/ScreenExamples.tsx +41 -41
  92. package/src/examples/SelectExamples.tsx +59 -59
  93. package/src/examples/SkeletonExamples.tsx +30 -30
  94. package/src/examples/SliderExamples.tsx +54 -54
  95. package/src/examples/SwitchExamples.tsx +20 -20
  96. package/src/examples/TabBarExamples.tsx +26 -26
  97. package/src/examples/TableExamples.tsx +36 -36
  98. package/src/examples/TextAreaExamples.tsx +25 -25
  99. package/src/examples/TextExamples.tsx +61 -66
  100. package/src/examples/ThemeExtensionExamples.tsx +12 -12
  101. package/src/examples/TooltipExamples.tsx +21 -21
  102. package/src/examples/VideoExamples.tsx +28 -28
  103. package/src/examples/ViewExamples.tsx +59 -59
  104. package/src/index.ts +4 -0
  105. package/src/utils/buildViewStyleVariants.ts +148 -0
  106. package/src/utils/viewStyleProps.ts +63 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idealyst/components",
3
- "version": "1.0.99",
3
+ "version": "1.1.0",
4
4
  "description": "Shared component library for React and React Native",
5
5
  "documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/components#readme",
6
6
  "readme": "README.md",
@@ -41,7 +41,7 @@
41
41
  "publish:npm": "npm publish"
42
42
  },
43
43
  "peerDependencies": {
44
- "@idealyst/theme": "^1.0.99",
44
+ "@idealyst/theme": "^1.1.0",
45
45
  "@mdi/js": ">=7.0.0",
46
46
  "@mdi/react": ">=1.0.0",
47
47
  "@react-native-vector-icons/common": ">=12.0.0",
@@ -91,7 +91,7 @@
91
91
  }
92
92
  },
93
93
  "devDependencies": {
94
- "@idealyst/theme": "^1.0.99",
94
+ "@idealyst/theme": "^1.1.0",
95
95
  "@mdi/react": "^1.6.1",
96
96
  "@types/react": "^19.1.0",
97
97
  "react": "^19.1.0",
@@ -117,4 +117,4 @@
117
117
  "components",
118
118
  "cross-platform"
119
119
  ]
120
- }
120
+ }
@@ -132,6 +132,14 @@ const Accordion = forwardRef<View, AccordionProps>(({
132
132
  defaultExpanded = [],
133
133
  type = 'standard',
134
134
  size = 'md',
135
+ // Spacing variants from ContainerStyleProps
136
+ gap,
137
+ padding,
138
+ paddingVertical,
139
+ paddingHorizontal,
140
+ margin,
141
+ marginVertical,
142
+ marginHorizontal,
135
143
  style,
136
144
  testID,
137
145
  }, ref) => {
@@ -141,6 +149,13 @@ const Accordion = forwardRef<View, AccordionProps>(({
141
149
  accordionStyles.useVariants({
142
150
  type,
143
151
  size,
152
+ gap,
153
+ padding,
154
+ paddingVertical,
155
+ paddingHorizontal,
156
+ margin,
157
+ marginVertical,
158
+ marginHorizontal,
144
159
  });
145
160
 
146
161
  const toggleItem = (itemId: string, disabled?: boolean) => {
@@ -1,6 +1,15 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
2
  import { Theme, StylesheetStyles, CompoundVariants, Size} from '@idealyst/theme';
3
3
  import { buildSizeVariants } from '../utils/buildSizeVariants';
4
+ import {
5
+ buildGapVariants,
6
+ buildPaddingVariants,
7
+ buildPaddingVerticalVariants,
8
+ buildPaddingHorizontalVariants,
9
+ buildMarginVariants,
10
+ buildMarginVerticalVariants,
11
+ buildMarginHorizontalVariants,
12
+ } from '../utils/buildViewStyleVariants';
4
13
  import { AccordionType } from './types';
5
14
 
6
15
  type AccordionSize = Size;
@@ -127,6 +136,14 @@ export const accordionStyles = StyleSheet.create((theme: Theme) => {
127
136
  expanded: { true: {}, false: {} },
128
137
  disabled: { true: {}, false: {} },
129
138
  isLast: { true: {}, false: {} },
139
+ // Spacing variants from ContainerStyleProps
140
+ gap: buildGapVariants(theme),
141
+ padding: buildPaddingVariants(theme),
142
+ paddingVertical: buildPaddingVerticalVariants(theme),
143
+ paddingHorizontal: buildPaddingHorizontalVariants(theme),
144
+ margin: buildMarginVariants(theme),
145
+ marginVertical: buildMarginVerticalVariants(theme),
146
+ marginHorizontal: buildMarginHorizontalVariants(theme),
130
147
  },
131
148
  },
132
149
  item: {
@@ -98,6 +98,14 @@ const Accordion: React.FC<AccordionProps> = ({
98
98
  defaultExpanded = [],
99
99
  type = 'standard',
100
100
  size = 'md',
101
+ // Spacing variants from ContainerStyleProps
102
+ gap,
103
+ padding,
104
+ paddingVertical,
105
+ paddingHorizontal,
106
+ margin,
107
+ marginVertical,
108
+ marginHorizontal,
101
109
  style,
102
110
  testID,
103
111
  }) => {
@@ -107,6 +115,13 @@ const Accordion: React.FC<AccordionProps> = ({
107
115
  accordionStyles.useVariants({
108
116
  type,
109
117
  size,
118
+ gap,
119
+ padding,
120
+ paddingVertical,
121
+ paddingHorizontal,
122
+ margin,
123
+ marginVertical,
124
+ marginHorizontal,
110
125
  });
111
126
 
112
127
  const containerProps = getWebProps([accordionStyles.container, style as any]);
@@ -1,5 +1,6 @@
1
1
  import { Size } from '@idealyst/theme';
2
2
  import type { StyleProp, ViewStyle } from 'react-native';
3
+ import { ContainerStyleProps } from '../utils/viewStyleProps';
3
4
 
4
5
  // Component-specific type aliases for future extensibility
5
6
  export type AccordionType = 'standard' | 'separated' | 'bordered';
@@ -12,7 +13,7 @@ export interface AccordionItem {
12
13
  disabled?: boolean;
13
14
  }
14
15
 
15
- export interface AccordionProps {
16
+ export interface AccordionProps extends ContainerStyleProps {
16
17
  items: AccordionItem[];
17
18
  allowMultiple?: boolean;
18
19
  defaultExpanded?: string[];
@@ -1,6 +1,7 @@
1
1
  import React, { ComponentRef, forwardRef, isValidElement } from 'react';
2
- import { Text, TouchableOpacity, View } from 'react-native';
2
+ import { StyleSheet as RNStyleSheet, Text, TouchableOpacity, View } from 'react-native';
3
3
  import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
4
+ import Svg, { Defs, LinearGradient, Stop, Rect } from 'react-native-svg';
4
5
  import { buttonStyles } from './Button.styles';
5
6
  import { ButtonProps } from './types';
6
7
 
@@ -13,17 +14,39 @@ const Button = forwardRef<ComponentRef<typeof TouchableOpacity>, ButtonProps>((p
13
14
  type = 'contained',
14
15
  intent = 'primary',
15
16
  size = 'md',
17
+ gradient,
16
18
  leftIcon,
17
19
  rightIcon,
18
20
  style,
19
21
  testID,
20
22
  } = props;
21
23
 
24
+ // Apply variants
25
+ buttonStyles.useVariants({
26
+ type,
27
+ intent,
28
+ size,
29
+ disabled,
30
+ gradient,
31
+ });
32
+
22
33
  // Compute dynamic styles
23
34
  const buttonStyle = buttonStyles.button;
24
35
  const textStyle = buttonStyles.text;
25
36
  const iconStyle = buttonStyles.icon;
26
37
 
38
+ // Gradient is only applicable to contained buttons
39
+ const showGradient = gradient && type === 'contained';
40
+
41
+ // Get gradient overlay colors (transparent to semi-transparent black/white)
42
+ const getGradientColors = (): [string, string] => {
43
+ switch (gradient) {
44
+ case 'darken': return ['transparent', 'rgba(0, 0, 0, 0.15)'];
45
+ case 'lighten': return ['transparent', 'rgba(255, 255, 255, 0.2)'];
46
+ default: return ['transparent', 'transparent'];
47
+ }
48
+ };
49
+
27
50
  // Map button size to icon size
28
51
  const iconSizeMap = {
29
52
  xs: 12,
@@ -59,6 +82,31 @@ const Button = forwardRef<ComponentRef<typeof TouchableOpacity>, ButtonProps>((p
59
82
  // Determine if we need to wrap content in icon container
60
83
  const hasIcons = leftIcon || rightIcon;
61
84
 
85
+ // Render gradient background layer
86
+ const renderGradientLayer = () => {
87
+ if (!showGradient) return null;
88
+
89
+ const [startColor, endColor] = getGradientColors();
90
+
91
+ return (
92
+ <Svg style={RNStyleSheet.absoluteFill}>
93
+ <Defs>
94
+ <LinearGradient id="buttonGradient" x1="0%" y1="0%" x2="100%" y2="100%">
95
+ <Stop offset="0%" stopColor={startColor} />
96
+ <Stop offset="100%" stopColor={endColor} />
97
+ </LinearGradient>
98
+ </Defs>
99
+ <Rect
100
+ width="100%"
101
+ height="100%"
102
+ fill="url(#buttonGradient)"
103
+ rx={8}
104
+ ry={8}
105
+ />
106
+ </Svg>
107
+ );
108
+ };
109
+
62
110
  return (
63
111
  <TouchableOpacity
64
112
  ref={ref}
@@ -66,8 +114,13 @@ const Button = forwardRef<ComponentRef<typeof TouchableOpacity>, ButtonProps>((p
66
114
  disabled={disabled}
67
115
  testID={testID}
68
116
  activeOpacity={0.7}
69
- style={[buttonStyle, style]}
117
+ style={[
118
+ buttonStyle,
119
+ showGradient && { overflow: 'hidden' },
120
+ style,
121
+ ]}
70
122
  >
123
+ {renderGradientLayer()}
71
124
  {hasIcons ? (
72
125
  <View style={buttonStyles.iconContainer}>
73
126
  {leftIcon && renderIcon(leftIcon)}
@@ -1,6 +1,7 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
2
  import { Theme, Intent, Size, CompoundVariants} from '@idealyst/theme';
3
3
  import { buildSizeVariants } from '../utils/buildSizeVariants';
4
+ import { ButtonGradient } from './types';
4
5
 
5
6
  type ButtonSize = Size;
6
7
  type ButtonIntent = Intent;
@@ -11,6 +12,7 @@ export type ButtonVariants = {
11
12
  intent: ButtonIntent;
12
13
  type: ButtonType;
13
14
  disabled: boolean;
15
+ gradient?: ButtonGradient;
14
16
  }
15
17
 
16
18
  /**
@@ -86,6 +88,25 @@ function createButtonCompoundVariants(theme: Theme): CompoundVariants<keyof Butt
86
88
  return compoundVariants;
87
89
  }
88
90
 
91
+ /**
92
+ * Create gradient variant styles for web
93
+ * Applies a transparent overlay gradient over the intent background color
94
+ */
95
+ function createGradientVariants() {
96
+ return {
97
+ 'darken': {
98
+ _web: {
99
+ backgroundImage: 'linear-gradient(135deg, transparent 0%, rgba(0, 0, 0, 0.15) 100%)',
100
+ },
101
+ },
102
+ 'lighten': {
103
+ _web: {
104
+ backgroundImage: 'linear-gradient(135deg, transparent 0%, rgba(255, 255, 255, 0.2) 100%)',
105
+ },
106
+ },
107
+ } as const;
108
+ }
109
+
89
110
  /**
90
111
  * Create icon compound variants for intent+type combinations
91
112
  */
@@ -214,6 +235,7 @@ export const buttonStyles = StyleSheet.create((theme: Theme) => {
214
235
  },
215
236
  } },
216
237
  } as const,
238
+ gradient: createGradientVariants(),
217
239
  } as const,
218
240
  compoundVariants: createButtonCompoundVariants(theme),
219
241
  } as const,
@@ -21,6 +21,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>((props: InternalButton
21
21
  type = 'contained',
22
22
  intent = 'primary',
23
23
  size = 'md',
24
+ gradient,
24
25
  leftIcon,
25
26
  rightIcon,
26
27
  leftIconPath,
@@ -33,10 +34,13 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>((props: InternalButton
33
34
  type,
34
35
  intent,
35
36
  size,
36
- disabled
37
+ disabled,
38
+ gradient,
37
39
  });
38
40
 
39
- const handleClick = () => {
41
+ const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
42
+ e.preventDefault();
43
+ e.stopPropagation();
40
44
  if (!disabled && onPress) {
41
45
  onPress();
42
46
  }
@@ -8,6 +8,14 @@ export type ButtonType = 'contained' | 'outlined' | 'text';
8
8
  export type ButtonIntentVariant = Intent;
9
9
  export type ButtonSizeVariant = Size;
10
10
 
11
+ /**
12
+ * Gradient overlay options for buttons.
13
+ * Applies a transparent gradient over the intent background color.
14
+ * - 'darken': Transparent to semi-transparent black (darkens one corner)
15
+ * - 'lighten': Transparent to semi-transparent white (lightens one corner)
16
+ */
17
+ export type ButtonGradient = 'darken' | 'lighten';
18
+
11
19
  export interface ButtonProps {
12
20
  /**
13
21
  * The text or content to display inside the button
@@ -44,6 +52,13 @@ export interface ButtonProps {
44
52
  */
45
53
  size?: ButtonSizeVariant;
46
54
 
55
+ /**
56
+ * Apply a gradient background enhancement.
57
+ * Only applies to 'contained' button type.
58
+ * Options: 'color-to-dark', 'color-to-light', 'light-to-color', 'dark-to-color'
59
+ */
60
+ gradient?: ButtonGradient;
61
+
47
62
  /**
48
63
  * Icon to display on the left side. Can be an icon name or custom component (ReactNode)
49
64
  */
@@ -5,13 +5,20 @@ import { cardStyles } from './Card.styles';
5
5
 
6
6
  const Card = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pressable>, CardProps>(({
7
7
  children,
8
- type = 'default',
9
- padding = 'md',
8
+ type = 'elevated',
10
9
  radius = 'md',
11
10
  intent = 'neutral',
12
11
  clickable = false,
13
12
  onPress,
14
13
  disabled = false,
14
+ // Spacing variants from ContainerStyleProps
15
+ gap,
16
+ padding,
17
+ paddingVertical,
18
+ paddingHorizontal,
19
+ margin,
20
+ marginVertical,
21
+ marginHorizontal,
15
22
  style,
16
23
  testID,
17
24
  accessibilityLabel,
@@ -21,11 +28,17 @@ const Card = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pressabl
21
28
  clickable,
22
29
  radius,
23
30
  type,
24
- padding,
25
31
  intent,
26
32
  disabled,
33
+ gap,
34
+ padding,
35
+ paddingVertical,
36
+ paddingHorizontal,
37
+ margin,
38
+ marginVertical,
39
+ marginHorizontal,
27
40
  });
28
-
41
+
29
42
  // Use appropriate component based on clickable state
30
43
  const Component = clickable ? Pressable : View;
31
44
 
@@ -52,4 +65,4 @@ const Card = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pressabl
52
65
 
53
66
  Card.displayName = 'Card';
54
67
 
55
- export default Card;
68
+ export default Card;
@@ -1,107 +1,94 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
2
  import { Theme, Intent, CompoundVariants } from '@idealyst/theme';
3
+ import {
4
+ buildGapVariants,
5
+ buildPaddingVariants,
6
+ buildPaddingVerticalVariants,
7
+ buildPaddingHorizontalVariants,
8
+ buildMarginVariants,
9
+ buildMarginVerticalVariants,
10
+ buildMarginHorizontalVariants,
11
+ } from '../utils/buildViewStyleVariants';
12
+ import { ViewStyleSize } from '../utils/viewStyleProps';
3
13
 
4
- type CardType = 'default' | 'outlined' | 'elevated' | 'filled';
5
- type CardPadding = 'none' | 'sm' | 'md' | 'lg';
6
- type CardRadius = 'none' | 'sm' | 'md' | 'lg';
14
+ type CardType = 'outlined' | 'elevated' | 'filled';
15
+ type CardRadius = 'none' | 'sm' | 'md' | 'lg' | 'xs' | 'xl';
7
16
  type CardIntent = Intent | 'info' | 'neutral';
8
17
 
9
18
  export type CardVariants = {
10
- type: CardType;
11
- padding: CardPadding;
12
- radius: CardRadius;
13
- intent: CardIntent;
14
- clickable: boolean;
15
- disabled: boolean;
16
- }
19
+ type: CardType;
20
+ radius: CardRadius;
21
+ intent: CardIntent;
22
+ clickable: boolean;
23
+ disabled: boolean;
24
+ // Spacing variants from ContainerStyleProps
25
+ gap: ViewStyleSize;
26
+ padding: ViewStyleSize;
27
+ paddingVertical: ViewStyleSize;
28
+ paddingHorizontal: ViewStyleSize;
29
+ margin: ViewStyleSize;
30
+ marginVertical: ViewStyleSize;
31
+ marginHorizontal: ViewStyleSize;
32
+ };
17
33
 
18
34
  /**
19
35
  * Create type variants (structure only, colors handled by compound variants)
20
36
  */
21
37
  function createTypeVariants(theme: Theme) {
22
- return {
23
- default: {
24
- backgroundColor: theme.colors.surface.primary,
25
- borderWidth: 1,
26
- borderStyle: 'solid' as const,
27
- },
28
- outlined: {
29
- backgroundColor: 'transparent',
30
- borderWidth: 1,
31
- borderStyle: 'solid' as const,
32
- },
33
- elevated: {
34
- backgroundColor: theme.colors.surface.primary,
35
- borderWidth: 0,
36
- ...theme.shadows.md,
37
- },
38
- filled: {
39
- backgroundColor: theme.colors.surface.secondary,
40
- borderWidth: 0,
41
- },
42
- } as const;
38
+ return {
39
+ outlined: {
40
+ backgroundColor: 'transparent',
41
+ borderWidth: 1,
42
+ borderStyle: 'solid' as const,
43
+ },
44
+ elevated: {
45
+ backgroundColor: theme.colors.surface.primary,
46
+ borderWidth: 0,
47
+ ...theme.shadows.md,
48
+ },
49
+ filled: {
50
+ backgroundColor: theme.colors.surface.secondary,
51
+ borderWidth: 0,
52
+ },
53
+ } as const;
43
54
  }
44
55
 
45
56
  /**
46
57
  * Create compound variants for type + intent combinations
47
58
  */
48
59
  function createCardCompoundVariants(theme: Theme) {
49
- const compoundVariants: CompoundVariants<keyof CardVariants> = [];
60
+ const compoundVariants: CompoundVariants<keyof CardVariants> = [];
50
61
 
51
- // Add intent-based border colors for default and outlined types
52
- for (const intent in theme.intents) {
53
- const intentValue = theme.intents[intent as Intent];
62
+ // Add intent-based border colors for outlined type
63
+ for (const intent in theme.intents) {
64
+ const intentValue = theme.intents[intent as Intent];
54
65
 
55
- // Default + intent
56
- compoundVariants.push({
57
- intent,
58
- type: 'default',
59
- styles: {
60
- borderColor: intentValue.primary,
61
- },
62
- });
63
-
64
- // Outlined + intent
65
- compoundVariants.push({
66
- intent,
67
- type: 'outlined',
68
- styles: {
69
- borderColor: intentValue.primary,
70
- },
71
- });
72
- }
73
-
74
- // Add special intents (info, neutral)
75
66
  compoundVariants.push({
76
- intent: 'info',
77
- type: 'default',
78
- styles: {
79
- borderColor: theme.colors.border.secondary,
80
- },
81
- });
82
- compoundVariants.push({
83
- intent: 'info',
84
- type: 'outlined',
85
- styles: {
86
- borderColor: theme.colors.border.secondary,
87
- },
88
- });
89
- compoundVariants.push({
90
- intent: 'neutral',
91
- type: 'default',
92
- styles: {
93
- borderColor: theme.colors.border.secondary,
94
- },
95
- });
96
- compoundVariants.push({
97
- intent: 'neutral',
98
- type: 'outlined',
99
- styles: {
100
- borderColor: theme.colors.border.secondary,
101
- },
67
+ intent,
68
+ type: 'outlined',
69
+ styles: {
70
+ borderColor: intentValue.primary,
71
+ },
102
72
  });
73
+ }
74
+
75
+ // Add special intents (info, neutral) for outlined type
76
+ compoundVariants.push({
77
+ intent: 'info',
78
+ type: 'outlined',
79
+ styles: {
80
+ borderColor: theme.colors.border.secondary,
81
+ },
82
+ });
83
+ compoundVariants.push({
84
+ intent: 'neutral',
85
+ type: 'outlined',
86
+ styles: {
87
+ borderColor: theme.colors.border.secondary,
88
+ },
89
+ });
103
90
 
104
- return compoundVariants;
91
+ return compoundVariants;
105
92
  }
106
93
 
107
94
  // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
@@ -109,58 +96,63 @@ function createCardCompoundVariants(theme: Theme) {
109
96
  export const cardStyles = StyleSheet.create((theme: Theme) => {
110
97
  return {
111
98
  card: {
112
- backgroundColor: theme.colors.surface.primary,
113
- position: 'relative',
114
- overflow: 'hidden',
115
- variants: {
116
- type: createTypeVariants(theme),
117
- padding: {
118
- none: { padding: 0 },
119
- sm: { padding: 8 },
120
- md: { padding: 16 },
121
- lg: { padding: 24 },
122
- },
123
- radius: {
124
- none: { borderRadius: 0 },
125
- sm: { borderRadius: 4 },
126
- md: { borderRadius: 8 },
127
- lg: { borderRadius: 12 },
128
- },
129
- clickable: {
130
- true: {
131
- _web: {
132
- cursor: 'pointer',
133
- transition: 'all 0.2s ease',
134
- _hover: {
135
- transform: 'translateY(-2px)',
136
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.06)',
137
- },
138
- },
139
- },
140
- false: {
141
- _web: {
142
- cursor: 'default',
143
- },
144
- },
99
+ backgroundColor: theme.colors.surface.primary,
100
+ position: 'relative',
101
+ overflow: 'hidden',
102
+ variants: {
103
+ type: createTypeVariants(theme),
104
+ radius: {
105
+ none: { borderRadius: 0 },
106
+ xs: { borderRadius: 2 },
107
+ sm: { borderRadius: 4 },
108
+ md: { borderRadius: 8 },
109
+ lg: { borderRadius: 12 },
110
+ xl: { borderRadius: 16 },
111
+ },
112
+ clickable: {
113
+ true: {
114
+ _web: {
115
+ cursor: 'pointer',
116
+ transition: 'all 0.2s ease',
117
+ _hover: {
118
+ transform: 'translateY(-2px)',
119
+ boxShadow:
120
+ '0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.06)',
121
+ },
145
122
  },
146
- disabled: {
147
- true: {
148
- opacity: 0.6,
149
- _web: {
150
- cursor: 'not-allowed',
151
- },
152
- },
153
- false: {
154
- opacity: 1,
155
- },
123
+ },
124
+ false: {
125
+ _web: {
126
+ cursor: 'default',
156
127
  },
128
+ },
157
129
  },
158
- compoundVariants: createCardCompoundVariants(theme),
159
- _web: {
160
- display: 'flex',
161
- flexDirection: 'column',
162
- boxSizing: 'border-box',
130
+ disabled: {
131
+ true: {
132
+ opacity: 0.6,
133
+ _web: {
134
+ cursor: 'not-allowed',
135
+ },
136
+ },
137
+ false: {
138
+ opacity: 1,
139
+ },
163
140
  },
141
+ // Spacing variants from ContainerStyleProps
142
+ gap: buildGapVariants(theme),
143
+ padding: buildPaddingVariants(theme),
144
+ paddingVertical: buildPaddingVerticalVariants(theme),
145
+ paddingHorizontal: buildPaddingHorizontalVariants(theme),
146
+ margin: buildMarginVariants(theme),
147
+ marginVertical: buildMarginVerticalVariants(theme),
148
+ marginHorizontal: buildMarginHorizontalVariants(theme),
149
+ },
150
+ compoundVariants: createCardCompoundVariants(theme),
151
+ _web: {
152
+ display: 'flex',
153
+ flexDirection: 'column',
154
+ boxSizing: 'border-box',
155
+ },
164
156
  } as const,
165
157
  };
166
- });
158
+ });