Skip to main content

FAQ Page with Expandable Answers

A Page that lists frequently asked questions the merchant manages from the settings panel. Tapping a question expands its answer; tapping it again - or another question - collapses it.

Settings panel​

The questions are a repeatable array field, so the merchant can add, reorder and remove them:

configurationSchema.json
[
{ "type": "text", "name": "title", "label": "Title" },
{
"type": "array",
"name": "faqs",
"label": "Questions",
"singularLabel": "question",
"schema": [
{ "type": "text", "name": "question", "label": "Question" },
{ "type": "textarea", "name": "answer", "label": "Answer" }
]
}
]
data.json
{
"title": "Frequently asked questions",
"faqs": [
{ "question": "How long does shipping take?", "answer": "Orders ship within 1-2 business days and arrive in 3-5 days." },
{ "question": "Can I return an item?", "answer": "Yes - unused items can be returned within 30 days of delivery." }
]
}

Example​

index.tsx
import React, { useState } from 'react';
import { Actionable, Box, Flexbox, Icon, Text } from '@evlop/native-components';
import { CustomBlock } from '@evlop/shopify';
import Collapsible from 'react-native-collapsible';

const FaqPage: CustomBlock.Page = ({ data }) => {
const [openIndex, setOpenIndex] = useState<number | null>(null);
const faqs = Array.isArray(data.faqs) ? data.faqs : [];

return (
<Flexbox flexDirection="column" flex={1} p="lg" gap={16}>
<Text fontSize="3xl" fontWeight="Bold">{data.title}</Text>

<Flexbox flexDirection="column">
{faqs.map((faq, index) => {
const isOpen = openIndex === index;
return (
<Box key={index} borderBottomWidth={1} borderColor="gray-100">
<Actionable action={() => setOpenIndex(isOpen ? null : index)}>
<Flexbox flexDirection="row" alignItems="center" justifyContent="space-between" gap={12} py={14}>
<Text fontWeight="Semibold" style={{ flex: 1 }}>{faq.question}</Text>
<Icon
icon={isOpen ? 'material-community-icons:chevron-up' : 'material-community-icons:chevron-down'}
size={22}
color="gray-500"
/>
</Flexbox>
</Actionable>
<Collapsible collapsed={!isOpen}>
<Text color="gray-700" pb={14}>{faq.answer}</Text>
</Collapsible>
</Box>
);
})}
</Flexbox>
</Flexbox>
);
};

export default FaqPage;

How it works​

  • array field → a list to map over. Each item in data.faqs is { question, answer }, exactly as declared in the field's nested schema. Guarding with Array.isArray keeps the page working before any questions are added.
  • One open question at a time. openIndex holds the index of the expanded question (or null); tapping the open question closes it, tapping another one switches to it.
  • Collapsible (from react-native-collapsible) animates the answer open and closed - it's one of the available packages for exactly this kind of accordion.
  • A function as an action. Actionable's action also accepts a plain function, which is handy for local UI state like this rather than an app action.
  • flex={1} on the root makes the page fill the screen, as recommended on the Page page.