@storysdk/react v2.0.1
@storysdk/react
React components and hooks for StorySDK. This package provides a comprehensive set of React components for rendering interactive stories and onboarding experiences with full TypeScript support.
Installation
npm install @storysdk/react
Note: This package automatically includes @storysdk/types
as a dependency. If you're using the full SDK, install @storysdk/core
instead, which includes this package.
Overview
@storysdk/react
offers:
- React Components for rendering stories and individual widgets
- TypeScript Support with full type definitions from
@storysdk/types
- Hooks for story state management and interactions
- Styling with customizable CSS and themes
- Performance optimized rendering with React best practices
Package Architecture
This package depends on @storysdk/types
for TypeScript definitions and provides the React layer for the StorySDK ecosystem:
@storysdk/react
└── @storysdk/types (TypeScript definitions)
Basic Usage
Simple Story Rendering
import { GroupsList } from "@storysdk/react";
import "@storysdk/react/dist/bundle.css";
function StoryComponent() {
const groups = [
{
id: 'group-1',
name: 'Welcome Stories',
// ... group configuration
}
];
return (
<GroupsList
groups={groups}
token="your-app-token"
/>
);
}
export default StoryComponent;
With TypeScript
import { GroupsList, GroupType } from "@storysdk/react";
import "@storysdk/react/dist/bundle.css";
interface StoryComponentProps {
groups: GroupType[];
token: string;
onStoryComplete?: (groupId: string) => void;
}
function StoryComponent({ groups, token, onStoryComplete }: StoryComponentProps) {
return (
<GroupsList
groups={groups}
token={token}
onStoryComplete={onStoryComplete}
/>
);
}
export default StoryComponent;
Components
GroupsList
Main component for rendering multiple story groups with comprehensive customization options:
import { GroupsList } from "@storysdk/react";
<GroupsList
// Required props
groups={groupsArray} // Array of GroupType
groupView="circle" // 'circle' | 'square' | 'bigSquare' | 'rectangle'
// Authentication
token="your-token" // Your StorySDK token
// Appearance customization
groupImageWidth={68} // Width of group images (default: 68)
groupImageHeight={68} // Height of group images (default: 68)
groupTitleSize={16} // Font size for group titles (default: 16)
activeGroupOutlineColor="#ff6b35" // Color for active group outline
groupsOutlineColor="#cccccc" // Color for inactive group outlines
backgroundColor="#ffffff" // Background color for stories
arrowsColor="#000000" // Color for navigation arrows
// CSS customization
groupClassName="custom-group" // CSS class for individual groups
groupsClassName="custom-groups" // CSS class for groups container
// Story display options
storyWidth={320} // Story modal width
storyHeight={568} // Story modal height
isShowMockup={true} // Show device mockup
isShowLabel={true} // Show story labels
isStatusBarActive={true} // Show status bar in stories
// Behavior options
autoplay={false} // Auto-open first story
startGroupId="group-id" // ID of group to start with
startStoryId="story-id" // ID of story to start with
forbidClose={false} // Prevent closing stories
isForceCloseAvailable={true} // Show force close button
preventCloseOnGroupClick={false} // Prevent closing on group click
openInExternalModal={false} // Open in external modal
isOnlyGroups={false} // Show only groups, no stories
// Environment options
isInReactNativeWebView={false} // React Native WebView mode
// Loading state
isLoading={false} // Show loading state
// Container reference
container={elementRef.current} // Container element reference
// Event handlers
onOpenGroup={(groupId) => console.log('Group opened:', groupId)}
onCloseGroup={(groupId) => console.log('Group closed:', groupId)}
onOpenStory={(groupId, storyId) => console.log('Story opened:', storyId)}
onCloseStory={(groupId, storyId, duration) => console.log('Story closed:', storyId, 'Duration:', duration)}
onNextStory={(groupId, storyId) => console.log('Next story:', storyId)}
onPrevStory={(groupId, storyId) => console.log('Previous story:', storyId)}
onModalOpen={(groupId, storyId) => console.log('Modal opened:', storyId)}
onModalClose={(groupId, storyId) => console.log('Modal closed:', storyId)}
onStartQuiz={(groupId, storyId) => console.log('Quiz started')}
onFinishQuiz={(groupId, storyId) => console.log('Quiz finished')}
/>
GroupsList Props Reference
Prop | Type | Default | Description |
---|---|---|---|
groups | Group[] | required | Array of story groups to display |
groupView | 'circle' \| 'square' \| 'bigSquare' \| 'rectangle' | required | Visual style for group items |
token | string | undefined | StorySDK authentication token |
groupImageWidth | number | 68 | Width of group thumbnails in pixels |
groupImageHeight | number | 68 | Height of group thumbnails in pixels |
groupTitleSize | number | 16 | Font size for group titles |
activeGroupOutlineColor | string | undefined | Hex color for active group border |
groupsOutlineColor | string | undefined | Hex color for inactive group borders |
backgroundColor | string | undefined | Background color for story modal |
arrowsColor | string | undefined | Color for navigation arrows |
groupClassName | string | undefined | CSS class for individual group items |
groupsClassName | string | undefined | CSS class for groups container |
storyWidth | number | undefined | Width of story modal |
storyHeight | number | undefined | Height of story modal |
isShowMockup | boolean | false | Display device mockup around stories |
isShowLabel | boolean | false | Show story title labels |
isStatusBarActive | boolean | false | Show status bar in story view |
autoplay | boolean | false | Automatically open first story |
startGroupId | string | undefined | ID of group to highlight initially |
startStoryId | string | undefined | ID of story to open initially |
forbidClose | boolean | false | Prevent users from closing stories |
isForceCloseAvailable | boolean | true | Show force close button |
preventCloseOnGroupClick | boolean | false | Don't close modal when clicking group |
openInExternalModal | boolean | false | Open stories in external modal |
isOnlyGroups | boolean | false | Only render groups, no story modal |
isInReactNativeWebView | boolean | false | Enable React Native WebView mode |
isLoading | boolean | false | Show loading state |
container | Element \| HTMLDivElement \| null | null | Container element reference |
Individual Widget Components
For custom layouts, you can use individual widget components:
import {
TextWidget,
ImageWidget,
VideoWidget,
QuizWidget
} from "@storysdk/react";
// Custom story layout
function CustomStoryLayout({ story }) {
return (
<div className="custom-story">
{story.widgets.map(widget => {
switch (widget.type) {
case 'text':
return <TextWidget key={widget.id} {...widget.params} />;
case 'image':
return <ImageWidget key={widget.id} {...widget.params} />;
case 'video':
return <VideoWidget key={widget.id} {...widget.params} />;
case 'quiz':
return <QuizWidget key={widget.id} {...widget.params} />;
default:
return null;
}
})}
</div>
);
}
Hooks
The package includes several utility hooks for enhanced React integration:
Available Hooks
useInterval
- Provides interval functionality with React lifecycleuseAdaptiveValue
- Adapts values based on screen size or conditionsuseAnswersCache
- Caches user answers for better performanceuseLocalStorage
- Local storage integration with React stateuseStoryCache
- Caches story data for improved loadinguseGroupCache
- Caches group data for better performanceuseSwipe
- Touch/swipe gesture handlinguseDebounced
- Debounced value updatesuseElementSize
- Track element size changes
Example Usage
import {
useLocalStorage,
useDebounced,
useSwipe
} from "@storysdk/react";
function CustomStoryComponent() {
const [viewedStories, setViewedStories] = useLocalStorage('viewedStories', []);
const debouncedSearch = useDebounced(searchTerm, 300);
const swipeHandlers = useSwipe({
onSwipeLeft: () => console.log('Swiped left'),
onSwipeRight: () => console.log('Swiped right'),
});
return (
<div {...swipeHandlers}>
{/* Your story content */}
</div>
);
}
Framework Integration
Next.js
For Next.js applications, use dynamic imports to avoid SSR issues:
import dynamic from 'next/dynamic';
import '@storysdk/react/dist/bundle.css';
// Component file (components/StoryComponent.tsx)
const StoryComponent = dynamic(
() => import('../components/StoryComponent'),
{
ssr: false,
loading: () => <div>Loading stories...</div>
}
);
// Page file
export default function HomePage() {
return (
<div>
<h1>My Next.js App</h1>
<StoryComponent />
</div>
);
}
Gatsby
// gatsby-ssr.js and gatsby-browser.js
import '@storysdk/react/dist/bundle.css';
// Component
import React from 'react';
const StoryComponent = React.lazy(() => import('../components/StoryComponent'));
function MyPage() {
return (
<React.Suspense fallback={<div>Loading...</div>}>
<StoryComponent />
</React.Suspense>
);
}
Styling and Customization
CSS Custom Properties
Override default styling with CSS variables:
:root {
--storysdk-primary-color: #your-brand-color;
--storysdk-secondary-color: #your-secondary-color;
--storysdk-border-radius: 12px;
--storysdk-font-family: 'Your Font', sans-serif;
}
Theme Configuration
import { GroupsList, ThemeProvider } from "@storysdk/react";
const customTheme = {
colors: {
primary: '#ff6b35',
secondary: '#004e64',
background: '#ffffff',
text: '#333333'
},
typography: {
fontFamily: 'Inter, sans-serif',
fontSize: {
small: '14px',
medium: '16px',
large: '18px'
}
},
spacing: {
small: '8px',
medium: '16px',
large: '24px'
}
};
function ThemedStories() {
return (
<ThemeProvider theme={customTheme}>
<GroupsList groups={groups} token={token} />
</ThemeProvider>
);
}
Performance
Code Splitting
import { lazy, Suspense } from 'react';
// Lazy load story components
const StoryComponent = lazy(() =>
import('@storysdk/react').then(module => ({
default: module.GroupsList
}))
);
function App() {
return (
<Suspense fallback={<div>Loading stories...</div>}>
<StoryComponent groups={groups} token={token} />
</Suspense>
);
}
Memory Management
import { useEffect, useRef } from 'react';
import { GroupsList } from '@storysdk/react';
function OptimizedStoryComponent({ groups, token }) {
const storyRef = useRef(null);
useEffect(() => {
// Cleanup on unmount
return () => {
if (storyRef.current) {
storyRef.current.destroy();
}
};
}, []);
return (
<GroupsList
ref={storyRef}
groups={groups}
token={token}
preloadNextStory={false} // Disable preloading for memory optimization
maxCacheSize={5} // Limit cached stories
/>
);
}
TypeScript Support
Full TypeScript support with types from @storysdk/types
:
import {
GroupType,
WidgetType,
GroupsListProps,
StoryEventHandler
} from '@storysdk/react';
// All props are fully typed
const storyProps: GroupsListProps = {
groups: groupsArray, // GroupType[]
token: 'your-token', // string
onStoryStart: (groupId: string) => void,
onStoryComplete: (groupId: string) => void
};
Migration from @storysdk/core
If you're using the high-level Story
class from @storysdk/core
, you can optionally migrate to React components for better React integration:
// Current approach (with @storysdk/core)
import { Story } from '@storysdk/core';
import { useRef, useEffect } from 'react';
function StoryComponent({ token }) {
const ref = useRef(null);
useEffect(() => {
const story = new Story(token);
story.renderGroups(ref.current);
return () => story.destroy();
}, [token]);
return <div ref={ref} />;
}
// Alternative approach (with @storysdk/react)
import { GroupsList } from '@storysdk/react';
function StoryComponent({ groups, token }) {
return <GroupsList groups={groups} token={token} />;
}
Note: The @storysdk/core
approach is still the recommended method for most use cases. Use @storysdk/react
components directly only when you need custom layouts or fine-grained control over individual story elements.
Related Packages
- @storysdk/types - TypeScript definitions (included automatically)
- @storysdk/core - Complete SDK with this package included
Resources
7 months ago
7 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
7 months ago
4 months ago
4 months ago
5 months ago
5 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
5 months ago
5 months ago
5 months ago
6 months ago
6 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
10 months ago
10 months ago
10 months ago
10 months ago
8 months ago
9 months ago
12 months ago
11 months ago
11 months ago
11 months ago
11 months ago
9 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago