@rific/auto-paper
v0.1.2
Published
Adaptive react-native-paper theming: triadic palette from a seed color + system/light/dark appearance
Maintainers
Readme
@rific/auto-paper
Adaptive theming for react-native-paper. Give it one color and an appearance setting — it generates a triadic MD3 palette and handles light/dark/system mode automatically.
Features
- Triadic color palette from a single seed color (primary → secondary → tertiary, 120° apart on the color wheel)
- System/light/dark appearance with live updates via
AppearanceAPI - Tinted surface, surfaceVariant, outline, and elevation levels derived from the seed
- Optional Redux slice for wiring appearance and color into your store
- All color utilities exported for standalone use
Installation
npm install @rific/auto-paperPeer dependencies:
npm install react-native react-native-paperUsage
Provider (simplest)
import { Provider as AutoPaperProvider } from '@rific/auto-paper'
export default function App() {
const [appearance, setAppearance] = useState<'system' | 'light' | 'dark'>('system')
const [color, setColor] = useState('#6750a4')
return (
<AutoPaperProvider appearance={appearance} color={color}>
{/* your app */}
</AutoPaperProvider>
)
}Provider renders null on the first render while the theme computes, then wraps your app in PaperProvider with the computed theme, a matching StatusBar, and a background View. Use onReady to hook into that moment — e.g. to dismiss a splash screen:
<AutoPaperProvider appearance={appearance} color={color} onReady={SplashScreen.hideAsync}>
{/* your app */}
</AutoPaperProvider>With Redux
The package exports an optional Redux slice. Use createThemeReducer to register it in your store with a custom initial color:
// store.ts
import { createThemeReducer, themeActions } from '@rific/auto-paper'
export const store = configureStore({
reducer: {
theme: createThemeReducer({ color: '#4caf50' }),
// ...
}
})Then read from the store and pass into Provider:
// App.tsx
import { useSelector } from 'react-redux'
import { Provider as AutoPaperProvider } from '@rific/auto-paper'
export default function App() {
const { appearance, color } = useSelector((state: RootState) => state.theme)
return (
<AutoPaperProvider appearance={appearance} color={color} onReady={SplashScreen.hideAsync}>
{/* your app */}
</AutoPaperProvider>
)
}// SettingsScreen.tsx
import { themeActions } from '@rific/auto-paper'
import { useDispatch } from 'react-redux'
dispatch(themeActions.setColor('#e91e63'))
dispatch(themeActions.setAppearance('dark'))With useComputedTheme
Use the hook directly when you need to extend the theme before passing it to PaperProvider — for example, to merge in a navigation theme or add custom color keys:
import { useComputedTheme } from '@rific/auto-paper'
import { DarkTheme, DefaultTheme, ThemeProvider as NavThemeProvider } from '@react-navigation/native'
import { Provider as PaperProvider } from 'react-native-paper'
export default function App() {
const theme = useComputedTheme('system', '#6750a4')
if (!theme) return null
const navTheme = {
...(theme.dark ? DarkTheme : DefaultTheme),
colors: {
...(theme.dark ? DarkTheme : DefaultTheme).colors,
background: theme.colors.background,
card: theme.colors.background
}
}
return (
<NavThemeProvider value={navTheme}>
<PaperProvider theme={theme}>
{/* your app */}
</PaperProvider>
</NavThemeProvider>
)
}API
Provider
| Prop | Type | Description |
|---|---|---|
| appearance | 'system' \| 'light' \| 'dark' | Appearance mode |
| color | string | Seed color (hex, rgb, or CSS name) |
| children | ReactNode | |
| onReady | () => void | Called once when the theme first resolves |
| statusBarProps | StatusBarProps | Spread over the auto-derived StatusBar defaults |
| style | StyleProp<ViewStyle> | Applied to the wrapper View |
useComputedTheme(appearance, color)
Returns MD3Theme | null. null on the first render while the theme computes.
const theme = useComputedTheme('system', '#6750a4')createThemeReducer(initialState?)
Returns a Redux reducer with an optional initial state override. Useful for setting a custom default color without dispatching an action at startup.
createThemeReducer({ color: '#4caf50' })Redux exports
import { themeReducer, themeActions, selectThemeAppearance, selectThemeColor } from '@rific/auto-paper'
import type { ThemeState, ThemeAppearance } from '@rific/auto-paper'| Action | Payload |
|---|---|
| initialize | Partial<ThemeState> |
| setAppearance | ThemeAppearance |
| setColor | string |
Selectors accept ThemeState directly — compose them with your root state selector:
const appearance = useSelector((state: RootState) => selectThemeAppearance(state.theme))Color utilities
import { getTriadicPalette, getBlendedColor, isDarkColor, getRgb, getHex } from '@rific/auto-paper'
getTriadicPalette('#ff0000')
// → { primary: '#ff0000', secondary: '#00ff00', tertiary: '#0000ff' }
getBlendedColor('#ff0000', '#0000ff', 0.5) // → '#800080'
isDarkColor('#6750a4') // → true
getRgb('coral') // → { r: 255, g: 127, b: 80 }
getHex('rgb(255, 0, 0)') // → '#ff0000'License
MIT
