Sibling scale

Among open siblings, the latest stays full size and each earlier one halves, so several open media sections fit on screen at once.

Show code
/**
 * Among open siblings, the last one (in document order) stays full size and
 * each earlier open one halves: 1 → 0.5 → 0.25. Closed siblings don't count,
 * so closing the latest grows the one before it back to full.
 *
 * Pair it with an element that sizes from a CSS variable and transitions that
 * size on the same curve and duration as whatever opens it (400ms in RGL),
 * so a sibling shrinking and a panel opening read as one motion.
 */
export function siblingScale(
  id: string,
  siblingIds: readonly string[],
  openIds: ReadonlySet<string>,
  /** Each earlier open sibling is this fraction of the next. */
  step = 0.5,
): number {
  const open = siblingIds.filter((siblingId) => openIds.has(siblingId));
  const index = open.indexOf(id);
  if (index === -1) return 1;
  return step ** (open.length - 1 - index);
}