Grid/Component/ButtonComponent.cs
// ================================
// ButtonComponent.cs
// ================================
using Sandbox;
using Sandbox.Grid.Base;
using System.Numerics;

public sealed class ButtonComponent : GridActivatableBase
{
    [Property] public float PressDepth { get; set; } = 1.2f;
    [Property] public float PressSpeed { get; set; } = 80f;
    [Property] public float ReleaseDelay { get; set; } = 3f;

    private Vector3 startPos;
    private Vector3 pressedPos;

    private bool pressed;
    private bool activated;
    private float releasedTime;
    private bool IsActivating;
    protected override void OnStart()
    {
        base.OnStart();

        startPos = Transform.Position;
        pressedPos = startPos - Vector3.Up * PressDepth;

        var box = Components.Get<BoxCollider>();
        box?.OnTriggerEnter += _ => pressed = true;
        box?.OnTriggerExit += _ => pressed = false;
        
    }

    protected override void OnUpdate()
    {
        Transform.Position = MoveTowards(
            Transform.Position,
            pressed ? pressedPos : startPos,
            PressSpeed * Time.Delta
        );

        if (pressed && !activated)
        {
            activated = true;

            if (!IsActivating)
            {
                IsActivating = true;
                ActivateChain(ChainDelay);
                IsActivating = false;
            }

            releasedTime = 0f;
        }


        if (!pressed && activated)
        {
            releasedTime += Time.Delta;
            if (releasedTime >= ReleaseDelay)
            {
                Deactivate();
                activated = false;
            }
        }
    }

    public override void Activate() { }
    public override void Deactivate()
    {
        foreach (var a in GetLinkedActivatables())
            a.Deactivate();
    }
}