### Initialize Subframe CLI Source: https://docs.subframe.com/installation Execute this command in your project's root directory to install the latest Subframe CLI and begin the interactive setup process for your project. ```Shell npx @subframe/cli@latest init ``` -------------------------------- ### Configure Subframe Project Settings Source: https://docs.subframe.com/installation Answer a series of prompts to customize Subframe's integration, including component sync directory, alias configuration, Tailwind CSS setup, and dependency installation. ```Shell Where should the Subframe components be synced to? › ./src Configure an alias for the subframe component directory (e.g. @/ui) › @/ui/* Do you want Subframe to configure your Tailwind config? › (Y/n) Would you like to sync all of your Subframe components? › (Y/n) Would you like to install dependencies? › (Y/n) ``` -------------------------------- ### Example Project File Structure Source: https://docs.subframe.com/framework-guides/manual Illustrates a typical project directory layout assumed for Subframe integration, including source files, HTML, and configuration files like `package.json` and `tsconfig.json`. ```Shell my-app/ |-- src/ | |-- main.tsx | `-- styles.css |-- index.html |-- package.json `-- tsconfig.json ``` -------------------------------- ### Install Tailwind CSS, PostCSS, and Autoprefixer Source: https://docs.subframe.com/framework-guides/manual Command to install the necessary development dependencies for setting up Tailwind CSS, including PostCSS for processing CSS and Autoprefixer for vendor prefixes. This command is typically run using a package manager like npm, yarn, pnpm, or bun. ```Shell npm install -D tailwindcss@^3 postcss autoprefixer ``` -------------------------------- ### Install Subframe CLI in Next.js Project Source: https://docs.subframe.com/framework-guides/nextjs This command initiates the installation and configuration of Subframe within your Next.js project. It utilizes `npx` to execute the latest version of the `@subframe/cli` package, streamlining the setup process. ```Shell npx @subframe/cli@latest init ``` -------------------------------- ### Install Subframe CLI for Astro Source: https://docs.subframe.com/framework-guides/astro Run this command in the root of your repository to install Subframe and configure your project. This command uses npx to execute the latest version of the Subframe CLI. ```Shell npx @subframe/cli@latest init ``` -------------------------------- ### Select Project Starter Template Source: https://docs.subframe.com/installation During the Subframe CLI initialization, choose from optimized starter templates like Next.js, Vite, or Astro to set up a new project. ```Shell ? Would you like to start a new project? › - Use arrow-keys. Return to submit. ❯ Next.js Vite Astro ``` -------------------------------- ### Install Subframe Core Package Source: https://docs.subframe.com/framework-guides/manual Command to install the `@subframe/core` package, which is the main dependency for Subframe functionality. It is recommended to install the latest version. This command is typically run using a package manager like npm, yarn, pnpm, or bun. ```Shell npm install @subframe/core@latest ``` -------------------------------- ### Install and Initialize Subframe CLI in Package Source: https://docs.subframe.com/framework-guides/monorepo Navigates into the `@repo/subframe` package directory and executes the Subframe CLI initialization command. The `--sync` flag enables component synchronization, and `--dir ui` specifies 'ui' as the output directory for synced components. It's critical to set the import alias to `@repo/subframe/*` during this initialization for proper component resolution. ```Shell cd packages/subframe && npx @subframe/cli@latest init --sync --dir ui ``` -------------------------------- ### Sync Subframe Components with CLI Source: https://docs.subframe.com/framework-guides/manual This command uses `npx` to execute the latest version of the `@subframe/cli` package. It triggers the `sync --all` operation, which downloads all Subframe component code into your project. The Subframe CLI automatically locates project settings within your `.subframe` directory to guide the download process. ```cli npx @subframe/cli@latest sync --all ``` -------------------------------- ### Install Subframe CLI in Vite Project Source: https://docs.subframe.com/framework-guides/vite Execute this command in your repository's root directory to install the latest Subframe CLI and automatically configure your Vite project for Subframe integration. ```bash npx @subframe/cli@latest init ``` -------------------------------- ### Install Monorepo Dependencies Source: https://docs.subframe.com/framework-guides/monorepo Executes the package manager's install command to resolve and link all project dependencies, including the newly added `@repo/subframe` package, within the monorepo. This ensures all required packages are available for development. ```Shell npm install ``` -------------------------------- ### Project File Structure After Tailwind CSS Initialization Source: https://docs.subframe.com/framework-guides/manual Shows the updated project directory structure after initializing Tailwind CSS, highlighting the newly created `postcss.config.js` and `tailwind.config.js` files. ```Shell my-app/ |-- src/ | |-- main.tsx | `-- styles.css |-- index.html |-- package.json |-- tsconfig.json |-- postcss.config.js `-- tailwind.config.js ``` -------------------------------- ### Subframe CLI Sync Command Arguments and Options Source: https://docs.subframe.com/syncing-components API documentation for the `subframe/cli sync` command, detailing its available arguments and options. This includes specifying components to sync, syncing all components, and installing dependencies post-sync. ```APIDOC Arguments: components the components to sync Options: -a, --all sync all components -p, --projectId project id to run sync with -i, --install install dependencies after syncing -h, --help display help for command ``` -------------------------------- ### Authenticate Subframe CLI with Access Token Source: https://docs.subframe.com/installation Provide your Subframe access token, obtained from the specified URL, to authenticate the CLI and link it to your Subframe account. ```Shell > No existing credentials found. > To get new credentials, please visit the following URL in your web browser: > https://app.subframe.com/cli/auth > You will need to login then enter the provided credentials below. ? Access token › ``` -------------------------------- ### Import Global Stylesheet into Main Application File Source: https://docs.subframe.com/framework-guides/manual Imports the `styles.css` file, which contains the Tailwind CSS directives, into the application's primary entry point (`src/main.tsx`). This ensures that the global styles are loaded and applied when the application starts. ```TypeScript import './styles.css'; ``` -------------------------------- ### Generate New Package for Subframe in Turborepo Source: https://docs.subframe.com/framework-guides/monorepo Utilizes the `turbo generate` command to create a new package named `@repo/subframe` within an existing Turborepo monorepo. This package will serve as the container for Subframe components. Users are prompted to select TypeScript and ESLint configuration packages as devDependencies during the interactive setup. ```Shell npx turbo generate workspace --name @repo/subframe --type package ``` -------------------------------- ### Subframe UI Configuration Object Example Source: https://docs.subframe.com/theme An example JavaScript configuration object, likely for a UI framework, defining various design tokens. This includes typography settings (font size, line height, font weight, letter spacing), font families, box shadows (sm, default, md, lg, overlay), border radii (sm, md, DEFAULT, lg, full), container padding for different screen sizes, custom spacing values, and screen breakpoints. ```javascript "monospace-body": [ "14px", { lineHeight: "20px", fontWeight: "400", letterSpacing: "0em", }, ], }, fontFamily: { caption: "Figtree", "caption-bold": "Figtree", body: "Figtree", "body-bold": "Figtree", "heading-3": "Figtree", "heading-2": "Figtree", "heading-1": "Figtree", "monospace-body": "monospace", }, boxShadow: { sm: "0px 1px 2px 0px rgba(0, 0, 0, 0.05)", default: "0px 1px 2px 0px rgba(0, 0, 0, 0.05)", md: "0px 4px 16px -2px rgba(0, 0, 0, 0.08), 0px 2px 4px -1px rgba(0, 0, 0, 0.08)", lg: "0px 12px 32px -4px rgba(0, 0, 0, 0.08), 0px 4px 8px -2px rgba(0, 0, 0, 0.08)", overlay: "0px 12px 32px -4px rgba(0, 0, 0, 0.08), 0px 4px 8px -2px rgba(0, 0, 0, 0.08)", }, borderRadius: { sm: "4px", md: "8px", DEFAULT: "8px", lg: "12px", full: "9999px", }, container: { padding: { DEFAULT: "16px", sm: "calc((100vw + 16px - 640px) / 2)", md: "calc((100vw + 16px - 768px) / 2)", lg: "calc((100vw + 16px - 1024px) / 2)", xl: "calc((100vw + 16px - 1280px) / 2)", "2xl": "calc((100vw + 16px - 1536px) / 2)", }, }, spacing: { 112: "28rem", 144: "36rem", 192: "48rem", 256: "64rem", 320: "80rem", }, screens: { mobile: { max: "767px", }, } } ``` -------------------------------- ### Create .subframe/sync.json Configuration File Source: https://docs.subframe.com/framework-guides/manual Defines the structure and content of the `.subframe/sync.json` file. This file holds configuration settings for Subframe's component synchronization, including the target directory for synced components, an import alias, and the project ID. ```JSON { "directory": "./src/ui", "importAlias": "@/ui/*", "projectId": "YOUR_PROJECT_ID" } ``` -------------------------------- ### Initialize Tailwind CSS and PostCSS Configuration Files Source: https://docs.subframe.com/framework-guides/manual Command to generate the `tailwind.config.js` and `postcss.config.js` files in the project root, which are essential for configuring Tailwind CSS. This command is typically run using a package manager's executor like npx. ```Shell npx tailwindcss init -p ``` -------------------------------- ### Subframe Sync Configuration File Source: https://docs.subframe.com/framework-guides/monorepo Displays the content of the `.subframe/sync.json` file, which defines the local directory ('ui') where Subframe components are synced and the `importAlias` (`@repo/subframe/*`) used for referencing these components within the monorepo. This configuration is crucial for correct component imports. ```JSON { "directory": "ui", "importAlias": "@repo/subframe/*" } ``` -------------------------------- ### Configure ESLint for Subframe Package Source: https://docs.subframe.com/framework-guides/monorepo Sets up ESLint for the newly created `@repo/subframe` package. It imports a shared ESLint configuration from `@repo/eslint-config/react-internal` to ensure consistent linting rules are applied across the monorepo, specifically for React-related code. ```JavaScript import { config } from "@repo/eslint-config/react-internal"; /** @type {import("eslint").Linter.Config} */ export default config; ``` -------------------------------- ### Clone Lovable Project Repository Source: https://docs.subframe.com/export-to-lovable Clones the Lovable project's GitHub repository to your local machine. This is a crucial prerequisite for installing Subframe and running the project locally, as per the instructions provided in the Readme. ```Bash git clone ... ``` -------------------------------- ### Configure Astro to use import aliases in tsconfig.json Source: https://docs.subframe.com/framework-guides/astro Update your tsconfig.json file to include a 'baseUrl' and 'paths' configuration. This enables import aliases like '@/*' for easier module resolution, pointing to your 'src' directory. ```JSON { "compilerOptions": { "baseUrl": "./", "paths": { "@/*": [ "./src/*" ] }, "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2020", "useDefineForClassFields": true, "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, "isolatedModules": true, "moduleDetection": "force", "noEmit": true, "jsx": "react-jsx", /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, "include": ["src"] } ``` -------------------------------- ### Add Tailwind CSS Directives to Main Stylesheet Source: https://docs.subframe.com/framework-guides/manual Adds the `@tailwind` directives (`base`, `components`, `utilities`) to the `src/styles.css` file. These directives are crucial for injecting Tailwind's generated styles into the application's CSS. ```CSS @tailwind base; @tailwind components; @tailwind utilities; ``` -------------------------------- ### Example TrackCard Component Using Only Props Source: https://docs.subframe.com/props-and-slots This React component demonstrates the usage of a `TrackCardWithProps` component, illustrating how props are used for passing static content like title, artist, and image URL. The inline comments highlight the limitations of this prop-only approach, specifically the inability to add dynamic event handlers or expose underlying subcomponent properties like `alt` text for images. ```TypeScript "use client" import { TrackCardWithProps } from "@/ui/components/TrackCardWithProps" function TrackCardWithPropsExample() { const [isFavorite, setIsFavorite] = useState(false) function handleFavoriteClick() { setIsFavorite((prev) => !prev) } const favoriteIcon = isFavorite ? "FeatherHeartOff" : "FeatherHeart" return ( are not exposed image="/covers/tame_impala-currents.jpg" // We have no way to add an onClick handler or an icon to our // FavoriteButton here, since it's events are not exposed /> ) } export default TrackCardWithPropsExample ``` -------------------------------- ### Configure TypeScript Path Aliases in tsconfig.app.json for Vite Source: https://docs.subframe.com/framework-guides/vite Modify your `tsconfig.app.json` to define `compilerOptions` that enable TypeScript to correctly resolve import aliases, specifically mapping `@/*` to `./src/*` for better module organization in your Vite project. ```json { "compilerOptions": { "baseUrl": "./", "paths": { "@/*": [ "./src/*" ] }, "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2020", "useDefineForClassFields": true, "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, "isolatedModules": true, "moduleDetection": "force", "noEmit": true, "jsx": "react-jsx", /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, "include": ["src"] } ``` -------------------------------- ### Import and Use Subframe Alert Component in React Source: https://docs.subframe.com/using-components This example demonstrates how to import and use a Subframe `Alert` component within a React application. It shows how to pass `variant`, `icon`, `title`, and `description` props to customize the alert's appearance and content. This assumes components have been synced and an import alias is configured. ```TypeScript import { Alert } from "@/ui/components/Alert" function App() { return ( ) } export default App ``` -------------------------------- ### React Magic Link Login Form UI (Initial) Source: https://docs.subframe.com/adding-business-logic This TypeScript/React snippet presents the initial user interface for a magic link login form. It showcases the basic structure of a Subframe-generated component, including a `DialogLayout`, `TextField` for email input, and a `Button`. This version lacks any business logic for form submission or state management, serving as a starting point before adding interactivity. ```TypeScript import { DialogLayout } from "@/ui/layouts/DialogLayout" import { TextField } from "@/ui/components/TextField" import { Button } from "@/ui/components/Button" function App() { return (
Magic Link Login
) } export default App ``` -------------------------------- ### Update Tailwind CSS Configuration for Content Scanning Source: https://docs.subframe.com/framework-guides/manual Modifies the `tailwind.config.js` file to specify the `content` array, instructing Tailwind CSS where to scan for class names to generate the final CSS. It includes HTML and all JavaScript/TypeScript/JSX files within the `src` directory. ```JavaScript /** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./index.html", "./src/**/*.{js,jsx,ts,tsx}" ], theme: { extend: {}, }, plugins: [], presets: [] } ``` -------------------------------- ### Export Subframe Components from Package Source: https://docs.subframe.com/framework-guides/monorepo Modifies the `package.json` of the `@repo/subframe` package to define `exports` fields. This configuration allows other applications within the monorepo to directly import Subframe components, layouts, and the associated Tailwind CSS configuration from this shared package. ```JSON { "name": "@repo/subframe", "version": "0.0.0", "private": true, "exports": { ".": "./ui/index.ts", "./components/*": "./ui/components/*.tsx", "./layouts/*": "./ui/layouts/*.tsx", "./tailwind-config": "./ui/tailwind.config.js" }, "dependencies": { "@subframe/core": "^1.141.0" }, "devDependencies": { "@repo/eslint-config": "*", "@repo/typescript-config": "*" } } ``` -------------------------------- ### Add Subframe Monorepo Package to App Dependencies Source: https://docs.subframe.com/framework-guides/monorepo Adds the locally defined `@repo/subframe` package as a dependency in a frontend application's `package.json`. This step links the shared Subframe components package to the consuming application within the monorepo, enabling its use. ```JSON "@repo/subframe": "*" ``` -------------------------------- ### Configure Vite Resolver for TypeScript Path Aliases Source: https://docs.subframe.com/framework-guides/vite Update your `vite.config.ts` file to include a `resolve.alias` configuration. This ensures Vite can correctly resolve modules using the `@` alias, pointing to your `src` directory, preventing import errors. ```typescript import { defineConfig } from "vite" import react from "@vitejs/plugin-react" import { resolve } from "node:path" export default defineConfig({ plugins: [react()], resolve: { alias: { "@": resolve(__dirname, "./src"), } } }) ``` -------------------------------- ### Include Subframe's Tailwind CSS Preset in Configuration Source: https://docs.subframe.com/framework-guides/manual Modifies the `tailwind.config.js` file to include Subframe's custom Tailwind CSS preset. This ensures that the theme and styling defined within Subframe are correctly applied to the application, typically by referencing a generated configuration file. ```JavaScript /** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./index.html", "./src/**/*.{js,jsx,ts,tsx}" ], theme: { extend: {}, }, plugins: [], presets: [ require("./src/ui/tailwind.config") ] } ``` -------------------------------- ### Configure TailwindCSS for Subframe Components Source: https://docs.subframe.com/framework-guides/monorepo This JavaScript configuration file for Tailwind CSS demonstrates how to integrate Subframe's styling. It extends the content array to include Subframe's UI files, ensuring their styles are processed by Tailwind. Additionally, it imports Subframe's predefined Tailwind preset for consistent theming and utility classes. ```JavaScript /** @type {import('tailwindcss').Config} */ export default { content: [ "./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}", "./app/**/*.{js,ts,jsx,tsx}", "./ui/**/*.{js,ts,jsx,tsx}", "../../packages/subframe/ui/**/*.{js,ts,jsx,tsx}", ], theme: { extend: {}, }, plugins: [], presets: [require("@repo/subframe/tailwind-config")], }; ``` -------------------------------- ### Tailwind CSS Theme Extension for Colors and Typography Source: https://docs.subframe.com/theme A complete `tailwind.config.js` example demonstrating how to extend the default Tailwind CSS theme. This configuration defines custom color palettes (brand, neutral, error, warning, success) and custom font sizes with detailed line height, font weight, and letter spacing for various text styles (caption, body, heading). This file is typically generated by the Subframe CLI. ```JavaScript module.exports = { // ... theme: { extend: { colors: { brand: { 50: "rgb(250, 250, 250)", 100: "rgb(245, 245, 245)", 200: "rgb(229, 229, 229)", 300: "rgb(212, 212, 212)", 400: "rgb(163, 163, 163)", 500: "rgb(115, 115, 115)", 600: "rgb(38, 38, 38)", 700: "rgb(64, 64, 64)", 800: "rgb(38, 38, 38)", 900: "rgb(23, 23, 23)" }, neutral: { 0: "rgb(255, 255, 255)", 50: "rgb(250, 250, 250)", 100: "rgb(245, 245, 245)", 200: "rgb(229, 229, 229)", 300: "rgb(212, 212, 212)", 400: "rgb(163, 163, 163)", 500: "rgb(115, 115, 115)", 600: "rgb(82, 82, 82)", 700: "rgb(64, 64, 64)", 800: "rgb(38, 38, 38)", 900: "rgb(23, 23, 23)", 950: "rgb(10, 10, 10)" }, error: { 50: "rgb(254, 242, 242)", 100: "rgb(254, 226, 226)", 200: "rgb(254, 202, 202)", 300: "rgb(252, 165, 165)", 400: "rgb(248, 113, 113)", 500: "rgb(239, 68, 68)", 600: "rgb(220, 38, 38)", 700: "rgb(185, 28, 28)", 800: "rgb(153, 27, 27)", 900: "rgb(127, 29, 29)" }, warning: { 50: "rgb(240, 249, 255)", 100: "rgb(224, 242, 254)", 200: "rgb(186, 230, 253)", 300: "rgb(125, 211, 252)", 400: "rgb(56, 189, 248)", 500: "rgb(14, 165, 233)", 600: "rgb(2, 132, 199)", 700: "rgb(3, 105, 161)", 800: "rgb(7, 89, 133)", 900: "rgb(12, 74, 110)" }, success: { 50: "rgb(240, 253, 244)", 100: "rgb(220, 252, 231)", 200: "rgb(187, 247, 208)", 300: "rgb(134, 239, 172)", 400: "rgb(74, 222, 128)", 500: "rgb(34, 197, 94)", 600: "rgb(22, 163, 74)", 700: "rgb(21, 128, 61)", 800: "rgb(22, 101, 52)", 900: "rgb(20, 83, 45)" }, "brand-primary": "rgb(38, 38, 38)", "default-font": "rgb(23, 23, 23)", "subtext-color": "rgb(115, 115, 115)", "neutral-border": "rgb(229, 229, 229)", white: "rgb(255, 255, 255)", "default-background": "rgb(255, 255, 255)" }, fontSize: { caption: [ "12px", { lineHeight: "16px", fontWeight: "400", letterSpacing: "0em" } ], "caption-bold": [ "12px", { lineHeight: "16px", fontWeight: "500", letterSpacing: "0em" } ], body: [ "14px", { lineHeight: "20px", fontWeight: "400", letterSpacing: "0em" } ], "body-bold": [ "14px", { lineHeight: "20px", fontWeight: "500", letterSpacing: "0em" } ], "heading-3": [ "16px", { lineHeight: "20px", fontWeight: "600", letterSpacing: "0em" } ], "heading-2": [ "20px", { lineHeight: "24px", fontWeight: "600", letterSpacing: "0em" } ], "heading-1": [ "30px", { lineHeight: "36px", fontWeight: "600", letterSpacing: "0em" } ] } } } }; ``` -------------------------------- ### Initialize Subframe CLI with Tailwind CSS v4 Source: https://docs.subframe.com/theme Command to initialize a new Subframe project, enabling experimental support for Tailwind CSS v4. This command uses the `npx` utility to execute the latest version of the Subframe CLI and configure it for Tailwind CSS v4. ```bash npx @subframe/cli@latest init --css-type tailwind-v4 ``` -------------------------------- ### Sync All Subframe Components via CLI Source: https://docs.subframe.com/syncing-components Command to sync all Subframe components from the cloud to your local codebase. This operation creates a local copy of all components, ensuring your project has the latest versions. ```shell npx @subframe/cli@latest sync --all ``` -------------------------------- ### Cursor AI Rules for Subframe Projects Source: https://docs.subframe.com/export-to-cursor This Markdown snippet defines general and framework-specific rules for Cursor AI when working with Subframe-generated components. It outlines guidelines for handling the 'ui' directory, checking for Next.js, Vite, or Astro configurations, importing Google Fonts, and the command to sync Subframe components. ```Markdown # Project Overview This project is built using components generated by a design tool called Subframe. The files for these components are located in the `ui` directory. NEVER EDIT THE FILES IN THE `ui` DIRECTORY. Instead, whem implementing business logic, wrap them in your own components. The `ui` directory may be in different places, so check the codebase first to make sure you find it. If you can't find it on the first try, look harder. It could be in the `src/ui` directory. If you can't find it, ask the user where it is. # General Guidelines Check if this project uses Next.js by looking for a `next.config.(js|mjs|cjs|ts|cts|mts)` file. If so, adhere to the guidelines in @nextjs.mdc. Check if this project uses vite by looking for a `vite.config.(js|mjs|cjs|ts|cts|mts)` file. If so, adhere to the guidelines in @vite.mdc. Check if this project uses astro by looking for a `astro.config.(js|mjs|cjs|ts|cts|mts)` file. If so, adhere to the guidelines in @astro.mdc. Check `ui/tailwind.config.js` for the fonts used in the project. Import them using Google Fonts adhering the to following structure: When the user wants to sync their Subframe components, run `[PACKAGE_MANAGER_COMMAND] exec @subframe/cli@latest sync -all`. ``` -------------------------------- ### Sync Specific Subframe Components via CLI Source: https://docs.subframe.com/syncing-components Command to sync only selected Subframe components (e.g., Alert, Accordion) to your local codebase. This is useful for managing specific parts of your application without updating all components. ```shell npx @subframe/cli@latest sync Alert Accordion ``` -------------------------------- ### Implement Responsive Container Utility Class Source: https://docs.subframe.com/theme This CSS `@utility` rule defines a responsive container class that adjusts its horizontal padding based on screen breakpoints. It ensures content is centered and has appropriate margins on different device sizes, utilizing `calc()` for dynamic padding calculations. ```css @utility container { padding-left: 16px; padding-right: 16px; @media (width >= theme(--breakpoint-sm)) { padding-left: calc((100vw + 16px - 640px) / 2); padding-right: calc((100vw + 16px - 640px) / 2); } @media (width >= theme(--breakpoint-md)) { padding-left: calc((100vw + 16px - 768px) / 2); padding-right: calc((100vw + 16px - 768px) / 2); } @media (width >= theme(--breakpoint-lg)) { padding-left: calc((100vw + 16px - 1024px) / 2); padding-right: calc((100vw + 16px - 1024px) / 2); } @media (width >= theme(--breakpoint-xl)) { padding-left: calc((100vw + 16px - 1280px) / 2); padding-right: calc((100vw + 16px - 1280px) / 2); } @media (width >= theme(--breakpoint-2xl)) { padding-left: calc((100vw + 16px - 1536px) / 2); padding-right: calc((100vw + 16px - 1536px) / 2); } } ``` -------------------------------- ### Load Google Fonts in HTML Head Source: https://docs.subframe.com/fonts This HTML snippet demonstrates how to include Google Fonts (specifically 'Inter' with various weights) in your web project. It uses `preconnect` for performance optimization and a `link` tag to import the font stylesheet. This snippet should be placed within the `` section of your `index.html` file to ensure fonts load correctly in your development environment. ```HTML ``` -------------------------------- ### Implement Interactive TrackCard Component in React Source: https://docs.subframe.com/adding-business-logic This React component wraps a Subframe-generated `TrackCard` to add interactive functionality like favoriting. It manages the display of track details, converts track length to a readable format (MM:SS), and handles favorite button clicks. It utilizes `useMemo` for performance optimization and integrates with a `SubframeTrackCard` component. ```typescript import { HTMLAttributes, useMemo } from "react" import { TrackCard as SubframeTrackCard } from "@/ui" import { Image } from "./Image" export interface TrackCardProps extends HTMLAttributes { title: string artist: string length: number // in seconds genre: string coverImage: string isFavorite: boolean onFavoriteClick: () => void } function lengthToString(length: number): string { const minutes = Math.floor(length / 60) const seconds = length % 60 return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}` } const TrackCard = ({ title, artist, length, genre, coverImage, isFavorite, onFavoriteClick }: TrackCardProps) => { // Convert track length in seconds to MM:SS format const formattedLength = useMemo(() => lengthToString(length), [length]) // Determine the icon based on favorite status const icon = useMemo(() => (isFavorite ? "FeatherHeartOff" : "FeatherHeart"), [isFavorite]) return ( } imageSlot={} genre={genre} /> ) } export default TrackCard ``` -------------------------------- ### Import Tailwind CSS and Subframe Theme Source: https://docs.subframe.com/theme CSS import statements typically placed in a global stylesheet (e.g., `index.css`, `styles.css`, or `globals.css`). These imports bring in the core Tailwind CSS utilities and the custom `theme.css` file generated by Subframe, making the design tokens available throughout the application. ```css @import "tailwindcss"; @import "../ui/theme.css"; ``` -------------------------------- ### Tailwind CSS Configuration for Subframe Theme Source: https://docs.subframe.com/theme This JavaScript code snippet represents the `tailwind.config.js` file generated by Subframe. It extends Tailwind's default theme to include custom color palettes (brand, neutral, error, warning, success), specific font sizes (caption, body, heading), font families (Figtree, monospace), and box shadows. This configuration defines the visual tokens for the Subframe theme. ```JavaScript module.exports = { // ... theme: { extend: { colors: { brand: { 50: "rgb(250, 250, 250)", 100: "rgb(245, 245, 245)", 200: "rgb(229, 229, 229)", 300: "rgb(212, 212, 212)", 400: "rgb(163, 163, 163)", 500: "rgb(115, 115, 115)", 600: "rgb(38, 38, 38)", 700: "rgb(64, 64, 64)", 800: "rgb(38, 38, 38)", 900: "rgb(23, 23, 23)" }, neutral: { 0: "rgb(255, 255, 255)", 50: "rgb(250, 250, 250)", 100: "rgb(245, 245, 245)", 200: "rgb(229, 229, 229)", 300: "rgb(212, 212, 212)", 400: "rgb(163, 163, 163)", 500: "rgb(115, 115, 115)", 600: "rgb(82, 82, 82)", 700: "rgb(64, 64, 64)", 800: "rgb(38, 38, 38)", 900: "rgb(23, 23, 23)", 950: "rgb(10, 10, 10)" }, error: { 50: "rgb(254, 242, 242)", 100: "rgb(254, 226, 226)", 200: "rgb(254, 202, 202)", 300: "rgb(252, 165, 165)", 400: "rgb(248, 113, 113)", 500: "rgb(239, 68, 68)", 600: "rgb(220, 38, 38)", 700: "rgb(185, 28, 28)", 800: "rgb(153, 27, 27)", 900: "rgb(127, 29, 29)" }, warning: { 50: "rgb(240, 249, 255)", 100: "rgb(224, 242, 254)", 200: "rgb(186, 230, 253)", 300: "rgb(125, 211, 252)", 400: "rgb(56, 189, 248)", 500: "rgb(14, 165, 233)", 600: "rgb(2, 132, 199)", 700: "rgb(3, 105, 161)", 800: "rgb(7, 89, 133)", 900: "rgb(12, 74, 110)" }, success: { 50: "rgb(240, 253, 244)", 100: "rgb(220, 252, 231)", 200: "rgb(187, 247, 208)", 300: "rgb(134, 239, 172)", 400: "rgb(74, 222, 128)", 500: "rgb(34, 197, 94)", 600: "rgb(22, 163, 74)", 700: "rgb(21, 128, 61)", 800: "rgb(22, 101, 52)", 900: "rgb(20, 83, 45)" }, "brand-primary": "rgb(38, 38, 38)", "default-font": "rgb(23, 23, 23)", "subtext-color": "rgb(115, 115, 115)", "neutral-border": "rgb(229, 229, 229)", white: "rgb(255, 255, 255)", "default-background": "rgb(255, 255, 255)" }, fontSize: { caption: [ "12px", { lineHeight: "16px", fontWeight: "400", letterSpacing: "0em" } ], "caption-bold": [ "12px", { lineHeight: "16px", fontWeight: "500", letterSpacing: "0em" } ], body: [ "14px", { lineHeight: "20px", fontWeight: "400", letterSpacing: "0em" } ], "body-bold": [ "14px", { lineHeight: "20px", fontWeight: "500", letterSpacing: "0em" } ], "heading-3": [ "16px", { lineHeight: "20px", fontWeight: "600", letterSpacing: "0em" } ], "heading-2": [ "20px", { lineHeight: "24px", fontWeight: "600", letterSpacing: "0em" } ], "heading-1": [ "30px", { lineHeight: "36px", fontWeight: "600", letterSpacing: "0em" } ], "monospace-body": [ "14px", { lineHeight: "20px", fontWeight: "400", letterSpacing: "0em" } ] }, fontFamily: { caption: "Figtree", "caption-bold": "Figtree", body: "Figtree", "body-bold": "Figtree", "heading-3": "Figtree", "heading-2": "Figtree", "heading-1": "Figtree", "monospace-body": "monospace" }, boxShadow: { sm: "0px 1px 2px 0px rgba(0, 0, 0, 0.05)", default: "0px 1px 2px 0px rgba(0, 0, 0, 0.05)", md: "0px 4px 16px -2px rgba(0, 0, 0, 0.08), 0px 2px 4px -1px rgba(0, 0, 0, 0.08)", lg: "0px 12px 32px -4px rgba(0, 0, 0, 0.08), 0px 4px 8px -2px rgba(0, 0, 0, 0.08)", overlay: "" } } } } ```