app-studio 0.7.11 → 0.7.12

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.
package/docs/Theming.md CHANGED
@@ -635,6 +635,236 @@ Each palette has these shades: `50, 100, 200, 300, 400, 500, 600, 700, 800, 900`
635
635
  - Colors automatically switch based on `themeMode` unless using `light-*` or `dark-*` prefix
636
636
  - Color values are inverted for dark mode (e.g., `color-white` becomes black in dark mode)
637
637
 
638
+ ## Using Colors with State Modifiers
639
+
640
+ App-Studio allows you to define different colors for interactive states using underscore-prefixed state modifiers. These provide a clean, declarative way to style components based on user interaction.
641
+
642
+ ### Available State Modifiers
643
+
644
+ **Interaction States**:
645
+ - `_hover` - Hover state (mouse over)
646
+ - `_active` - Active/pressed state
647
+ - `_focus` - Focus state (keyboard/click)
648
+ - `_visited` - Visited state (for links)
649
+
650
+ **Form States**:
651
+ - `_disabled` - Disabled state
652
+ - `_enabled` - Enabled state
653
+ - `_checked` - Checked state (radio/checkbox)
654
+ - `_unchecked` - Unchecked state
655
+ - `_invalid` - Invalid form state
656
+ - `_valid` - Valid form state
657
+ - `_required` - Required form field
658
+ - `_optional` - Optional form field
659
+
660
+ **Element States**:
661
+ - `_selected` - Selected state
662
+ - `_target` - Target state (URL hash)
663
+ - `_empty` - Empty state
664
+ - `_focusVisible` - Visible focus (keyboard)
665
+ - `_focusWithin` - Focus within element
666
+ - `_placeholder` - Placeholder text state
667
+
668
+ **Child States**:
669
+ - `_firstChild` - First child element
670
+ - `_lastChild` - Last child element
671
+ - `_onlyChild` - Only child element
672
+ - `_firstOfType` - First of type element
673
+ - `_lastOfType` - Last of type element
674
+
675
+ **Group & Peer Modifiers**:
676
+ - `_groupHover` - Applied when parent `.group` is hovered
677
+ - `_groupFocus` - Applied when parent `.group` is focused
678
+ - `_groupActive` - Applied when parent `.group` is active
679
+ - `_groupDisabled` - Applied when parent `.group` is disabled
680
+ - `_peerHover` - Applied when sibling `.peer` is hovered
681
+ - `_peerFocus` - Applied when sibling `.peer` is focused
682
+ - `_peerActive` - Applied when sibling `.peer` is active
683
+ - `_peerDisabled` - Applied when sibling `.peer` is disabled
684
+ - `_peerChecked` - Applied when sibling `.peer` is checked
685
+
686
+ ### Color Examples with State Modifiers
687
+
688
+ ```javascript
689
+ import { View, Text, Element } from 'app-studio';
690
+
691
+ function InteractiveButton() {
692
+ return (
693
+ <Element
694
+ as="button"
695
+ backgroundColor="theme-primary"
696
+ color="color-white"
697
+ padding={16}
698
+ borderRadius={8}
699
+ cursor="pointer"
700
+ transition="all 200ms ease"
701
+
702
+ // Hover state - lighter color
703
+ _hover={{
704
+ backgroundColor: "theme-primary-600",
705
+ transform: "translateY(-2px)",
706
+ }}
707
+
708
+ // Active/pressed state - darker color
709
+ _active={{
710
+ backgroundColor: "theme-primary-700",
711
+ transform: "translateY(0)",
712
+ }}
713
+
714
+ // Focus state - add outline
715
+ _focus={{
716
+ outline: "2px solid",
717
+ outlineColor: "theme-primary",
718
+ outlineOffset: "2px",
719
+ }}
720
+
721
+ // Disabled state - gray out
722
+ _disabled={{
723
+ backgroundColor: "color-gray-400",
724
+ color: "color-gray-600",
725
+ cursor: "not-allowed",
726
+ opacity: 0.6,
727
+ }}
728
+ >
729
+ Click me
730
+ </Element>
731
+ );
732
+ }
733
+ ```
734
+
735
+ ### Form Control Examples
736
+
737
+ ```javascript
738
+ import { Element, View, Text } from 'app-studio';
739
+
740
+ function CheckboxExample() {
741
+ return (
742
+ <label style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
743
+ <Element
744
+ as="input"
745
+ type="checkbox"
746
+ // Default state
747
+ accentColor="theme-primary"
748
+
749
+ // Checked state - different color
750
+ _checked={{
751
+ accentColor: "theme-success",
752
+ }}
753
+
754
+ // Disabled state
755
+ _disabled={{
756
+ accentColor: "color-gray-400",
757
+ cursor: "not-allowed",
758
+ }}
759
+
760
+ // Focus state - add glow
761
+ _focus={{
762
+ boxShadow: "0 0 0 3px rgba(var(--theme-primary), 0.1)",
763
+ }}
764
+ />
765
+ <Text color="color-gray-800">Accept terms</Text>
766
+ </label>
767
+ );
768
+ }
769
+ ```
770
+
771
+ ### Group Modifiers Example
772
+
773
+ Group modifiers allow you to style child elements based on parent state:
774
+
775
+ ```javascript
776
+ import { View, Element } from 'app-studio';
777
+
778
+ function CardWithGroupHover() {
779
+ return (
780
+ <View
781
+ className="group"
782
+ backgroundColor="color-white"
783
+ borderRadius={12}
784
+ padding={16}
785
+ transition="all 200ms"
786
+ cursor="pointer"
787
+
788
+ // Parent hover
789
+ _hover={{
790
+ boxShadow: "0 10px 25px rgba(0,0,0,0.1)",
791
+ }}
792
+ >
793
+ {/* Child text changes color when parent is hovered */}
794
+ <Element
795
+ color="color-gray-600"
796
+ transition="color 200ms"
797
+ _groupHover={{
798
+ color: "theme-primary",
799
+ }}
800
+ >
801
+ Hover the card to change text color
802
+ </Element>
803
+
804
+ {/* Child background changes when parent is hovered */}
805
+ <Element
806
+ as="button"
807
+ backgroundColor="color-gray-100"
808
+ marginTop={12}
809
+ padding={8}
810
+ borderRadius={6}
811
+ transition="all 200ms"
812
+
813
+ _groupHover={{
814
+ backgroundColor: "theme-primary",
815
+ color: "color-white",
816
+ }}
817
+ >
818
+ Action Button
819
+ </Element>
820
+ </View>
821
+ );
822
+ }
823
+ ```
824
+
825
+ ### Pseudo-Elements with Colors
826
+
827
+ You can also style pseudo-elements like `::before` and `::after` with colors:
828
+
829
+ ```javascript
830
+ import { Element } from 'app-studio';
831
+
832
+ function PseudoElementButton() {
833
+ return (
834
+ <Element
835
+ as="button"
836
+ position="relative"
837
+ color="theme-primary"
838
+ fontWeight="bold"
839
+ paddingBottom={8}
840
+
841
+ // Create underline effect with ::after
842
+ _after={{
843
+ content: '""',
844
+ position: 'absolute',
845
+ bottom: 0,
846
+ left: 0,
847
+ right: 0,
848
+ height: 2,
849
+ backgroundColor: "theme-primary",
850
+ transform: 'scaleX(0)',
851
+ transition: 'transform 200ms',
852
+ transformOrigin: 'center',
853
+ }}
854
+
855
+ // Expand underline on hover
856
+ _hover={{
857
+ _after: {
858
+ transform: 'scaleX(1)',
859
+ },
860
+ }}
861
+ >
862
+ Underline Effect
863
+ </Element>
864
+ );
865
+ }
866
+ ```
867
+
638
868
  ## Using Colors with Animations
