UNPKG

@ramses-superapp/ramses-ui

Version:

Skinless UI primitives for Ramses Built Apps

344 lines (256 loc) 8.46 kB
# Ramses UI A modern, theme-aware UI kit for React Native, designed for Ramses-built apps. Includes customizable components, seamless light/dark theming, and built-in Cairo font support. --- ## Features - Light & dark mode with auto device detection - Cairo font family integration (Android/iOS) - Ready-to-use components: Button, Text, TextInput - Simple, powerful theming via `ThemeProvider` - Ergonomic, theme-aware styling utilities --- ## Installation ```sh npm install @ramses-superapp/ramses-ui # or yarn add @ramses-superapp/ramses-ui ``` --- ## Quick Start Wrap your app with the `ThemeProvider` for automatic theming: ```tsx import { ThemeProvider } from '@ramses-superapp/ramses-ui'; export default function App() { return <ThemeProvider>{/* your app code */}</ThemeProvider>; } ``` --- ## What ThemeProvider Does When you wrap your app with `ThemeProvider`, it does more than just provide theming: - **Safe Area Handling:** Your app is automatically wrapped in a `SafeAreaView` for proper layout on all devices. - **Keyboard Avoidance:** A `KeyboardAvoidingView` is included, so your UI adjusts automatically when the keyboard appears (on both iOS and Android). - **Keyboard Dismissal:** The entire app is wrapped in a touchable area, so tapping outside of inputs will dismiss the keyboard by default. - **Status Bar Styling:** The status bar style and color are set based on the current theme. This means you get best-practice layout and keyboard handling out of the box—no need to add these wrappers yourself! --- ## Components ### RsButton - `title` (string/number): Button label - `primary` (bool): Primary style (default: true) - `isLoading` (bool): Show spinner - `disabled` (bool): Disable button - `onPress` (fn): Press handler - `fontSize`, `fontWeight`, `textStyle`, `style`, `width` ### RsText - `text` (string/number): Content - `fontSize`, `fontWeight`, `textAlign`, `textTransform`, `color` - `pressable` (bool), `onPress` (fn) - `style`, `containerStyle` ### RsTextInput - All standard `TextInput` props - All `RsText` style props - `containerStyle` - Floating label with Cairo font #### FontWeight All components support: `'ExtraLight' | 'Light' | 'Regular' | 'Medium' | 'SemiBold' | 'Bold' | 'ExtraBold' | 'Black'` ### RsDivider A flexible, theme-aware divider for separating content, supporting horizontal/vertical orientation, custom thickness, color, margin, and center content (text or custom node). **Props:** - `direction` (`'row' | 'column'`): Divider orientation. `'column'` (default) is horizontal, `'row'` is vertical. - `thickness` (number): Line thickness. Default: `1`. - `color` (string): Line color. Default: theme border color. - `margin` (number): Margin in the _opposite_ direction. Default: `8`. - `content` (string | ReactNode): Center content (e.g., "or", icon, etc.). Optional. - `textProps` (`RsTextStyle`): Props for customizing `RsText` if `content` is a string. - `style` (ViewStyle): Style for the outer container. - `lineStyle` (ViewStyle): Style for the line(s). **Usage:** ```tsx import { RsDivider } from '@ramses-superapp/ramses-ui'; // Horizontal divider with text <RsDivider content="or" /> // Vertical divider (for row layouts) <RsDivider direction="row" thickness={2} margin={16} /> // Divider with custom node in the center <RsDivider content={<MyIcon />} color="#A549E5" /> // Simple horizontal line <RsDivider /> ``` ### RsToggleButton A two-option, animated toggle switch for binary choices (e.g., Yes/No, On/Off). Theme-aware, fully animated, and adapts to parent width. **Props:** - `choices` (`[{ label: string, value: T }, { label: string, value: T }]`): Array of two options to display. Each option has a `label` and a `value`. - `value` (`T`): The currently selected value. - `onChange` (`(value: T) => void`): Callback when the selection changes. - `style` (`ViewStyle`, optional): Style for the outer container. **Usage:** ```tsx import { RsToggleButton } from '@ramses-superapp/ramses-ui'; const [value, setValue] = useState<'yes' | 'no'>('yes'); <RsToggleButton choices={[ { label: 'Yes', value: 'yes' }, { label: 'No', value: 'no' }, ]} value={value} onChange={setValue} />; ``` --- ## Theming & Customization ### ThemeProvider Props - `mode`: `'light' | 'dark' | 'auto'` (default: `'auto'`) - `'auto'`: Follows device color scheme - `'light'`: Forces light mode - `'dark'`: Forces dark mode - `customLightTheme`: (optional) Custom theme object for light mode - `customDarkTheme`: (optional) Custom theme object for dark mode **Force Light or Dark Mode:** ```tsx <ThemeProvider mode="light">{/* ... */}</ThemeProvider> <ThemeProvider mode="dark">{/* ... */}</ThemeProvider> ``` **Provide Custom Themes:** ```tsx import { ThemeProvider, colors } from '@ramses-superapp/ramses-ui'; const MyLightTheme = { /* ...see below... */ }; const MyDarkTheme = { /* ...see below... */ }; <ThemeProvider mode="auto" customLightTheme={MyLightTheme} customDarkTheme={MyDarkTheme} > {/* ... */} </ThemeProvider>; ``` #### Theme Object Structure ```ts type Theme = { Background: { screen: string; input: string; primaryButton: string; secondaryButton: string; }; Text: { primaryTitle: string; text: string; highlightText: string; inputText: string; inputPlaceholder: string; primaryButtonText: string; secondaryButtonText: string; }; Borders: { primaryButton: string; secondaryButton: string; input: string; inputActive: string; }; StatusBar: { barStyle: 'light-content' | 'dark-content'; }; }; ``` #### Accessing the Theme Use the `useTheme()` hook in your components: ```tsx import { useTheme } from '@ramses-superapp/ramses-ui'; const theme = useTheme(); ``` --- ## Cairo Font Integration - Fonts are auto-linked for Android/iOS. - **iOS only:** Add to your `Info.plist`: ```xml <key>UIAppFonts</key> <array> <string>Cairo-Regular-Tight.ttf</string> <string>Cairo-Bold-Tight.ttf</string> <string>Cairo-ExtraBold-Tight.ttf</string> <string>Cairo-Black-Tight.ttf</string> <string>Cairo-ExtraLight-Tight.ttf</string> <string>Cairo-Light-Tight.ttf</string> <string>Cairo-Medium-Tight.ttf</string> <string>Cairo-SemiBold-Tight.ttf</string> </array> ``` - Clean & rebuild your app after linking fonts. --- ## Theme-Aware Styling ### User-Friendly: `useStyles` The easiest way to create theme-aware and dynamic styles. Just provide a style object factory that receives the current theme and any state/props you want. ```tsx import { useStyles } from '@ramses-superapp/ramses-ui'; function MyComponent({ isActive }) { const styles = useStyles( (theme, { isActive }) => ({ container: { backgroundColor: isActive ? theme.Background.primaryButton : theme.Background.screen, padding: 16, borderRadius: 8, }, text: { color: theme.Text.text, fontSize: 18, }, }), { isActive } ); return ( <View style={styles.container}> <Text style={styles.text}>Hello Themed World</Text> </View> ); } ``` - No need to call `StyleSheet.create` or `useMemo` yourself. - Styles update automatically when the theme or any prop/state changes. --- ### Advanced: `useThemedStyles` If you need more control over memoization or want to pass multiple arguments, use the lower-level `useThemedStyles` hook. ```tsx import { useThemedStyles, type Theme } from '@ramses-superapp/ramses-ui'; import { StyleSheet } from 'react-native'; const generateStyles = (theme: Theme, isActive: boolean) => StyleSheet.create({ container: { backgroundColor: isActive ? theme.Background.primaryButton : theme.Background.screen, padding: 16, borderRadius: 8, }, text: { color: theme.Text.text, fontSize: 18, }, }); function MyComponent({ isActive }) { const styles = useThemedStyles(generateStyles, isActive); return ( <View style={styles.container}> <Text style={styles.text}>Hello Themed World</Text> </View> ); } ``` --- ## Scripts - `yarn test` Run tests - `yarn lint` Lint code - `yarn typecheck` TypeScript check - `yarn clean` Clean build artifacts - `yarn example` Run example app --- ## License MIT --- Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)