Thank you for your interest in contributing to VarVar! This document provides guidelines and information for contributors.
- Node.js (v18 or higher)
- npm
- Git
-
Clone the repository:
git clone https://github.com/atropical/varvar.git cd varvar -
Install dependencies:
npm install
-
Start the development server:
npm run dev
This will start the TypeScript compiler in watch mode, build the plugin, and serve the UI with hot reloading.
- Use strict TypeScript with proper type annotations
- Prefer interfaces over types for object shapes
- Use enums for constants and command types
- Add JSDoc comments for all public functions and interfaces
- Use meaningful variable and function names
- Use functional components with hooks
- Follow the component structure:
interface ComponentProps { // Props interface } /** * JSDoc comment describing the component */ export const Component: React.FC<ComponentProps> = ({ prop1, prop2 }) => { // Component logic return ( // JSX ); };
- Place reusable UI components in
src/components/ - Place format-specific views in
src/views/ - Place utility functions in
src/utils/ - Use descriptive file names that match their purpose
- Files: Use PascalCase for React components, camelCase for utilities
- Components: PascalCase (e.g.,
ExportHeader) - Functions: camelCase (e.g.,
handleExport) - Constants: UPPER_SNAKE_CASE (e.g.,
DEFAULT_FILENAME) - Types/Interfaces: PascalCase (e.g.,
PluginMessage)
All UI components should be:
- Reusable: Can be used across different views
- Typed: Have proper TypeScript interfaces for props
- Documented: Include JSDoc comments
- Focused: Have a single responsibility
- PluginDialogShell: Provides consistent layout, padding, and common elements (like Footer) for all views
- ExportHeader: Format-specific titles and descriptions
- Footer: Plugin information and links (automatically included in shell)
Example structure:
import React from "react";
import { ComponentProps } from "figma-kit";
interface MyComponentProps {
title: string;
onAction: () => void;
optional?: boolean;
}
/**
* Brief description of what this component does
* @param props - Component properties
*/
export const MyComponent: React.FC<MyComponentProps> = ({
title,
onAction,
optional = false
}) => {
return (
// Component JSX
);
};Format-specific views should:
- Use shared components from
src/components/ - Handle format-specific logic
- Provide appropriate defaults
- Include proper error handling
-
Test your changes: Ensure the plugin builds and works correctly
npm run test # Runs TypeScript check and build (no unit tests)
-
Follow code style: Use the established patterns and conventions
-
Add documentation: Update JSDoc comments and README if needed
-
Test in Figma: Verify your changes work in the actual Figma environment
- Clear title: Use a descriptive title that explains what the PR does
- Detailed description: Explain the changes and why they were made
- Link issues: Reference any related issues
- Screenshots: Include screenshots for UI changes
- Testing notes: Describe how you tested the changes
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Tested in Figma
- [ ] All exports work correctly
- [ ] No TypeScript errors
- [ ] UI renders properly
## Screenshots (if applicable)
Add screenshots here
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No console errorsBefore submitting a PR, test the following:
- All export formats: JSON, CSV, CSS, JavaScript, Tailwind CSS
- Menu commands: Each format-specific menu item
- Linked variables: Ensure proper handling across formats
- Error handling: Test with edge cases and invalid data
- UI responsiveness: Check different screen sizes
- File downloads: Verify files are downloaded correctly
- TypeScript compilation must pass without errors
- Build process must complete successfully
- No linting errors
- All function parameters and return types must be explicitly typed
- Use proper enum types instead of string literals
- Avoid
anytype - use proper interfaces or union types - Use type guards for runtime type checking
All plugin messages must use the PluginMessage interface:
// Good
figma.ui.postMessage({
type: MessageTypes.EXPORT_SUCCESS,
format: OutputFormats.JSON,
data: "exported data"
} as PluginMessage);
// Bad
figma.ui.postMessage({
type: "EXPORT.SUCCESS", // String literal
format: "json", // String literal
data: "exported data"
});To add a new export format:
- Add to enums: Update
OutputFormatsandPluginCommandsintypes.d.ts - Create utility: Add export function in
src/utils/ - Create view: Add format-specific view in
src/views/ - Update router: Add case to the switch statement in
ui.tsx - Update manifest: Add menu item in
figma.manifest.ts - Update documentation: Add to README and this file
Note: Tailwind CSS export is currently available as a CSS format option (toggle in ExportOptions) but not as a separate menu command.
When reporting issues:
- Use the issue template: Provide all requested information
- Include steps to reproduce: Clear, numbered steps
- Add screenshots: Visual context is helpful
- Specify environment: Figma version, OS, browser
- Check existing issues: Avoid duplicates
- Be respectful and inclusive
- Provide constructive feedback
- Help others learn and grow
- Follow the project's coding standards
If you have questions about contributing:
- Check existing issues and discussions
- Review the codebase and documentation
- Open a new issue with the "question" label
- Join our community discussions
Thank you for contributing to VarVar! 🎉