Skip to content

Latest commit

Β 

History

History
537 lines (429 loc) Β· 13.7 KB

File metadata and controls

537 lines (429 loc) Β· 13.7 KB

Section Pages and Sections Documentation

🎯 Overview

Section pages are dynamic pages in the Fynd Commerce App that allow sellers to create custom templates by combining multiple reusable UI components called "sections". These pages are highly customizable and can be configured through the Theme Editor in the Fynd Platform Panel.

πŸ“‹ Table of Contents

  1. What are Section Pages?
  2. How Section Pages Work
  3. Creating Section Pages on Platform
  4. What are Sections?
  5. Anatomy of a Section
  6. Creating Custom Sections
  7. Section Rendering System
  8. Navigation and Tracking
  9. Best Practices

🏠 What are Section Pages?

Section pages are pages where you can add, edit, or remove sections. If you wish to create a custom template consisting of sections, you can create section pages. These pages are:

  • Dynamic: Content is fetched based on the page value
  • Customizable: Sections can be added, removed, or reordered
  • Responsive: Sections adapt to different screen sizes and platforms
  • Conditional: Sections can be shown/hidden based on user authentication, device type, and platform

Key Features

  • Theme-based: Content is fetched from the theme configuration
  • Section-based: Built from reusable UI components
  • Predicate-driven: Sections can be conditionally rendered
  • Performance optimized: Lazy loading of section components

βš™οΈ How Section Pages Work

1. Page Structure

// src/pages/section-page/section-page.tsx
export default function SectionPage() {
  const {fpi} = useFpi();
  const page: any = useSelector(fpi.getters.PAGE);

  return (
    <Container keyBoardAvoid scrollEnable showHeader>
      <SectionRenderer sections={page?.sections || []} />
    </Container>
  );
}

2. Data Flow

  1. Navigation: User navigates to a section page
  2. URL Parsing: Navigation tracker extracts page value from URL
  3. Theme Fetching: Theme data is fetched based on page value
  4. Section Rendering: Sections are rendered with their configurations
  5. Predicate Evaluation: Sections are filtered based on conditions

3. URL Patterns

Section pages follow specific URL patterns:

  • Section Pages: /sections/{pageValue}
    • Example: /sections/products β†’ pageValue = "products"
    • Example: /sections/home β†’ pageValue = "home"

πŸ› οΈ Creating Section Pages on Platform

Step-by-Step Process

  1. Access Theme Editor

    • Go to the Theme Editor in the Fynd platform
    • Navigate to the Platform Panel
  2. Create New Section Page

    • Click on the Pages dropdown menu on the top right corner
    • Scroll down and click on the Add Section Page option
  3. Configure Page

    • Enter a name for your section page
    • Select a Layout for your section page
    • Configure page-specific settings
  4. Add Sections

    • Add sections to your section page
    • Configure section properties
    • Set up section predicates (conditions)
  5. Save Changes

    • Review your configuration
    • Save your changes
    • Publish the theme

Example Configuration

{
  "pageName": "Product Landing",
  "pageValue": "products",
  "layout": "default",
  "sections": [
    {
      "id": "hero-1",
      "name": "hero-image",
      "props": {
        "heading": {"value": "Welcome to Our Store"},
        "description": {"value": "Discover amazing products"},
        "button_text": {"value": "Shop Now"}
      },
      "predicate": {
        "user": {
          "anonymous": true,
          "authenticated": true
        },
        "screen": {
          "mobile": true,
          "tablet": true
        }
      }
    }
  ]
}

🧩 What are Sections?

Sections are reusable UI components that sellers can customize. Section files are present inside the sections folder of a theme. Each section is a self-contained React component with:

  • Visual Interface: The component's UI
  • Configuration Schema: Settings that define customizable properties
  • Predicate Support: Conditional rendering based on various criteria
  • Responsive Design: Adapts to different screen sizes

Section Types

  • Content Sections: Display text, images, and media
  • Interactive Sections: Buttons, forms, and user interactions
  • Layout Sections: Containers and structural elements
  • Data Sections: Display dynamic content from APIs

πŸ—οΈ Anatomy of a Section

1. Component Structure

Each section must have:

