Module: Studio::FizzHelper

Defined in:
app/helpers/studio/fizz_helper.rb

Overview

The bubble table behind the hold-to-confirm button's fizz layers.

The CodePen this adapts scattered its particles with Sass random() at compile time. There is no Sass here, and a runtime rand would re-scatter the bubbles on every render — which fights Turbo's page cache (a restored page would not match the one it replaced) and leaves the markup untestable. So the scatter is SEEDED: stable for a given button across renders, and different between two buttons on one page.

ZONES. The button is cut into a 3x2 grid — three zones along the top edge, three along the bottom, numbered left to right, top row first. A bubble only ever wears the colours of the zone it sits in, so a six-item palette reads as six things standing around the button rather than one shaken bag of confetti. The outer columns also own the spray off the left and right sides, each within its own half.

COLOURS. Each zone carries three slots — 1..18 across the six zones — and the two layers split them: the resting layer wears the FIRST of its zone's three, and the layer that fades in on hover alternates the second and third. A caller binds them as --fizz-c-1..18 on the stack (turf-monster's board maps the six picked teams' light / dark / alt colours onto them, in pick order); anything unbound falls back to the bubble's own hue, so the effect is never colourless.

Constant Summary collapse

HUES =

Candy hues a bubble falls back to. Deliberately narrow — the source material spanned the whole wheel and read as confetti.

[ 262, 276, 292, 318, 336, 190, 168, 46 ].freeze
ZONE_COLUMNS =
3
ZONE_ROWS =
2
ZONES =
ZONE_COLUMNS * ZONE_ROWS
COLORS_PER_ZONE =
3
SLOTS =
ZONES * COLORS_PER_ZONE
LAYER_OFFSETS =

Which of its zone's three slots a layer's bubbles take.

{
  base: [ 0 ].freeze,     # the first colour
  hover: [ 1, 2 ].freeze  # the second and third, alternating
}.freeze

Instance Method Summary collapse

Instance Method Details

#fizz_bit_style(bit) ⇒ Object

The inline style one bubble carries. Kept here rather than in the partial so the property names and the CSS that reads them stay in one place.



70
71
72
73
74
# File 'app/helpers/studio/fizz_helper.rb', line 70

def fizz_bit_style(bit)
  "left:#{bit[:x]}%;top:#{bit[:y]}%;" \
    "--fs:#{bit[:size]}px;--fx:#{bit[:dx]}px;--fy:#{bit[:dy]}px;" \
    "--fd:#{bit[:delay]}s;--ft:#{bit[:duration]}s;--fc:#{fizz_color(bit)}"
end

#fizz_bits(seed, layer: :base, per_zone: 5) ⇒ Object

One layer's bubbles. Each is a hash the partial writes out as inline custom properties: x/y place it (%), dx/dy are the drift it travels before fading (dy negative = rises off the top edge), size is px, delay and duration are seconds, hue is its fallback colour, zone and slot are its place in the palette.



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'app/helpers/studio/fizz_helper.rb', line 49

def fizz_bits(seed, layer: :base, per_zone: 5)
  offsets = LAYER_OFFSETS.fetch(layer)
  prng = Random.new(seed.to_s.each_byte.sum * 7919 + per_zone)

  ZONES.times.flat_map do |zone|
    Array.new(per_zone) do |i|
      fizz_zone_bit(prng, zone: zone, index: i).merge(
        zone: zone + 1,
        slot: (zone * COLORS_PER_ZONE) + offsets[i % offsets.size] + 1
      )
    end
  end
end

#fizz_color(bit) ⇒ Object

One bubble's colour: its slot's bound colour, else its own hue.



64
65
66
# File 'app/helpers/studio/fizz_helper.rb', line 64

def fizz_color(bit)
  "var(--fizz-c-#{bit[:slot]}, hsl(#{bit[:hue]} 92% 70%))"
end