# How the Pill-Shaped Activity-Bar Selection Indicator Works in Islands Dark

> Discover how the Islands Dark VS Code theme uses CSS keyframe animations to create a dynamic pill-shaped activity bar selection indicator with a breathing glow effect.

- Repository: [Bradley Wyatt/vscode-dark-islands](https://github.com/bwya77/vscode-dark-islands)
- Tags: deep-dive
- Published: 2026-05-06

---

**The pill-shaped selection indicator in the Islands Dark VS Code theme is created purely with CSS keyframe animations that morph a flat element into a rounded pill and add a subtle breathing glow effect.**

The Islands Dark theme for VS Code features a distinctive pill-shaped selection indicator on the activity bar that animates when you switch between views like Explorer or Search. Unlike traditional bitmap icons, this visual effect is generated entirely through CSS animations defined in the theme's [`animations.css`](https://github.com/bwya77/vscode-dark-islands/blob/main/animations.css) file. Understanding how this pill-shaped activity bar selection indicator works reveals a clever combination of transform scaling, border-radius manipulation, and filter shadows that responds to VS Code's internal state classes.

## What Triggers the Animation

When a view becomes active in VS Code, the application automatically adds the class `action-item checked` to the corresponding activity-bar button. The Islands Dark theme targets this specific state using the selector `.part.activitybar .action-item.checked .action-label` defined in [`animations.css`](https://github.com/bwya77/vscode-dark-islands/blob/main/animations.css) at lines 127-131. This CSS selector catches the checked state and applies the animation sequence to the label element inside the activity bar item.

## The Drop-Morph Animation

The primary animation that creates the pill shape is defined in [`animations.css`](https://github.com/bwya77/vscode-dark-islands/blob/main/animations.css) at lines 20-38. The `@keyframes islands-drop-morph` sequence morphs a flat element into a pill-shaped rounded rectangle through three simultaneous transformations:

- **Scale transformation** – Expands the element horizontally while shrinking it vertically to create the characteristic pill proportions
- **Opacity fade** – Brings the element from invisible to fully visible during the first 20% of the animation
- **Border-radius expansion** – Increases the corner radius from 35% to 50%, transforming a rectangle into a perfect ellipse

```css
@keyframes islands-drop-morph {
  0%   { transform: scaleX(0.45) scaleY(2);   opacity: 0;   border-radius: 35%; }
  20%  { opacity: 0.7; border-radius: 40%;   transform: scaleX(0.5)  scaleY(1.5); }
  50%  { transform: scaleX(1.2)  scaleY(0.8); opacity: 1;   border-radius: 50%; }
  70%  { transform: scaleX(0.92) scaleY(1.08); }
  85%  { transform: scaleX(1.04) scaleY(0.96); }
  100% { transform: scaleX(1)    scaleY(1);   opacity: 1;   border-radius: 50%; }
}

```

## The Breathing Glow Effect

After the initial morph completes, a secondary animation add a subtle "breathing" glow. Defined in [`animations.css`](https://github.com/bwya77/vscode-dark-islands/blob/main/animations.css) at lines 44-48, the `islands-breathe` keyframes animate a `drop-shadow` filter to create a pulsing accent effect:

```css
@keyframes islands-breathe {
  0%, 100% { filter: drop-shadow(0 0 2px rgba(13,188,121,0)); }
  50%      { filter: drop-shadow(0 0 8px rgba(13,188,121,0.3)); }
}

```

This animation uses the theme's accent color (defined in [`themes/islands-dark.json`](https://github.com/bwya77/vscode-dark-islands/blob/main/themes/islands-dark.json) as `#548af7`) to create a soft glow that pulses indefinitely.

## Combining the Animations

The final effect is achieved by applying both animations simultaneously to the checked label. As shown in [`animations.css`](https://github.com/bwya77/vscode-dark-islands/blob/main/animations.css) at lines 127-131, the CSS declaration combines the morph and breathe animations with specific timing functions:

```css
.part.activitybar .action-item.checked .action-label {
  animation:
    islands-drop-morph 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    islands-breathe   4s ease-in-out 0.5s infinite !important;
}

```

The `islands-drop-morph` runs once over 0.4 seconds using a custom cubic-bezier curve for smooth settling, while `islands-breathe` starts after a 0.5-second delay and loops infinitely every 4 seconds.

## Working Implementation Example

You can reproduce this effect outside of VS Code using the following minimal HTML and CSS. This snippet demonstrates how the `islands-drop-morph` and `islands-breathe` animations work together to create the pill-shaped indicator:

```html
<style>
  @keyframes islands-drop-morph {
    0%   { transform: scaleX(0.45) scaleY(2); opacity: 0; border-radius: 35%; }
    20%  { opacity: 0.7; border-radius: 40%; transform: scaleX(0.5) scaleY(1.5); }
    50%  { transform: scaleX(1.2) scaleY(0.8); opacity: 1; border-radius: 50%; }
    70%  { transform: scaleX(0.92) scaleY(1.08); }
    85%  { transform: scaleX(1.04) scaleY(0.96); }
    100% { transform: scaleX(1) scaleY(1); opacity: 1; border-radius: 50%; }
  }

  @keyframes islands-breathe {
    0%, 100% { filter: drop-shadow(0 0 2px rgba(13,188,121,0)); }
    50%      { filter: drop-shadow(0 0 8px rgba(13,188,121,0.3)); }
  }

  .activity-bar .item.checked .label {
    display: inline-block;
    padding: 4px 12px;
    background: #548af7;
    color: #fff;
    border-radius: 50%;
    animation:
      islands-drop-morph 0.4s cubic-bezier(0.22, 1, 0.36, 1),
      islands-breathe 4s ease-in-out 0.5s infinite;
  }
</style>

<div class="activity-bar">
  <div class="item checked"><span class="label">Explorer</span></div>
</div>

```

## Summary

- **Pure CSS implementation** – The pill-shaped activity bar selection indicator relies entirely on CSS keyframe animations without any image assets
- **Two-stage animation** – The effect combines an initial `islands-drop-morph` animation that creates the shape, followed by an infinite `islands-breathe` animation for the glow effect
- **State-based triggering** – VS Code adds the `action-item checked` class automatically when a view is active, which triggers the CSS selector in [`animations.css`](https://github.com/bwya77/vscode-dark-islands/blob/main/animations.css)
- **Responsive design** – Because the animation uses scalable CSS properties (transform, border-radius, filter), the pill shape adapts to any DPI or zoom level automatically
- **Source locations** – Key definitions reside in [`animations.css`](https://github.com/bwya77/vscode-dark-islands/blob/main/animations.css) (lines 20-38 for the morph, lines 44-48 for the breathe, and lines 127-131 for the application rule)

## Frequently Asked Questions

### How does the pill shape form without using images?

The pill shape is created dynamically using the `border-radius` CSS property animated from 35% to 50% combined with `transform: scaleX()` and `scaleY()` operations. As the `islands-drop-morph` animation progresses, the element stretches horizontally while its corners become increasingly rounded, resulting in a perfect pill shape by the animation's end.

### Where are the animation keyframes defined in the repository?

All animation logic resides in the [`animations.css`](https://github.com/bwya77/vscode-dark-islands/blob/main/animations.css) file. The `@keyframes islands-drop-morph` definition spans lines 20-38, while `@keyframes islands-breathe` appears at lines 44-48. The selector that applies these animations to the activity bar is located at lines 127-131 in the same file.

### Can I customize the animation speed or disable the breathing effect?

Yes. You can override the animation duration by modifying the `0.4s` value for `islands-drop-morph` or the `4s` value for `islands-breathe` in your VS Code settings.json using custom CSS injection. To disable the breathing effect entirely, remove the `islands-breathe` reference from the animation declaration, leaving only the morph animation for a static pill indicator.

### What triggers the animation to start when I click an activity bar icon?

VS Code's core UI automatically adds the `checked` class to the `action-item` div when its associated view becomes active. The Islands Dark theme leverages this standard VS Code behavior by targeting `.part.activitybar .action-item.checked .action-label`, which means the animation starts immediately when VS Code updates the DOM class, requiring no JavaScript or additional markup from the theme itself.