---
title: "BRAND Spotify 2026 · Recipe: app-shell"
url: https://memocore.ai/memos/6ae42ed0cb977478f04eb823
project: "Brand Styles"
tags: "brand-spotify"
updated_at: "2026-10-30T06:30:43.652Z"
---

# BRAND Spotify 2026 · Recipe: app-shell

HEADER
brand: Spotify; design_date: 2026-10; kind: component; used_in: all player Page memos
captured: https://open.spotify.com/ 2026-10-30, Japan (market JP) by direct connection with the user's agreement; logged out; UI in English
evidence: measured on that URL unless marked; timings recorded live from transitionrun events; (code) = read in CSS or JS

LOOK
A black window with floating dark panels separated by 8px: the library on the left, the main view in the center, a narrow collapsed rail on the right. A black bar with logo, home button, and a large pill search sits on top; a violet-to-blue "Preview of Spotify" bar sits at the bottom when logged out. Hovering the gap shows a thin resize line.

STRUCTURE
Root grid: "top-banner" / "global-nav" / "left-sidebar main-view right-sidebar" (1fr) / "now-playing-bar"; columns auto 1fr. Padding and gap --panel-gap 8; background #000. When logged out the right sidebar is a collapsed rail 32 wide (x 1400 to 1432 at 1440), bg #121212, radius 8, with a left chevron at mid height.

KEY PARAMETERS
global nav: 64 total (48 + gap x 2), background #000; left: logo, home 48 circle, search; right: Premium, Support, Download 16/700 #b3b3b3 tightly spaced (about 8 between labels), 1 x 25 white divider (margin 16), Install App 14/700 with an icon, Sign up 14/700, Log in white pill 108 x 48
search: pill radius 500, height 48, width 50% (min 350, max 546), measured 474 at 1440; padding 12 96 12 48; bg #1f1f1f; placeholder "What do you want to play?"; search icon left, divider and browse icon right
sidebar: bg #000 in frame set, radius 8; measured 331 x 754 at 1440 (var --left-sidebar-width, root default 232); resize range 280 to 420, read from the slider aria values on the artist page; title row: "Your Library" 16/700 white at y 87, plus icon in a 32 circle at right; first promo starts at y 155; promo cards bg #1f1f1f, radius 8, padding 16 20, 315 x 133, 24 apart; card title 16/700, text 14, white pill button 32 tall; lower part: legal links 11-12 #b3b3b3 (est) in wrapped rows, Cookies, language pill 100 x 32 at y 754 with globe icon, 1px border
main view: x 347, width 1045, height 754, bg #121212, radius 8; container query main-view-grid-area
bottom bar: 1424 x 66, radius 8 on Windows, 16 on macOS; gradient 90deg #af2896 -> #509bf5; padding 11 24 7 15; gap 24; title 14/700, text 16/400; white pill "Sign up free" 48
scrollbar: overlay scrollbars, auto-hide, top 4 bottom 4
body min width 800

MOTION: interaction records
- id: shell.home
  element: home 48 circle
  trigger: hover
  open: background #1f1f1f -> #2a2a2a, 200ms, ease-in-out; icon #fff; scale 1.04 with no transition, because its transition list has only background and color, so the circle jumps while the colour eases
  close: background 200ms, ease-in-out; scale back at once
- id: shell.search
  element: search pill, icon, shortcut hints
  trigger: hover
  open: background #1f1f1f -> #2a2a2a, box-shadow none -> inset 0 0 0 1px #ffffff1a, icon #b3b3b3 -> #fff, all 220ms, ease-in. Shortcut hints (Ctrl Shift L) opacity 0 -> 1, 220ms, ease-in-out
  close: same reversed; hints fade 220ms
  switch: focus: box-shadow -> inset 0 0 0 2px #fff, 220ms, ease-in; hints stay. Blur reverses
  keyboard: Tab gives the same 2px inset
- id: shell.nav-buttons
  element: nav text and icon buttons
  trigger: hover
  open: color #b3b3b3 -> #fff and none -> scale(1.04), 50ms, cubic-bezier(.3,0,0,1)
  close: 150ms, same curve
  press: opacity .7, scale 1 at once
- id: shell.login
  element: Log in, Create playlist, Sign up free (white primary)
  trigger: hover
  open: background #fff -> #f0f0f0 and none -> scale(1.04), 50ms, same curve
  close: 150ms, same curve
  press: #c7c7c7 (code), scale 1
- id: shell.language
  element: language pill (secondary)
  trigger: hover
  open: border #7c7c7c -> #fff on all sides and none -> scale(1.04), 50ms, same curve
  close: 150ms, same curve
  press: opacity .7, scale 1 at once
  children: click opens a dialog with no recorded animation: 978 x 588, #282828, radius 8, overlay rgba(0,0,0,.7)
- id: shell.tooltip
  element: tooltip on icon buttons
  trigger: hover or focus; delay depends on the button (Play 1000ms; others pass 500, 1500 or none, code)
  open: opacity 0 -> 1, 200ms, ease-in-out
- id: shell.scrollbar
  element: overlay scrollbar of the main view
  trigger: pointer in and out
  open: visibility and opacity, 200ms, ease
  close: same
- id: shell.resize
  element: bar in the gap
  trigger: hover (code, not recorded live)
  open: width 8, opacity 0 -> 1, 150ms, ease-out; line 1px #7c7c7c, height calc(100% - 16px); while resizing line #fff; cursor col-resize
  keyboard: alt+shift+left and right change sidebar width; alt+shift+l toggles; step 10 by code
- id: shell.bars
  element: global nav and bottom bar fades
  trigger: state change (code)
  open: opacity .3s ease-in
  close: hidden .3s ease-out, delay .5s

STATES
Hover and press: above. Focus: browser default ring on legacy buttons, 2px white on newer ones (code).
touch and mobile: below 800 the site serves another layout: top bar 56 tall (est) with logo, white "Open App" pill 93 x 32 (13/700) and menu icon; content single column on #121212, padding 16; fixed bottom tab bar 70 tall (Home, Search, Your Library, Premium) with icons above 11px labels over a dark fade; no sidebar. Search page: white 48 tall input radius 4.
reduced motion: scale off (code)
loading fallback: dark panels

HOW TO BUILD
CSS grid with named areas, gap and padding from one variable. Panels get radius 8 and their own scroll. Resize by pointer events updating one custom property, clamped to 280-420.

PITFALLS
The frame is pure #000 and the main panel #121212; the difference must be visible. Radius 8 on all panels. Do not add borders between panels, the gap is the divider. Keep the 32 rail at the right; without it the main view is too wide and shelves show an extra card. Search has its own slower 220ms ease-in, unlike the buttons around it. Home scales with no transition.

SCREENSHOTS
- file: spotify_2026_home_d1440_top.jpeg
  shows: full shell at 1440x900, logged out
  source: live, Japan market, 2026-10-30; cookie banner hidden
  key values: frame #000; main #121212; gap 8; search 474 x 48
  do not copy: logo, covers
- file: spotify_2026_overview_d1440_language-dialog.jpeg
  shows: language dialog, overlay rgba(0,0,0,.7), dialog #282828 radius 8, 978 x 588
  source: live, Japan market, 2026-10-30; cookie banner hidden
  key values: overlay .7; dialog radius 8
  do not copy: logo
