# get_guide: styling

This is a subtopic for swatches/shared styles/fills/borders/corners/blurs/masks/typography. If you have not already loaded the parent topic, call `get_guide` with `topic: "use"` first. The `use` topic also requires the `mcp` topic to be loaded before any Sketch MCP tool call.

# Styling — deep dive

Use after calling `get_guide` with `topic: "use"`, section "Styling Guidance", when you need full coverage of swatches, shared styles, corners, per-side borders, blurs, glass, container tints, and masks.

Rule of thumb: prefer swatches and shared styles over hardcoded per-layer values. A layer that points at a swatch updates everywhere when the swatch changes; a layer with a hex literal does not.

For reusable components, prefer library symbols/components before recreating styled layer groups by hand. Call `get_design_assets` for symbols and `get_guide` with `topic: "symbols"` when inserting or overriding symbol instances.

MCP-created layers: the Sketch JavaScript API already applies sensible border positions and Frame backgrounds at creation. The notes below cover what still needs explicit control. Do not restyle existing layers unless the user or task requires it.

## Document tokens

### Swatches (`document.swatches`)

```javascript
const sketch = require('sketch');
const doc = sketch.getSelectedDocument();

// Read
doc.swatches.forEach(function (s) {
  console.log(JSON.stringify({ id: s.id, name: s.name, hex: String(s.color).slice(0, 9) }));
});

// Create
doc.swatches.push({ name: 'Brand/Primary', color: '#575fff' });

// Update (propagates to every reference)
var swatch = doc.swatches.find(function (s) { return s.name === 'Brand/Primary'; });
swatch.color = '#3b48ff';
swatch.name = 'Brand/Primary 2';
```

`Swatch.color` is a hex-like string when read. Library swatches are immutable — update them in the source library and call `syncWithLibrary()`.

### Using swatches in styles

Color-bearing properties accept a `Swatch` directly, which keeps the link alive:

```javascript
// Fills / borders / shadows / tints
layer.style.fills[0].swatch = swatch;        // ✅ preferred
layer.style.borders[0].swatch = swatch;
layer.style.shadows[0].swatch = swatch;
layer.style.tint = { swatch: swatch };

// Text color
textLayer.style.textSwatch = swatch;         // ✅ preferred over .textColor
```

Where the API only accepts a color string, pass `swatch.referencingColor`:

```javascript
layer.style.fills[0].color = swatch.referencingColor;
```

Plain hex (`'#575fff'`) works but breaks the swatch link — only fall back to it when no token exists.

### Shared layer/text styles

```javascript
// Discover
doc.sharedLayerStyles.forEach(function (s) {
  console.log(JSON.stringify({ id: s.id, name: s.name }));
});

// Create
var newStyle = { fills: [{ color: '#1a1a1a', enabled: true, fillType: sketch.Style.FillType.Color }] };
doc.sharedLayerStyles.push({ name: 'Surface/Card', style: newStyle });

// Apply (instances update when the source style changes)
var style = doc.sharedLayerStyles.find(function (s) { return s.name === 'Surface/Card'; });
layer.sharedStyle = style;

// Text styles work the same
doc.sharedTextStyles.push({ name: 'Type/Body', style: { fontSize: 14 } });
```

Library-backed styles are imported via `library.getImportableLayerStyleReferencesForDocument(doc)` / `...TextStyleReferences...`, then `ref.import()` and assigned on the same statement.

## Fills

```javascript
// Solid color fill
layer.style.fills = [{
  fillType: sketch.Style.FillType.Color,
  color: '#1a1a1a',
  enabled: true,
}];

// Or via a swatch
layer.style.fills[0].swatch = swatch;

// Gradient fill
layer.style.fills = [{
  fillType: sketch.Style.FillType.Gradient,
  gradient: {
    gradientType: sketch.Style.GradientType.Linear,
    from: { x: 0.5, y: 0 },
    to: { x: 0.5, y: 1 },
    stops: [
      { position: 0, color: '#ffffff' },
      { position: 1, color: '#000000' },
    ],
  },
  enabled: true,
}];

// Disable / remove fills (e.g. structural Frame containers)
layer.style.fills = [];                // remove all
group.background.enabled = false;      // Frame-specific helper
```

`FillType` values: `Color` | `Gradient` | `Pattern`.

## Borders

```javascript
layer.style.borders = [{
  color: '#454545',
  thickness: 1,
  position: sketch.Style.BorderPosition.Inside,  // Inside | Center | Outside (avoid Both)
  enabled: true,
  fillType: sketch.Style.FillType.Color,
}];
```

### Per-side borders

```javascript
var border = layer.style.borders[0];

// Single-thickness (default)
border.thickness = 2;

// Per-side, partial
border.sides = { top: 1, bottom: 2 };       // left/right keep their previous value
// Per-side, full
border.sides = { top: 1, right: 1, bottom: 1, left: 1 };

// Reset to single-thickness
border.sides = null;

console.log(JSON.stringify({ hasIndividualSides: border.hasIndividualSides }));
```

`border.sides = null` resets to single-thickness; `hasIndividualSides` reports the current mode.

## Corners

Corners live on `layer.style.corners`. Available styles:

- `Auto` (-1): Inherit from parent Frame's concentric corner system
- `Rounded` (0): Standard rounded corners
- `Smooth` (1): iOS-style smooth corners
- `Angled` (2): Beveled corner
- `InsideSquare` (3): Square inner cut
- `InsideArc` (4): Arc inner cut

