diff --git a/.cursor/rules/figma-rules.mdc b/.cursor/rules/figma-rules.mdc new file mode 100644 index 0000000000..b03a83680e --- /dev/null +++ b/.cursor/rules/figma-rules.mdc @@ -0,0 +1,26 @@ +--- +description: +globs: +alwaysApply: true +--- + +--- +description: Figma Dev Mode MCP rules +globs: +alwaysApply: true +--- + - The Figma Dev Mode MCP Server provides an assets endpoint which can serve image and SVG assets + - IMPORTANT: If the Figma Dev Mode MCP Server returns a localhost source for an image or an SVG, use that image or SVG source directly + - IMPORTANT: DO NOT import/add new icon packages, all the assets should be in the Figma payload + - IMPORTANT: do NOT use or create placeholders if a localhost source is provided + - IMPORTANT: Always use components from `/packages` whenever possible + - Prioritize using semantic tokens and component props over Figma fidelity + - Avoid hardcoded values, use semantic design tokens whenever possible. The Background component is the exception - use color token names (i.e, navy, white, etc) and not a semantic token + - IMPORTANT: Do not use inline styles, whenever possible use emotion and the css-in-js utilities from `/packages/gamut-styles`. Follow the rules from `packages/styleguide/src/lib/Foundations/System` + - IMPORTANT: Follow WCAG requirements for accessibility + - Always follow best practices from `/packages/styleguide/src/lib/Meta/Best Practices.mdx` + - IMPORTANT: All patterns should come from `/packages/gamut-patterns` - match the Figma component name to the pattern component + - IMPORTANT: All icons should come from `/packages/gamut-icons` - match the Figma component name to the icon component + - Check if the Figma component name matches a Gamut component name and use that component + - Use the tokens from `packages/gamut-styles/src/variables` + - Use the CodeConnect implementation \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 13c37b8648..dddd024c3c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,5 +41,15 @@ }, "storyExplorer.storiesGlobs": "packages/styleguide/stories/**/*.stories.mdx", "jest.jestCommandLine": "node_modules/.bin/jest", - "nxConsole.generateAiAgentRules": true + "nxConsole.generateAiAgentRules": true, + "chat.mcp.discovery.enabled": true + // "mcp": { + // "servers": { + // "Figma Dev Mode MCP": { + // "type": "sse", + // "url": "http://127.0.0.1:3845/sse" + // } + // } + // }, + // "chat.agent.enabled": true } diff --git a/FIGMA_SETUP.md b/FIGMA_SETUP.md new file mode 100644 index 0000000000..84d9986775 --- /dev/null +++ b/FIGMA_SETUP.md @@ -0,0 +1,92 @@ +# Figma Dev Mode MCP Server Setup + +This repository is configured to use the Figma Dev Mode MCP server locally. This allows you to extract designs, code, and assets directly from Figma within Cursor. + +## Setup Instructions + +### 1. Install Dependencies + +```bash +yarn install +``` + +This will install the `@figma/mcp-server` package that's configured in the `devDependencies`. + +### 2. Get Your Figma Access Token + +1. Go to [Figma Settings > Personal Access Tokens](https://www.figma.com/developers/api#access-tokens) +2. Click "Create new personal access token" +3. Give it a descriptive name (e.g., "Gamut Repository MCP") +4. Copy the generated token + +### 3. Configure the Token + +You have two options to provide your Figma access token: + +#### Option A: Environment Variable (Recommended) + +Set the environment variable in your shell: + +```bash +export FIGMA_ACCESS_TOKEN="your_figma_access_token_here" +``` + +Or add it to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.): + +```bash +echo 'export FIGMA_ACCESS_TOKEN="your_figma_access_token_here"' >> ~/.zshrc +source ~/.zshrc +``` + +#### Option B: Update MCP Configuration + +Edit `.cursor/mcp.json` and replace the empty token: + +```json +{ + "mcpServers": { + "figma": { + "command": "npx", + "args": ["@figma/mcp-server"], + "env": { + "FIGMA_ACCESS_TOKEN": "your_figma_access_token_here" + } + } + } +} +``` + +### 4. Restart Cursor + +After configuring the token, restart Cursor to load the MCP server. + +## Usage + +Once configured, you can: + +1. **Extract designs from Figma**: Select elements in Figma and use the MCP tools to get code +2. **Get design specifications**: Extract colors, spacing, typography from Figma designs +3. **Generate components**: Create React components based on Figma designs + +The MCP server will be available in Cursor's chat interface when working in this repository. + +## Troubleshooting + +### MCP Server Not Loading + +- Ensure your Figma access token is valid +- Check that the token has the necessary permissions +- Restart Cursor after making configuration changes + +### Token Issues + +- Verify the token is correctly set in the environment or configuration +- Make sure there are no extra spaces or quotes in the token +- Generate a new token if the current one isn't working + +## Configuration Files + +- `.cursor/mcp.json` - Local MCP server configuration for this repository +- `package.json` - Contains the `@figma/mcp-server` dependency + +This setup is local to this repository and won't affect your global Cursor configuration. diff --git a/packages/styleguide/src/lib/Meta/Claude3Sonnet.mdx b/packages/styleguide/src/lib/Meta/Claude3Sonnet.mdx new file mode 100644 index 0000000000..6b2b62caa4 --- /dev/null +++ b/packages/styleguide/src/lib/Meta/Claude3Sonnet.mdx @@ -0,0 +1,74 @@ +import { Canvas, Meta } from '@storybook/blocks'; + +import { ComponentHeader } from '~styleguide/blocks'; + +import * as Claude3SonnetStories from './Claude3Sonnet.stories'; + +export const parameters = { + subtitle: + 'Example showing how to use Figma Dev Mode with MCP to generate production-ready code.', + design: { + type: 'figma', + url: 'https://www.figma.com/file/XXX', // Replace with actual Figma file URL + }, + status: 'current', + source: { + repo: 'gamut', + githubLink: + 'https://github.com/Codecademy/gamut/blob/main/packages/styleguide/src/lib/Meta/Claude3Sonnet.stories.tsx', + }, +}; + + + + + +## Overview + +This example demonstrates how to use Figma Dev Mode with MCP to automatically generate production-ready code from Figma designs. It showcases: + +- Direct mapping between design components and code implementation +- Use of semantic tokens and design system props +- Integration with Gamut components +- Proper accessibility and styling practices + +## Example Implementation + +The example shows a landing page layout with three main sections: + +1. Hero section with a badge, heading, and description +2. "How it works" section explaining the workflow +3. Component showcase demonstrating various Gamut components + + + +## Best Practices + +1. **Use Real Components** + + - Always use components from `/packages` whenever possible + - Match Figma component names to Gamut component names + +2. **Follow Design System** + + - Use semantic tokens and component props over hardcoded values + - Avoid inline styles, use emotion and css-in-js utilities + - Maintain consistent spacing and typography + +3. **Ensure Accessibility** + + - Follow WCAG requirements + - Provide proper labels and ARIA attributes + - Maintain sufficient color contrast + +4. **Leverage MCP Features** + - Use the assets endpoint for images and SVGs + - Reference design tokens from Figma + - Take advantage of automatic code generation + +## Benefits + +- **Efficiency**: No manual translation needed between design and code +- **Consistency**: Direct mapping ensures design system compliance +- **Quality**: Production-ready code with proper accessibility +- **Maintainability**: Changes in design system automatically reflected diff --git a/packages/styleguide/src/lib/Meta/Claude3Sonnet.stories.tsx b/packages/styleguide/src/lib/Meta/Claude3Sonnet.stories.tsx new file mode 100644 index 0000000000..dcda24a2b9 --- /dev/null +++ b/packages/styleguide/src/lib/Meta/Claude3Sonnet.stories.tsx @@ -0,0 +1,192 @@ +import { + Badge, + Box, + Checkbox, + FillButton, + GridBox, + IconButton, + Input, + Menu, + MenuItem, + Radio, + Text, +} from '@codecademy/gamut'; +import { SearchIcon } from '@codecademy/gamut-icons'; +import { Background } from '@codecademy/gamut-styles'; +import styled from '@emotion/styled'; +import type { Meta, StoryObj } from '@storybook/react'; + +const Pattern = styled.div<{ pattern: string }>` + position: absolute; + inset: 0; + background-color: ${({ theme }) => theme.colors.navy[800]}; + mask-image: url(${({ pattern }) => pattern}); + mask-repeat: repeat; + mask-size: 64px; +`; + +const HeroSection = styled.section` + padding: 96px 32px; + position: relative; + overflow: hidden; +`; + +const ComponentGrid = styled(GridBox)` + gap: 4rem; + padding: 3rem; + border: 1px solid rgba(16, 22, 47, 0.06); +`; + +const Claude3Sonnet = () => { + return ( + + + + + + New + + From canvas to code—automagically. + + + You can now inspect a Figma file and get back real, usable code + thanks to MCP. + + + + + + + + How it works + + + + + + 1. Design with real components + + + Use components from your design system directly in Figma. Each + one is mapped to a real implementation in code—no need to fake + it. + + + + {/* Placeholder for screenshot */} + + + + + + + + {/* Placeholder for screenshot */} + + + + 2. Inspect in Dev Mode + + + With the MCP server running, Figma Dev Mode shows the actual + component name, available props, and design tokens used (like + spacing, color, and typography). + + + + + + + + + + 3. Copy usable code + + + Developers get production-ready code they can copy straight + from the design—no guessing, no redlining, no translation. + + + + {/* Placeholder for screenshot */} + + + + + + + + + Inspectable components + + + Each of these elements below are real Gamut components. Open Dev + Mode to view props, tokens, and usable code. + + + + Button text + + + Menu item + Menu item + Menu item + + + + + + + + + + + + + + + + + + ); +}; + +const meta: Meta = { + title: 'Meta/Claude3Sonnet', + component: Claude3Sonnet, +}; + +export default meta; +type Story = StoryObj; + +export const Example: Story = {}; diff --git a/packages/styleguide/src/lib/Meta/Claude3WithCodeConnect.stories.tsx b/packages/styleguide/src/lib/Meta/Claude3WithCodeConnect.stories.tsx new file mode 100644 index 0000000000..092cfbfd3c --- /dev/null +++ b/packages/styleguide/src/lib/Meta/Claude3WithCodeConnect.stories.tsx @@ -0,0 +1,154 @@ +import { + Badge, + Box, + Checkbox, + FillButton, + FlexBox, + IconButton, + Input, + Menu, + MenuItem, + Radio, + Text, +} from '@codecademy/gamut'; +import { SearchIcon } from '@codecademy/gamut-icons'; +import { Background } from '@codecademy/gamut-styles'; +import styled from '@emotion/styled'; +import type { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'Meta/Claude3WithCodeConnect', + parameters: { + layout: 'fullscreen', + }, +}; + +export default meta; +type Story = StoryObj; + +const StyledSection = styled.section` + padding: 6rem; + width: 100%; +`; + +const ComponentsGrid = styled.div` + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + padding: 3rem; + border: 1px solid var(--color-navy-800); +`; + +export const MainExample: Story = { + render: () => ( + + + {/* Hero Section */} + + + New + + From canvas to code—automagically. + + + You can now inspect a Figma file and get back real, usable code + thanks to MCP. + + + + + {/* How it Works Section */} + + + + How it works + + + + + + 1. Design with real components + + + Use components from your design system directly in Figma. Each + one is mapped to a real implementation in code—no need to fake + it. + + + + + + 2. Inspect in Dev Mode + + + With the MCP server running, Figma Dev Mode shows the actual + component name, available props, and design tokens used (like + spacing, color, and typography). + + + + + + 3. Copy usable code + + + Developers get production-ready code they can copy straight + from the design—no guessing, no redlining, no translation. + + + + + + + {/* Inspectable Components Section */} + + + + Inspectable components + + + Each of these elements below are real Gamut components. Open Dev + Mode to view props, tokens, and usable code. + + + + Button text + + + Menu Item + Menu Item + Menu Item + + + + + + + + + + + + + + + + + + ), +}; diff --git a/packages/styleguide/src/lib/Meta/o3WithCodeConnectNoBackground.stories.tsx b/packages/styleguide/src/lib/Meta/o3WithCodeConnectNoBackground.stories.tsx new file mode 100644 index 0000000000..3157aa1ba4 --- /dev/null +++ b/packages/styleguide/src/lib/Meta/o3WithCodeConnectNoBackground.stories.tsx @@ -0,0 +1,204 @@ +import { + Badge, + Box, + Checkbox, + FillButton, + GridBox, + IconButton, + Input, + Menu, + MenuItem, + Radio, + Text, +} from '@codecademy/gamut'; +import { SearchIcon } from '@codecademy/gamut-icons'; +import { DiagonalADense, DiagonalALoose } from '@codecademy/gamut-patterns'; +import styled from '@emotion/styled'; +import type { Meta, StoryObj } from '@storybook/react'; + +// Generic wrapper used to absolutely-position SVG patterns +const PatternOverlay = styled(Box)` + position: absolute; + inset: 0; + pointer-events: none; /* Ensure overlay doesn't affect layout / clicks */ + z-index: 0; /* Sit behind content */ +`; + +// Section wrappers +const HeroSection = styled.section` + padding: 96px 32px; + position: relative; + overflow: hidden; +`; + +const ComponentGrid = styled(GridBox)` + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1.5rem; /* 24px for tighter spacing */ + padding: 3rem; /* matches Figma 48px (3rem) padding */ + border: 1px solid rgba(16, 22, 47, 0.06); + align-items: flex-start; /* keep rows aligned to top */ +`; + +const O3WithCodeConnectNoBackground = () => { + return ( + + {/* Hero */} + + + + + + + New + + From canvas to code—automagically. + + + You can now inspect a Figma file and get back real, usable code + thanks to MCP. + + + + + + {/* How it Works */} + + + + How it works + + + + + + 1. Design with real components + + + Use components from your design system directly in Figma. Each + one is mapped to a real implementation in code—no need to fake + it. + + + + {/* screenshot placeholder */} + + + + + + + + + + {/* screenshot placeholder */} + + + + 2. Inspect in Dev Mode + + + With the MCP server running, Figma Dev Mode shows the actual + component name, available props, and design tokens used (like + spacing, color, and typography). + + + + + + + + + + + + 3. Copy usable code + + + Developers get production-ready code they can copy straight from + the design—no guessing, no redlining, no translation. + + + + {/* screenshot placeholder */} + + + + + + {/* Inspectable Components */} + + + + Inspectable components + + + Each of these elements below are real Gamut components. Open Dev + Mode to view props, tokens, and usable code. + + + + Button text + + + Menu item + Menu item + Menu item + + + + + + + + + + + + + + + + + ); +}; + +const meta: Meta = { + title: 'Meta/o3WithCodeConnectNoBackground', + component: O3WithCodeConnectNoBackground, +}; + +export default meta; + +type Story = StoryObj; + +export const Example: Story = {}; diff --git a/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.mdx b/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.mdx index 3a1d963083..c3067243ae 100644 --- a/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.mdx +++ b/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.mdx @@ -32,7 +32,7 @@ Use a Modal to create a dialog on sits on top of a full screen overlay. Setting the `size` to `'fluid'` will make the width of the Modal fit its content. - + ### Large diff --git a/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.stories.tsx b/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.stories.tsx index 2176b405f9..f41f8c4c00 100644 --- a/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.stories.tsx +++ b/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.stories.tsx @@ -1,6 +1,7 @@ import { Box, Checkbox, + Dialog, FillButton, FlexBox, Modal, @@ -345,3 +346,52 @@ export const MultipleViewsDisabled: React.FC = () => { ); }; + +const ImagePlaceholder = () => { + return ( + + + Replace with any image + + 16:9 + + ); +}; + +export const ARobotMadeThis: React.FC = () => { + const [isOpen, setIsOpen] = useState(false); + + return ( + <> + setIsOpen(true)}>Open Figma Dialog + setIsOpen(false), + }} + confirmCta={{ + children: 'Primary action', + onClick: () => setIsOpen(false), + }} + image={} + isOpen={isOpen} + size="small" + title="Headline" + onRequestClose={() => setIsOpen(false)} + > + + Optional 1-2 lines of explanation that provides relevant details. + Lorem ipsum cras nulla massa odio ligula. + + + + ); +};