// Named export for the component
export function SectionName({props, blocks}: any) {
  // Component implementation
  return <View>{/* Section UI */}</View>;
}

// Named export for settings
export const settings = {
  label: 'Section Display Name',
  props: [
    // Configuration schema
  ],
  blocks: [
    // Block configurations
  ],
};

2. Settings Configuration

The settings export defines the configuration schema:

export const settings = {
  label: 'Category Selector',
  props: [
    {
      type: 'category',
      id: 'category',
      default: '',
      label: 'Category Dropdown',
      info: 'Search a category from the dropdown',
    },
    {
      type: 'text',
      id: 'heading',
      default: 'Featured Categories',
      label: 'Section Heading',
      info: 'Enter the heading for this section',
    },
  ],
  blocks: [
    {
      type: 'hotspot_mobile',
      label: 'Product Hotspot',
      props: [
        {
          type: 'text',
          id: 'hotspot_header',
          label: 'Hotspot Title',
        },
      ],
    },
  ],
};

3. Props Structure

Props are passed to the component and contain:

interface SectionProps {
  // Configuration values
  heading?: {value: string};
  description?: {value: string};
  button_text?: {value: string};

  // Predicate information
  predicate?: {
    user?: {
      anonymous?: boolean;
      authenticated?: boolean;
    };
    screen?: {
      mobile?: boolean;
      tablet?: boolean;
    };
    platform?: {
      ios?: boolean;
      android?: boolean;
    };
  };

  // Block data
  blocks?: Array<{
    type: string;
    props: Record<string, any>;
  }>;
}

🎨 Creating Custom Sections

1. Create Section Directory

src/sections/
β”œβ”€β”€ my-custom-section/
β”‚   β”œβ”€β”€ index.ts
β”‚   β”œβ”€β”€ my-custom-section.tsx
β”‚   β”œβ”€β”€ styles.ts
β”‚   └── README.md

2. Implement Section Component

// src/sections/my-custom-section/my-custom-section.tsx
import React from 'react';
import {View} from 'react-native';
import {Text, Button} from '../../components/ui';
import {useThemedStyles} from '../../shared/hooks/use-themed-styles';
import getStyles from './styles';

export function MyCustomSection({props}: any) {
  const {heading, description, button_text, button_link} = props;

  const styles = useThemedStyles(getStyles);

  return (
    <View style={styles.container}>
      {heading?.value && (
        <Text variant="heading" style={styles.heading}>
          {heading.value}
        </Text>
      )}

      {description?.value && (
        <Text variant="body" style={styles.description}>
          {description.value}
        </Text>
      )}

      {button_text?.value && (
        <Button
          title={button_text.value}
          onPress={() => {
            // Handle button press
          }}
        />
      )}
    </View>
  );
}

export const settings = {
  label: 'My Custom Section',
  props: [
    {
      type: 'text',
      id: 'heading',
      default: 'Welcome',
      label: 'Section Heading',
      info: 'Enter the main heading',
    },
    {
      type: 'textarea',
      id: 'description',
      default: '',
      label: 'Description',
      info: 'Enter section description',
    },
    {
      type: 'text',
      id: 'button_text',
      default: 'Learn More',
      label: 'Button Text',
      info: 'Enter button text',
    },
    {
      type: 'url',
      id: 'button_link',
      default: '',
      label: 'Button Link',
      info: 'Enter button destination URL',
    },
  ],
  blocks: [],
};

3. Add to Section Map

// src/sections/index.tsx
export const sectionMap: Record<
  string,
  React.LazyExoticComponent<React.ComponentType<any>>
> = {
  'hero-image': React.lazy(() => import('./hero-image')),
  'my-custom-section': React.lazy(() => import('./my-custom-section')),
  // Add more sections here
};

4. Create Index File

// src/sections/my-custom-section/index.ts
import {MyCustomSection} from './my-custom-section';

export default MyCustomSection;

πŸ”„ Section Rendering System

1. SectionRenderer Component

The SectionRenderer component handles:

  • Lazy Loading: Sections are loaded on-demand
  • Predicate Evaluation: Filters sections based on conditions
  • Error Handling: Graceful fallbacks for missing sections
  • Performance Optimization: Suspense boundaries for loading states
