templates
A template engine that comes with tools for building presentational components in realtime
Sep 18, 2021

paperclip
Build UIs at the speed of thought. Paperclip is a template engine that comes with tools for building presentational components in realtime, all within your existing IDE:
This took me about 12 minutes to make start to finish.
Features
- Templates compile down to plain React code (more targets planned).
- Scoped CSS. Write styles however you want, without worying about them leaking out.
- Percy integration for catching visual regressions.
- Compatible with existing CSS libraries like Tailwind, Bulma, and Bootstrap.
Resources
- Slack channel - for questions, feedback, help, or whatever!
- Installation
- Project installation - Basic installation of Paperclip for new and existing projects.
- VSCode Extension - Getting started with the VS Code extension.
- Webpack setup - Setting up with Webpack
- Documentation
- Syntax - How to write Paperclip documents
- React usage - Using Paperclip UIs in your React code
Example
Here's what Paperclip's syntax looks like (from GIF above):
<!-- @frame is like a doc-comment & attaches metadata about your elements for the designer & other visual tooling. --> <!-- @frame { visible: false } --> <h4 export component as="FormTitle"> <!-- Styles defined within elements are scoped, and don't need selectors --> <style> margin: 0px; </style> {children} </h4> <!-- @frame { visible: false } --> <!-- Note this would typically be defined in a separate file & imported into this doc --> <input export component as="TextInput" {placeholder?} {type}> <style> border: 1px solid rgb(156, 156, 156); padding: 8px 16px; border-radius: 2px; </style> </input> <!-- @frame { visible: false } --> <div export component as="FormFooter"> <style> display: flex; justify-content: flex-end; </style> {children} </div> <!-- @frame { visible: false } --> <!-- This typically wouldn't be defined here --> <button export component as="Button"> <style> --button-bg-color: rgb(116, 176, 255); background: var(--button-bg-color); color: rgb(46, 85, 136); padding: 8px 16px; border-radius: 2px; border: 2px solid var(--button-bg-color); </style> {children} </button> <!-- @frame { visible: false } --> <div export component as="AuthModal"> <style> display: grid; grid-row-gap: 16px; max-width: 250px; margin: 0px auto; /* rule of thirds */ top: 30%; padding: 32px; border-radius: 4px; color: rgb(97, 97, 97); background: rgb(238, 238, 238); position: relative; border: 1px solid rgb(194, 194, 194); </style> {children} </div> <!-- @frame { visible: false, title: "Auth / login", width: 586, height: 446, x: 3, y: 141 } --> <div export component as="Preview"> <style> font-family: sans-serif; height: 100vh; </style> {showLogin && <AuthModal> <FormTitle>Log in</FormTitle> <TextInput placeholder="Username" /> <TextInput placeholder="Password" /> <FormFooter> <Button>Sign up</Button> </FormFooter> </AuthModal>} {showSignup && <AuthModal> <FormTitle>Sign up</FormTitle> <TextInput placeholder="Full Name" /> <TextInput placeholder="Username" /> <TextInput placeholder="Password" /> <TextInput placeholder="Repeat Password" /> <FormFooter> <Button>Sign up</Button> </FormFooter> </AuthModal>} </div> <!-- @frame { title: "Auth / Login", width: 501, height: 427, x: 0, y: 0 } --> <Preview showLogin /> <!-- @frame { title: "Auth / Sign Up", width: 501, height: 561, x: 581, y: 1 } --> <Preview showSignup />
Here's how you integrate Paperclip into your code:
import React from "react"; import * as styles from "./auth.pc"; import { TextInput } from "@design-system/components/TextInput"; import { Button } from "@design-system/components/Button"; export const LoginPage = () => { const { onSubmit, usernameInputProps, passwordInputProps } = useLogin(); const userNameProps = useTextInput(); return <form onSubmit={onSubmit}> <styles.Modal> <styles.AuthModal> <styles.FormTitle>Welcome back!</styles.FormTitle> <TextInput type="text" {...usernameInputProps} /> <TextInput type="password" {...passwordInputProps} /> <styles.FormFooter> <Button>Log in</Button> </styles.FormFooter> </styles.AuthModal> </styles.Modal> </form>; };
Roadmap
What's the future looking like for Paperclip? Here's the tentative plan:
- ✅ Prettier integration
- ✅ Avocode / Figma integration (Figma to design sync)
- 🔲 CSS & HTML linting (a11y, showing unused styles, caniuse integration)
- 🔲 CSS tree shaking (removing unused CSS from builds)
- 🔲 Visual builder (no-code like)
- 🔲 Multiple compiler targets: PHP, Ruby, VueJS, Svelte
- 🔲 IDE integrations