npm package: @ramses-superapp/ramses-ui
Description: UI kit for Ramses Built Apps
Author: Dyaa El-Deen
Latest version: 0.2.0

# 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)