639
869
 
640
870
  When using colors in CSS animations or gradients, you can reference theme variables directly using the `var(--color-*)` syntax. This is especially useful for scroll-driven animations like `fillTextScroll()`.
@@ -724,3 +954,234 @@ All color palettes have CSS variables available:
724
954
  | `gray` | `var(--color-gray-800)` | Text on light backgrounds |
725
955
 
726
956
  See [docs/Animation.md](./Animation.md) for complete animation examples with theming.
957
+
958
+ ## Responsive Colors with Media Queries
959
+
960
+ Use the `media` prop to define different colors for different screen sizes:
961
+
962
+ ```javascript
963
+ import { View, Text } from 'app-studio';
964
+
965
+ function ResponsiveCard() {
966
+ return (
967
+ <View
968
+ backgroundColor="theme-primary"
969
+ padding={16}
970
+
971
+ // Responsive backgrounds based on screen size
972
+ media={{
973
+ mobile: {
974
+ backgroundColor: "color-blue-500",
975
+ padding: 8,
976
+ },
977
+ tablet: {
978
+ backgroundColor: "color-blue-600",
979
+ padding: 12,
980
+ },
981
+ desktop: {
982
+ backgroundColor: "color-blue-700",
983
+ padding: 20,
984
+ },
985
+ }}
986
+ >
987
+ <Text color="color-white">Responsive colors</Text>
988
+ </View>
989
+ );
990
+ }
991
+ ```
992
+
993
+ ## Color Accessibility Guidelines
994
+
995
+ ### Text Contrast
996
+
997
+ Always ensure sufficient contrast between text and background colors:
998
+
999
+ ```javascript
1000
+ // Good: High contrast
1001
+ <View backgroundColor="color-white">
1002
+ <Text color="color-gray-900">Good contrast</Text>
1003
+ </View>
1004
+
1005
+ // Poor: Low contrast - avoid
1006
+ <View backgroundColor="color-gray-100">
1007
+ <Text color="color-gray-200">Poor contrast</Text>
1008
+ </View>
1009
+ ```
1010
+
1011
+ ### Using Semantic Colors
1012
+
1013
+ Use theme colors semantically for consistency:
1014
+
1015
+ ```javascript
1016
+ const theme = {
1017
+ colors: {
1018
+ success: "color-emerald-500", // For positive actions
1019
+ error: "color-red-500", // For errors/warnings
1020
+ warning: "color-amber-500", // For warnings
1021
+ info: "color-blue-500", // For information
1022
+ disabled: "color-gray-400", // For disabled states
1023
+ },
1024
+ };
1025
+ ```
1026
+
1027
+ ### Color Opacity for Subtle Effects
1028
+
1029
+ Use alpha transparency for less intrusive elements:
1030
+
1031
+ ```javascript
1032
+ import { View, Text } from 'app-studio';
1033
+
1034
+ function SuccessMessage() {
1035
+ return (
1036
+ <View
1037
+ backgroundColor="color-emerald-500-100" // 10% opacity
1038
+ borderColor="color-emerald-500"
1039
+ borderWidth={1}
1040
+ borderRadius={8}
1041
+ padding={12}
1042
+ >
1043
+ <Text color="color-emerald-900">Success!</Text>
1044
+ </View>
1045
+ );
1046
+ }
1047
+ ```
1048
+
1049
+ ## Advanced Color Patterns
1050
+
1051
+ ### Dynamic Theme Switching
1052
+
1053
+ ```javascript
1054
+ import { ThemeProvider, View, Button, Text } from 'app-studio';
1055
+ import { useState } from 'react';
1056
+
1057
+ function AppWithThemeToggle() {
1058
+ const [mode, setMode] = useState('light');
1059
+
1060
+ const theme = {
1061
+ primary: mode === 'light' ? 'color-blue-600' : 'color-blue-400',
1062
+ background: mode === 'light' ? 'color-white' : 'color-gray-900',
1063
+ text: mode === 'light' ? 'color-gray-900' : 'color-white',
1064
+ };
1065
+
1066
+ return (
1067
+ <ThemeProvider theme={theme} mode={mode}>
1068
+ <View
1069
+ backgroundColor="theme-background"
1070
+ color="theme-text"
1071
+ padding={20}
1072
+ minHeight="100vh"
1073
+ >
1074
+ <Button
1075
+ onClick={() => setMode(mode === 'light' ? 'dark' : 'light')}
1076
+ backgroundColor="theme-primary"
1077
+ >
1078
+ Toggle {mode === 'light' ? 'Dark' : 'Light'} Mode
1079
+ </Button>
1080
+ </View>
1081
+ </ThemeProvider>
1082
+ );
1083
+ }
1084
+ ```
1085
+
1086
+ ### Gradient Colors with Transparency
1087
+
1088
+ ```javascript
1089
+ import { View } from 'app-studio';
1090
+
1091
+ function GradientCard() {
1092
+ return (
1093
+ <View
1094
+ background={`
1095
+ linear-gradient(
1096
+ 135deg,
1097
+ color-mix(in srgb, var(--color-blue-500) 100%, transparent) 0%,
1098
+ color-mix(in srgb, var(--color-purple-500) 100%, transparent) 100%
1099
+ )
1100
+ `}
1101
+ padding={24}
1102
+ borderRadius={12}
1103
+ >
1104
+ {/* content */}
1105
+ </View>
1106
+ );
1107
+ }
1108
+ ```
1109
+
1110
+ ### Stacked State Modifiers
1111
+
1112
+ You can nest state modifiers for complex interactions:
1113
+
1114
+ ```javascript
1115
+ import { Element } from 'app-studio';
1116
+
1117
+ function ComplexButton() {
1118
+ return (
1119
+ <Element
1120
+ as="button"
1121
+ backgroundColor="theme-primary"
1122
+ color="color-white"
1123
+
1124
+ _hover={{
1125
+ backgroundColor: "theme-primary-600",
1126
+
1127
+ // Nested focus state
1128
+ _focus: {
1129
+ outline: "2px solid",
1130
+ outlineColor: "color-white",
1131
+ },
1132
+ }}
1133
+
1134
+ _active={{
1135
+ backgroundColor: "theme-primary-700",
1136
+ transform: "scale(0.98)",
1137
+ }}
1138
+
1139
+ _disabled={{
1140
+ backgroundColor: "color-gray-400",
1141
+ opacity: 0.5,
1142
+ }}
1143
+ >
1144
+ Complex State
1145
+ </Element>
1146
+ );
1147
+ }
1148
+ ```
1149
+
1150
+ ## Color Debugging Tips
1151
+
1152
+ ### Using CSS Variables Directly
1153
+
1154
+ If you need to inspect theme colors:
1155
+
1156
+ ```javascript
1157
+ // In browser console:
1158
+ // getComputedStyle(document.documentElement)
1159
+ // .getPropertyValue('--color-blue-500')
1160
+ // or
1161
+ // getComputedStyle(document.documentElement)
1162
+ // .getPropertyValue('--theme-primary')
1163
+ ```
1164
+
1165
+ ### Checking Color Availability
1166
+
1167
+ See what colors are available in your theme:
1168
+
1169
+ ```javascript
1170
+ import { useTheme } from 'app-studio';
1171
+
1172
+ function ColorDebugger() {
1173
+ const { colors } = useTheme();
1174
+
1175
+ return (
1176
+ <pre>{JSON.stringify(colors, null, 2)}</pre>
1177
+ );
1178
+ }
1179
+ ```
1180
+
1181
+ ## Color Performance Tips
1182
+
1183
+ 1. **Use CSS Variables** - Reference theme colors via CSS variables for optimal performance
1184
+ 2. **Limit Color Computations** - Pre-define commonly used color combinations
1185
+ 3. **Leverage Inheritance** - Set colors on parent elements and inherit to children
1186
+ 4. **Cache Color Mix Operations** - The browser caches `color-mix()` results
1187
+ 5. **Avoid Inline Computations** - Use theme colors directly instead of computing colors in JavaScript
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.7.11",
2
+ "version": "0.7.12",
3
3
  "name": "app-studio",
4
4
  "description": "App Studio is a responsive and themeable framework to build cross platform applications",
5
5
  "repository": "git@github.com:rize-network/app-studio.git",