Skip to content

BuilderIO/vcp-sample-app

Repository files navigation

Ecommerce

Welcome to our ecommerce project! This README provides all the necessary information to get started, including links to our Jira board and Figma designs, as well as instructions for running the project locally.

To run the project locally, clone this repository and run the following commands:

npm install
npm run dev

VCP component mapping

Figma-Component-to-React-Component mappings live in *.mapper.tsx files, these files connect specific Figma components to some of the local React components in this repos.

  1. Make sure you have the latest version of @builder.io/dev-tools installed.
npm i @builder.io/dev-tools@latest
  1. Login/Signup in Builder.io

  2. Publish existing mappings into your Builder.io space. (The CLI might prompt you to authorize with Builder.io.)

npx builder.io figma publish
  1. Open the Sample Figma file This figma files includes several components, some of which are already mapped in this repository, and some Homepage example to export to builder.io.

  2. Open the Builder.io Figma Plugin and login into the same account/space as you did in step 2.

builder-figma-plugin.mp4
  1. Click Generate Code, you will be able to see the generated code properly import and use the components in this repo.

Why publishing mappings?

Mappings don't come into effect until they are published to your Builder.io space, this allows following up figma exports to reference your local components.

To publish your mappings:

npx builder.io figma publish

Figma Mapping Files

Special files in this repository named *.mapper.tsx are used to map Figma components to React components.

Generic mapper

generic.mapper.tsx: Defines generic mappings for Figma elements.

import { figmaMapping } from "@builder.io/dev-tools/figma";

figmaMapping({
  genericMapper(figma) {
    if (figma.$type === "FRAME" && figma.$name === "Section") {
      // If we have a FRAME node named "Section" then we will render it as a <section> element.
      return <section>{figma.$children}</section>;
    }

    // For other nodes, do not apply the generic
    // mapper and keep the default rendering behavior
    return undefined;
  },
});

Component Mappings

For example, Hero.mapper.tsx maps various the Hero component from Figma to React.

import { figmaMapping } from "@builder.io/dev-tools/figma";
import ImageHero from "@/components/Hero/ImageHero";

figmaMapping({
  componentKey: "4bd6da0f53b73a462b070b55dd055ce6a4cb3eca",
  mapper(figma) {
    return (
      <ImageHero
        title={
          figma.Title ?? figma.$children[1]?.$children[0]?.$textContent ?? ""
        }
        subTitle="Discover our collection"
        buttonText={
          figma.buttonText ??
          figma.$findOneByName("Shop Now")?.$textContent ??
          ""
        }
        buttonLink="#"
        backgroundImage={figma.$children[0]?.$imageUrl ?? ""}
        alignment="center"
        makeFullBleed={false}
      />
    );
  },
});

Design Tokens Mapper

design-tokens.mapper.tsx defines mappings for design tokens (colors, etc.).

import { figmaMapping } from "@builder.io/dev-tools/figma";

figmaMapping({
  designTokenMapper(token) {
    if (token === "black") {
      return "var(--company-black, #000)";
    }

    // For anything keep the same
    return undefined;
  },
});

Builder Registry

builder-registry.ts registers custom components and design tokens with Builder.io.

"use client";
import "@builder.io/widgets";
import { builder, Builder, withChildren } from "@builder.io/react";
import { Button } from "./components/ui/button";
import Counter from "./components/Counter/Counter";
import HeroWithChildren from "./components/Hero/HeroWithChildren";
import IconCard from "./components/Card/IconCard";
import ImageHero from "./components/Hero/ImageHero";
import SplitHero from "./components/Hero/SplitHero";
import TextHero from "./components/Hero/TextHero";

builder.init(process.env.NEXT_PUBLIC_BUILDER_API_KEY!);

Builder.register("editor.settings", {
  styleStrictMode: false,
  allowOverridingTokens: true, // optional
  models: ["page"],
  designTokens: {
    colors: [
      { name: "Primary", value: "var(--color-primary, #000000)" },
      { name: "Secondary", value: "var(--color-secondary, #ffffff)" },
      { name: "Deconstructive", value: "var(--color-deconstructive, #18B4F4)" },
      { name: "Muted", value: "var(--color-muted, #C8E2EE)" },
      { name: "Accent", value: "var(--color-accent, #F35959)" },
      { name: "Energetic", value: "var(--color-energetic, #A97FF2)" },
      { name: "Background", value: "var(--color-background, #ffffff)" },
      { name: "Text", value: "var(--color-primary, #000000)" },
      { name: "Text Muted", value: "var(--color-muted, #e2e8f0)" },
      {
        name: "Background Light",
        value: "var(--color-background-light, #FAFAFA)",
      },
    ],
    spacing: [
      { name: "Large", value: "var(--space-large, 20px)" },
      { name: "Small", value: "var(--space-small, 10px)" },
      { name: "Tiny", value: "5px" },
    ],
    fontFamily: [{ name: "Primary", value: "var(--primary-font, Poppins)" }],
    fontSize: [
      { name: "Small", value: "var(--font-size-small, 12px)" },
      { name: "Medium", value: "var(--font-size-medium, 14px)" },
      { name: "Large", value: "var(--font-size-large, 16px)" },
    ],
    fontWeight: [
      { name: "Light", value: "var(--font-weight-light, 200)" },
      { name: "Normal", value: "var(--font-weight-regular, 400)" },
      { name: "Medium", value: "var(--font-weight-medium, 600)" },
      { name: "Bold", value: "var(--font-weight-bold, 800)" },
    ],
    letterSpacing: [
      { name: "Tight", value: "var(--letter-spacing-tight, -0.02em)" },
      { name: "Normal", value: "var(--letter-spacing-normal, 0em)" },
      { name: "Relaxed", value: "var(--letter-spacing-wide, 0.02em)" },
      { name: "Loose", value: "var(--letter-spacing-wide, 0.04em)" },
    ],
    lineHeight: [
      { name: "None", value: "var(--line-height-none, 1)" },
      { name: "Tight", value: "var(--line-height-tight, 1.2)" },
      { name: "Normal", value: "var(--line-height-normal, 1.5)" },
      { name: "Relaxed", value: "var(--line-height-relaxed, 1.8)" },
      { name: "Loose", value: "var(--line-height-loose, 2)" },
    ],
  },
});
Builder.register("insertMenu", {
  name: "Heros",
  items: [
    { name: "TextHero" },
    { name: "ImageHero" },
    { name: "SplitHero" },
    { name: "HeroWithChildren" },
  ],
  // priority: 2,
});
Builder.register("insertMenu", {
  name: "Cards",
  items: [{ name: "IconCard" }, { name: "ProductCard" }],
  // priority: 3,
});
if (Builder.isBrowser) {
  if (builder.editingModel === "homepage") {
    Builder.register("insertMenu", {
      name: "Layout",
      items: [
        { name: "Columns" },
        { name: "Builder:Carousel" },
        { name: "Collection" },
      ],
    });
  }
}
Builder.register("insertMenu", {
  name: "Popups",
  items: [{ name: "UpsellPopup" }],
});

Builder.registerComponent(Counter, {
  name: "Counter",
  image: "https://cdn.builder.io/api/v1/image/assets%2Fa87584e551b6472fa0f0a2eb10f2c0ff%2F000c4b516154412498592db34d340789",
  inputs: [
    {
      name: "initialCount",
      type: "number",
    },
  ],
});

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published