# 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: defaults below help new automation avoid Sketch UI pitfalls. Do not restyle existing layers to match them 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 "sane defaults" snippet for new Frames (MCP-created only)

```javascript
const sketch = require('sketch');
var f = new sketch.Group.Frame({
  parent: page,
  name: 'Container',
  frame: { x: 0, y: 0, width: 400, height: 600 },
});
f.background.enabled = false;                 // no accidental fill
f.style.borders = [{
  color: '#454545',
  thickness: 1,
  position: sketch.Style.BorderPosition.Inside,
  enabled: false,                              // off until you actually want one
  fillType: sketch.Style.FillType.Color,
}];
```
