roundtableAI / roundtable-js

Open-source research-grade programmatic survey software
https://surveys.roundtable.ai
Apache License 2.0
247 stars 4 forks source link

feat(survey): Enable modification of all question styles from the survey styles object #41

Closed Ayush-Vashisht closed 3 weeks ago

Ayush-Vashisht commented 1 month ago

This pull request addresses the following issue:

Issue: #24

Changes:

Example Usage:

import Survey from "./library/core/survey.js";
import SingleSelect from "./library/elements/singleSelect.js";

// Define an asynchronous function to run the survey
async function runSurvey() {
  // Global styles that apply to the entire survey
  const globalStyles = {
    questionRoot: {
      marginBottom: "20px",
      padding: "10px",
      borderRadius: "5px",
      backgroundColor: "#f0f8ff",
    },
    questionLabel: {
      display: "block",
      marginBottom: "8px",
      fontWeight: "bold",
      fontSize: "1.2em",
    },
    questionSubText: {
      display: "block",
      marginBottom: "10px",
      color: "#6c757d",
      fontSize: "1em",
    },
  };

  // Create a new Survey instance with a specific participant ID
  const survey = new Survey({ participantId: "participant_123" });

  // Define the first question as a single-select question with two options
  const question1 = new SingleSelect({
    id: "question1",
    text: "What is your favorite color?",
    subText: "Choose one option below", // Subtext for additional information
    options: ["Red", "Green", "Blue"],
    styles: {
      questionRoot: globalStyles.questionRoot,
      questionLabel: globalStyles.questionLabel,
      questionSubText: globalStyles.questionSubText,
    },
  });

  // Define the second question as a single-select question with two options
  const question2 = new SingleSelect({
    id: "question2",
    text: "What is your preferred mode of transportation?",
    subText: "Select your most used mode", // Subtext for additional information
    options: ["Car", "Bike", "Public Transport"],
    styles: {
      questionRoot: globalStyles.questionRoot,
      questionLabel: globalStyles.questionLabel,
      questionSubText: globalStyles.questionSubText,
    },
  });

  // Show the first page with the first question and wait for it to be answered
  await survey.showPage({ id: "page1", elements: [question1] });

  // This code runs only after the first page is completed
  console.log("Page 1 completed");

  // Show the next page with the second question and wait for it to be answered
  await survey.showPage({ id: "page2", elements: [question2] });

  // Finish the survey once all pages are completed and display an end message
  survey.finishSurvey("Thank you for completing the survey!");
}

// Start the survey by calling the runSurvey function
runSurvey();
mdahardy commented 1 month ago

Hey Ayush - this is great. One small change:

If the user specifies a style in the Survey object, it should override the default style in the element. For example:

async function runSurvey() {
    const survey = new Survey({
        styles: {
            questionLabel: {
                fontWeight: '400',
                marginTop: '100px',
            },
        }
    });

    const q1 = new SingleSelect({
        id: 'travel_frequency',
        text: 'How often do you travel for business?',
        options: ['Never', 'Once a year', '2-3 times a year', '4-6 times a year', 'Monthly', 'Weekly'],
        required: true,
    });
    await survey.showPage({ id: 'page1', elements: [q1] });

    survey.finishSurvey('Thank you for completing our business travel survey!');
};

This should set the font weight of the questionLabel to 400 (even though it's bold by default in SingleSelect), and the marginTop to '100px' (this works in your current implementation. The user can then override survey specific styling in the element:

async function runSurvey() {
    const survey = new Survey({
        styles: {
            questionLabel: {
                fontWeight: '400',
                marginTop: '100px',
            },
        }
    });

    const q1 = new SingleSelect({
        id: 'travel_frequency',
        text: 'How often do you travel for business?',
        options: ['Never', 'Once a year', '2-3 times a year', '4-6 times a year', 'Monthly', 'Weekly'],
        required: true,
        styles: {
            questionLabel: {
                fontWeight: '600', // Override the survey font weight for this element
            },
        }
    });
    await survey.showPage({ id: 'page1', elements: [q1] });

    survey.finishSurvey('Thank you for completing our business travel survey!');
};

Other than that, looks great, and we just have to apply the same selector updates to every element type.

mdahardy commented 1 month ago

Thanks Ayush. Right now this only works for singleSelect - we should go through and update every element type so that the survey styling applies to it. I can take a stab at that and then merge it with your changes, but I'll hold off on approving the PR until that's ready.