Edit in JSFiddle

// Initialisations
let s = Snap('svg')
let f = s.filter(Snap.filter.shadow(2, 2, 1, 'black', .5))  
let boutonbase = s.rect(10, 10, 40, 40, 10, 10).attr({filter: f, fill: 'yellow'})
let boutons = []
let textes = []
let boutonOuvert = null
const colors = ['yellow', 'lightgreen', 'lightblue']
const texts = ['Texte 1', 'Texte 2', 'Texte 3']

// Création des boutons et textes
boutons.push(boutonbase)
for(let i = 0; i < 3; ++i) {
    let y = 44 * i
    if(i) boutons.push(boutonbase.clone().transform('t0,' + y ).attr({ fill: colors[i]}))
    textes.push(s.text(-100, -100, texts[i]).attr({ 
        fontSize: 20,
        fontFamily: 'Arial, Helvetica, sans-serif',
        opacity: 0
    }))        
}

// Mise en place des événements
for(let bouton of boutons) {
    bouton.mouseover( function() {
        action(this)
    })       
}

let action = (bouton) => {console.log('fire')
    if(bouton != boutonOuvert) {
        bouton.stop().animate({ width: 100 }, 1500, mina.bounce, 
            () => {
                let box = bouton.getBBox()
                let x = box.x + 10
                let y = box.y + 28
                let boutonTemp = boutonOuvert 
                boutonOuvert = bouton
                textes[boutons.indexOf(bouton)].attr({x: x, y: y}).stop().animate({opacity: 1}, 400)
                if(boutonTemp) {
                    let textActual = textes[boutons.indexOf(boutonTemp)]  
                    textActual.animate({opacity: 0}, 300, () => textActual.attr({x: -100, y: -100}))
                    boutonTemp.stop().animate({ width: 40 }, 1500, mina.bounce)
                }               
            }
        )
    }
}