Transaction is still open after cancelling query

IMHO, it is an intended behavior. When you cancels query running if there was open transaction - it remains open until you explicitly commit or roll it back OR until connection is not closed

There is no any valuable mistakes in your pattern. If you control execution flow manually (Cancel Executing Query), then you should care of opened transactions in the same manner - manually.

Update:

The behavior is controlled by SSMS option Disconnect after the query executes - which means that the query disconnects after execution or cancel and rolls back opened transactions: enter image description here