426 lines
8.3 KiB
Markdown
426 lines
8.3 KiB
Markdown
# Pencil File Format Reference
|
|
|
|
Complete technical reference for `.pen` file structure, element types, and properties.
|
|
|
|
## JSON Structure
|
|
|
|
### Root Object
|
|
|
|
```json
|
|
{
|
|
"version": "2.6",
|
|
"children": [ /* Page frames and components */ ],
|
|
"variables": { /* Design tokens */ }
|
|
}
|
|
```
|
|
|
|
## Element Types
|
|
|
|
### Frame
|
|
|
|
Container for layouts and grouping.
|
|
|
|
```json
|
|
{
|
|
"type": "frame",
|
|
"id": "unique_id",
|
|
"name": "Frame Name",
|
|
"width": 400,
|
|
"height": 300,
|
|
"fill": "#FFFFFF",
|
|
"layout": "vertical",
|
|
"gap": 16,
|
|
"padding": [16, 24],
|
|
"justifyContent": "center",
|
|
"alignItems": "center",
|
|
"children": [],
|
|
"reusable": true
|
|
}
|
|
```
|
|
|
|
| Property | Type | Values | Description |
|
|
|----------|------|--------|-------------|
|
|
| `layout` | string | `vertical`, `horizontal`, `none` | Flexbox direction |
|
|
| `gap` | number | pixels | Spacing between children |
|
|
| `padding` | number/array | `16` or `[vertical, horizontal]` | Internal padding |
|
|
| `justifyContent` | string | `start`, `center`, `end`, `space_between` | Main axis alignment |
|
|
| `alignItems` | string | `start`, `center`, `end` | Cross axis alignment |
|
|
| `reusable` | boolean | `true`/`false` | Can be referenced by other elements |
|
|
|
|
### Text
|
|
|
|
Text element with typography properties.
|
|
|
|
```json
|
|
{
|
|
"type": "text",
|
|
"id": "text_id",
|
|
"name": "Label",
|
|
"content": "Hello World",
|
|
"fontSize": 16,
|
|
"fontFamily": "Roboto",
|
|
"fontWeight": "500",
|
|
"fill": "$text-primary",
|
|
"textAlign": "left"
|
|
}
|
|
```
|
|
|
|
| Property | Type | Values | Description |
|
|
|----------|------|--------|-------------|
|
|
| `content` | string | Any text | Text content |
|
|
| `fontSize` | number | pixels | Font size |
|
|
| `fontFamily` | string | Font name | e.g., "Roboto", "Inter" |
|
|
| `fontWeight` | string | `"400"`, `"500"`, `"600"`, `"700"` | Font weight |
|
|
| `fill` | string | Color/variable | Text color |
|
|
| `textAlign` | string | `left`, `center`, `right` | Text alignment |
|
|
|
|
### Rectangle
|
|
|
|
Rectangular shape.
|
|
|
|
```json
|
|
{
|
|
"type": "rectangle",
|
|
"id": "rect_id",
|
|
"name": "Box",
|
|
"width": 200,
|
|
"height": 100,
|
|
"fill": "$bg-surface",
|
|
"cornerRadius": 10
|
|
}
|
|
```
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `cornerRadius` | number | Border radius in pixels |
|
|
| `fill` | string/object | Solid color, variable, or gradient |
|
|
|
|
### Ellipse
|
|
|
|
Circle or ellipse shape.
|
|
|
|
```json
|
|
{
|
|
"type": "ellipse",
|
|
"id": "ellipse_id",
|
|
"name": "Circle",
|
|
"width": 48,
|
|
"height": 48,
|
|
"fill": "$orange-primary"
|
|
}
|
|
```
|
|
|
|
### Icon Font
|
|
|
|
Icon from Lucide icon set.
|
|
|
|
```json
|
|
{
|
|
"type": "icon_font",
|
|
"id": "icon_id",
|
|
"name": "Search Icon",
|
|
"iconFontName": "search",
|
|
"iconFontFamily": "Lucide",
|
|
"fill": "$text-secondary",
|
|
"fontSize": 20
|
|
}
|
|
```
|
|
|
|
| Property | Description |
|
|
|----------|-------------|
|
|
| `iconFontName` | Lucide icon name (e.g., "search", "user", "menu") |
|
|
| `iconFontFamily` | Always "Lucide" |
|
|
|
|
### Ref (Component Instance)
|
|
|
|
Reference to a reusable component in the same file.
|
|
|
|
```json
|
|
{
|
|
"type": "ref",
|
|
"ref": "component_id",
|
|
"name": "myButton",
|
|
"descendants": {
|
|
"child_element_id": {
|
|
"content": "Click Me"
|
|
}
|
|
},
|
|
"x": 100,
|
|
"y": 200
|
|
}
|
|
```
|
|
|
|
| Property | Description |
|
|
|----------|-------------|
|
|
| `ref` | ID of the component being referenced |
|
|
| `descendants` | Property overrides for child elements |
|
|
|
|
**Descendants structure:**
|
|
```json
|
|
"descendants": {
|
|
"element_id_to_override": {
|
|
"property_name": "new_value"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Component Ref (External Reference)
|
|
|
|
Custom type for build system - references components from external files.
|
|
|
|
```json
|
|
{
|
|
"type": "component_ref",
|
|
"component": "ui-kit#Button/Primary",
|
|
"name": "myButton",
|
|
"overrides": {
|
|
"label_id": {
|
|
"content": "Click Me"
|
|
}
|
|
},
|
|
"x": 100,
|
|
"y": 200
|
|
}
|
|
```
|
|
|
|
> [!NOTE]
|
|
> `component_ref` is processed by the build system and converted to standard `ref` type during build.
|
|
|
|
## Size Properties
|
|
|
|
### Fixed Size
|
|
|
|
```json
|
|
{
|
|
"width": 400,
|
|
"height": 200
|
|
}
|
|
```
|
|
|
|
### Fill Container
|
|
|
|
```json
|
|
{
|
|
"width": "fill_container", // 100% of parent width
|
|
"height": 200
|
|
}
|
|
```
|
|
|
|
## Fill Properties
|
|
|
|
### Solid Color
|
|
|
|
```json
|
|
{
|
|
"fill": "#FF5C00"
|
|
}
|
|
```
|
|
|
|
### Design Token Variable
|
|
|
|
```json
|
|
{
|
|
"fill": "$bg-page"
|
|
}
|
|
```
|
|
|
|
### Gradient
|
|
|
|
```json
|
|
{
|
|
"fill": {
|
|
"type": "gradient",
|
|
"colors": [
|
|
{"color": "#FF5C00", "position": 0},
|
|
{"color": "#FF8A4C", "position": 1}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Design Tokens / Variables
|
|
|
|
Variables are defined in the root `variables` object:
|
|
|
|
```json
|
|
"variables": {
|
|
"bg-page": {
|
|
"type": "color",
|
|
"value": "#0A0A0B"
|
|
},
|
|
"text-primary": {
|
|
"type": "color",
|
|
"value": "#FFFFFF"
|
|
},
|
|
"orange-primary": {
|
|
"type": "color",
|
|
"value": "#FF5C00"
|
|
},
|
|
"font-primary": {
|
|
"type": "string",
|
|
"value": "Roboto"
|
|
},
|
|
"space-4": {
|
|
"type": "number",
|
|
"value": 16
|
|
}
|
|
}
|
|
```
|
|
|
|
### Variable Types
|
|
|
|
| Type | Purpose | Example Value |
|
|
|------|---------|---------------|
|
|
| `color` | Colors | `"#FF5C00"` |
|
|
| `string` | Font names, text | `"Roboto"` |
|
|
| `number` | Spacing, sizes | `16` |
|
|
|
|
### Using Variables in Elements
|
|
|
|
Reference variables with `$` prefix:
|
|
|
|
```json
|
|
{
|
|
"fill": "$bg-page",
|
|
"fontSize": "$text-lg",
|
|
"fontFamily": "$font-primary"
|
|
}
|
|
```
|
|
|
|
### Common Token Categories
|
|
|
|
| Category | Prefix | Examples |
|
|
|----------|--------|----------|
|
|
| **Background** | `bg-` | `$bg-page`, `$bg-surface`, `$bg-elevated` |
|
|
| **Text** | `text-` | `$text-primary`, `$text-secondary`, `$text-tertiary` |
|
|
| **Border** | `border-` | `$border-default`, `$border-subtle` |
|
|
| **Brand Colors** | `{color}-` | `$orange-primary`, `$green-success`, `$red-error` |
|
|
| **Typography Sizes** | `text-` | `$text-xs`, `$text-sm`, `$text-base`, `$text-lg` |
|
|
| **Spacing** | `space-` | `$space-2`, `$space-4`, `$space-6` |
|
|
| **Border Radius** | `radius-` | `$radius-sm`, `$radius-md`, `$radius-lg` |
|
|
| **Breakpoints** | `breakpoint-` | `$breakpoint-mobile`, `$breakpoint-tablet` |
|
|
|
|
## Component System
|
|
|
|
### Defining Reusable Components
|
|
|
|
Set `reusable: true` on frames to make them reusable:
|
|
|
|
```json
|
|
{
|
|
"type": "frame",
|
|
"id": "btn_primary_001",
|
|
"name": "Button/Primary",
|
|
"reusable": true,
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"id": "btn_label_001",
|
|
"content": "Button",
|
|
"fontSize": 14
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Using Internal References
|
|
|
|
```json
|
|
{
|
|
"type": "ref",
|
|
"ref": "btn_primary_001",
|
|
"name": "submitButton",
|
|
"descendants": {
|
|
"btn_label_001": {
|
|
"content": "Submit"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Using External References (Build System)
|
|
|
|
In source files, use `component_ref`:
|
|
|
|
```json
|
|
{
|
|
"type": "component_ref",
|
|
"component": "ui-kit#Button/Primary",
|
|
"name": "submitButton",
|
|
"overrides": {
|
|
"btn_label_001": {
|
|
"content": "Submit"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
During build, this becomes:
|
|
|
|
```json
|
|
{
|
|
"type": "ref",
|
|
"ref": "btn_primary_001",
|
|
"descendants": {
|
|
"btn_label_001": {
|
|
"content": "Submit"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Property Reference
|
|
|
|
### Common Properties
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `type` | string | Element type |
|
|
| `id` | string | Unique identifier |
|
|
| `name` | string | Display name |
|
|
| `x` | number | X position |
|
|
| `y` | number | Y position |
|
|
| `width` | number/string | Width in pixels or "fill_container" |
|
|
| `height` | number | Height in pixels |
|
|
| `fill` | string/object | Background/text color |
|
|
| `opacity` | number | 0.0 to 1.0 |
|
|
| `visible` | boolean | Visibility |
|
|
| `locked` | boolean | Whether element is locked |
|
|
|
|
### Layout-Specific Properties
|
|
|
|
| Property | Applies To | Description |
|
|
|----------|-----------|-------------|
|
|
| `layout` | frame | Layout direction |
|
|
| `gap` | frame | Spacing between children |
|
|
| `padding` | frame | Internal padding |
|
|
| `justifyContent` | frame | Main axis alignment |
|
|
| `alignItems` | frame | Cross axis alignment |
|
|
|
|
### Text-Specific Properties
|
|
|
|
| Property | Description |
|
|
|----------|-------------|
|
|
| `content` | Text content |
|
|
| `fontSize` | Font size in pixels |
|
|
| `fontFamily` | Font name |
|
|
| `fontWeight` | Font weight |
|
|
| `textAlign` | Text alignment |
|
|
| `letterSpacing` | Letter spacing |
|
|
| `lineHeight` | Line height |
|
|
|
|
### Shape-Specific Properties
|
|
|
|
| Property | Applies To | Description |
|
|
|----------|-----------|-------------|
|
|
| `cornerRadius` | rectangle | Border radius |
|
|
| `stroke` | rectangle, ellipse | Stroke color |
|
|
| `strokeWidth` | rectangle, ellipse | Stroke width |
|
|
|
|
## Resources
|
|
|
|
- Back to [Pencil Design Skill](../SKILL.md)
|
|
- [Build System Reference](./BUILD_SYSTEM.md)
|
|
- [Atomic Design Reference](./ATOMIC_DESIGN.md)
|
|
- [Code Conversion Reference](./CODE_CONVERSION.md)
|