// src/components/common/section-renderer/section-renderer.tsx
export default function SectionsRenderer({sections}: {sections: any[]}) {
  const {fpi} = useFpi();
  const isLoggedIn = useSelector(fpi.getters.LOGGED_IN);
  const isTablet = Dimensions.get('window').width >= 768;

  return (
    <View style={styles.container}>
      {sections.map((item, _index) => {
        // Evaluate predicates
        const isUserPredicateValid = evaluateUserPredicate(item, isLoggedIn);
        const isScreenPredicateValid = evaluateScreenPredicate(item, isTablet);
        const isPlatformPredicateValid = evaluatePlatformPredicate(item);

        // Render section if all predicates pass
        if (
          isUserPredicateValid &&
          isScreenPredicateValid &&
          isPlatformPredicateValid
        ) {
          return <SectionRenderer key={item.id} section={item} />;
        }

        return null;
      })}
    </View>
  );
}

2. Predicate Evaluation

Sections support three types of predicates:

User Predicates

predicate: {
  user: {
    anonymous: true,    // Show for non-logged-in users
    authenticated: true // Show for logged-in users
  }
}

Screen Predicates

predicate: {
  screen: {
    mobile: true,  // Show on mobile devices
    tablet: true   // Show on tablet devices
  }
}

Platform Predicates

predicate: {
  platform: {
    ios: true,     // Show on iOS
    android: true  // Show on Android
  }
}

🧭 Navigation and Tracking

1. Navigation Tracker

The navigation system automatically:

  • Detects Route Changes: Monitors navigation state
  • Extracts Page Values: Parses URLs for section pages
  • Fetches Theme Data: Loads section configurations
  • Tracks Performance: Measures navigation timing
// src/shared/hooks/use-navigation-tracker.tsx
const onRouteChange = useCallback(
  async (route: NavigationRoute) => {
    if (route.name === 'SectionPage' && route.params?.pageValue) {
      const pageValueResult = getPageValueFromPath(route.params.pageValue);

      // Fetch theme data for section page
      await fpi.executeGQL(THEME_DATA, {
        themeId: theme?.id,
        pageValue: pageValueResult.pageValue,
      });
    }
  },
  [fpi, getPageValueFromPath, theme?.id],
);

2. URL Pattern Handling

// Pattern: '/sections/products'
if (segments[0] === PATH_TYPES.SECTIONS) {
  const sectionValue = segments[1] ?? DEFAULT_PAGES.SECTIONS;
  return {pageValue: sectionValue};
}

πŸ“š Best Practices

1. Section Development

  • Keep Sections Focused: Each section should have a single responsibility
  • Use TypeScript: Define proper types for props and settings
  • Implement Error Boundaries: Handle component errors gracefully
  • Optimize Performance: Use lazy loading and memoization
  • Follow Naming Conventions: Use kebab-case for section names

2. Configuration Design

  • Provide Defaults: Always set sensible default values
  • Use Descriptive Labels: Make configuration user-friendly
  • Add Help Text: Include info text for complex properties
  • Validate Inputs: Implement proper validation for user inputs
  • Group Related Props: Organize properties logically

3. Responsive Design

  • Mobile-First: Design for mobile devices first
  • Use Flexbox: Implement flexible layouts
  • Test on Multiple Devices: Ensure compatibility across devices
  • Handle Orientation Changes: Support portrait and landscape modes

4. Performance Optimization

  • Lazy Load Sections: Use React.lazy for code splitting
  • Minimize Re-renders: Use React.memo and useMemo
  • Optimize Images: Compress and resize images appropriately
  • Cache Data: Implement caching for frequently accessed data

5. Testing

  • Unit Tests: Test individual section components
  • Integration Tests: Test section interactions
  • Visual Regression Tests: Ensure UI consistency
  • Accessibility Tests: Verify screen reader compatibility

πŸ”— Related Documentation

πŸ“ Examples

Hero Image Section

See the complete implementation in src/sections/hero-image/ for a real-world example of a section with:

  • Complex layout positioning
  • Hotspot functionality
  • Responsive design
  • Multiple configuration options
  • Predicate support

Custom Section Template

Use the template in src/sections/my-custom-section/ as a starting point for creating new sections.