```javascript
var c = layer.style.corners;
c.style = sketch.Style.CornerStyle.Smooth;
c.radii = [12, 12, 12, 12];   // top-left, top-right, bottom-right, bottom-left
c.smoothing = 0.6;            // Smooth corner smoothing factor

// Per-corner radius
c.radiusAt(0);                 // read
// Set via radii array (no per-index setter; reassign the array)

// Concentric corners (children of a Frame inherit/adapt automatically)
parentFrame.style.corners.concentric = true;
```

Concentric corners are most useful when you have nested rectangles or buttons inside a rounded Frame — children inherit the rounding behavior so the inset stays visually correct.

## Blurs

`layer.style.blurs` is an array of blur objects. Five blur types:

```javascript
sketch.Style.BlurType    // { Gaussian, Motion, Zoom, Background, Glass }
```

### Gaussian (the default)

```javascript
layer.style.blurs = [{
  enabled: true,
  blurType: sketch.Style.BlurType.Gaussian,
  radius: 8,
}];
```

### Motion

```javascript
layer.style.blurs = [{
  enabled: true,
  blurType: sketch.Style.BlurType.Motion,
  radius: 12,
  motionAngle: 45,    // degrees
}];
```

### Zoom

```javascript
layer.style.blurs = [{
  enabled: true,
  blurType: sketch.Style.BlurType.Zoom,
  radius: 20,
  center: { x: 0.5, y: 0.5 },     // unit coordinates (0..1) inside the layer
}];
```

### Background

```javascript
layer.style.blurs = [{
  enabled: true,
  blurType: sketch.Style.BlurType.Background,
  radius: 16,
  saturation: 1.3,   // [0..2]
}];
```

### Glass

```javascript
layer.style.blurs = [{
  enabled: true,
  blurType: sketch.Style.BlurType.Glass,
  radius: 24,
  brightness: 1.0,            // [0..2]
  distortion: 0.4,            // [0..1]
  depth: 0.5,                 // [0..1]
  chromaticAberration: 0.1,   // [0..1]
  saturation: 1.0,            // [0..2]
  hasSpecularHighlights: true,
}];
```

All Glass properties are clamped to the documented ranges; values outside the range are silently snapped to the nearest bound.

### Progressive blur

Any blur can be made progressive by attaching a gradient that drives alpha-by-progression:

```javascript
layer.style.blurs = [{
  enabled: true,
  blurType: sketch.Style.BlurType.Gaussian,
  radius: 20,
  progressive: true,
  gradient: {
    gradientType: sketch.Style.GradientType.Linear,
    from: { x: 0.5, y: 0 },
    to:   { x: 0.5, y: 1 },
    stops: [
      { position: 0, color: '#000000ff' },  // alpha 1
      { position: 1, color: '#00000000' },  // alpha 0
    ],
  },
}];
```

The blur strength follows the gradient's alpha along its direction.

## Container tint

A tint colors all contents of a Frame uniformly. Use a swatch when possible:

```javascript
frame.style.tint = { swatch: swatch };
// or
frame.style.tint = { color: '#80000080' };  // hex with alpha
// Clear
frame.style.tint = null;
```

## Shadows

```javascript
layer.style.shadows = [{
  enabled: true,
  color: '#00000040',
  x: 0,
  y: 4,
  blur: 12,
  spread: 0,
}];

layer.style.innerShadows = [{ /* same shape */ }];
```

Use `shadows[i].swatch = swatch` to keep the color linked to a token.

## Masks

The mask system is layer-relational, not a style property:

```javascript
// Make a layer act as a mask for its following siblings
shape.masksSiblings = true;

// Skip the current mask chain
overlay.breaksMaskChain = true;

// Inspect
console.log(JSON.stringify({
  isMasked: !!layer.closestMaskingLayer,
  masksSiblings: layer.masksSiblings,
  breaksMaskChain: layer.breaksMaskChain,
}));

// Walk up the mask chain
var current = layer;
while (current && current.closestMaskingLayer) {
  console.log(JSON.stringify({ name: current.name, maskedBy: current.closestMaskingLayer.name }));
  current = current.closestMaskingLayer;
}
```

Masks work best inside a Group/Frame where the mask layer is the first sibling and subsequent siblings are masked by it.

## Style copy / shared style hygiene

To reuse styles across layers without creating a shared style:

```javascript
// Read a style snapshot (plain JS object)
var ref = sourceLayer.style;
// Copy properties individually (assigning the whole style.fills array is safe)
targetLayer.style.fills = ref.fills.map(function (f) { return { ...f }; });
```

When you find yourself doing this for two or more layers, convert to a shared style instead — it scales better and keeps tokens linked.

## Typography (text style)

```javascript
textLayer.style.fontFamily = 'Inter';
textLayer.style.fontSize = 14;
textLayer.style.fontWeight = 5;   // 1..12 maps to ultralight..black
textLayer.style.alignment = sketch.Text.Alignment.left;
textLayer.style.textColor = '#1a1a1a';     // or .textSwatch = swatch (preferred)
textLayer.style.textTransform = 'none';    // 'none' | 'uppercase' | 'lowercase'
textLayer.style.textUnderline = 'single';
textLayer.style.textStrikethrough = 'single';
```

When setting typography on new MCP-created text, avoid `kerning`, `lineHeight`, `paragraphSpacing` unless the spec requires them. Leave existing text layers as-is.

## Quick snippet for transparent structural Frames (MCP-created only)

Use when you need a layout wrapper, not a new screen/artboard. Canvas-level Frames on a Page get a default background automatically; opt out at creation:

```javascript
const sketch = require('sketch');
var f = new sketch.Group.Frame({
  parent: page,
  name: 'Container',
  frame: { x: 0, y: 0, width: 400, height: 600 },
  background: { enabled: false },              // transparent structural wrapper
});
```
