Here is an example of a custom node that works like an accordion.


The Control moves each child to the end of the previous one (only in the y direction)

extends Control
export var spacing = 10
func _draw():
var last_end_achor = Vector2.ZERO
for child in get_children():
child.rect_position = last_end_achor
last_end_achor.y = child.rect_position.y + child.rect_size.y
last_end_achor.y += spacing
rect_min_size.y = last_end_achor.y #to work with ScrollContainer
And clicking on the button "show" toggles the parent "Panel" size to the open or the closed value.

extends Panel
var is_expanded = false
func _ready():
$VBoxContainer/show.connect("pressed",self,"expand")
func expand():
is_expanded = !is_expanded
var last_rect_size = Vector2.ZERO
func _process(delta):
#snap to end
if abs(rect_size.y-rect_min_size.y) < 1:
rect_size.y = rect_min_size.y
#resize to target size
if is_expanded:
rect_size.y = lerp(rect_size.y, 70, 0.1)
else:
rect_size.y = lerp(rect_size.y, rect_min_size.y, 0.1)
#update layout
if last_rect_size != rect_size:
get_parent().update()
last_rect_size = rect_size