Align viewport rotation to normal vector like Shift+7 in edit mode I know this question has been asked and answered before but the behavior I want is what ⇧ Shift + Num 7 exactly does in edit mode which is to align the viewport to &quot;face&quot; the element selected (in my case a face or polygon) and &quot;rotate&quot; the viewport on its axis to match the orientation of the normal.
My code takes care of the first part which is to position the viewport to &quot;face&quot; the polygon and have no problem orienting itself on their normals except for faces that are rotated in multiple axis. e.g. the active face in the picture below, for the other faces which are angled only on a single axis the script has no problem orienting itself on their normals.

In my original code, the variables are delivered by raycast so I'd like to achieve this effect using only hit, normal plus the viewport and object properties. Face index is avoided since the target objects are using unapplied modifiers.
import bpy
import bmesh
from mathutils import *; from math import *

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
       rv3d = area.spaces[0].region_3d
       
obj = bpy.context.edit_object
mat = obj.matrix_world
me = obj.data

bm = bmesh.from_edit_mesh(me)
f = bm.select_history.active

start = f.calc_center_median()
normal = f.normal

stop  = start + normal
norm = start - stop
norm.normalize()

q = norm.to_track_quat('-Z', 'Y')
rv3d.view_rotation = q
rv3d.view_location = start

bmesh.update_edit_mesh(me, True)

rotateview_blend_file
I solved it. If the tangent picks the wrong direction and doesn't align to the viewport, the rotation matrix inverts and uses the negative value of the angle for correction. Keeping it here for prosperity and to help those seeking this kind of alignment behavior.
import bpy
import bmesh
from mathutils import *; from math import *

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
       rv3d = area.spaces[0].region_3d

obj = bpy.context.active_object
mat = obj.matrix_world
me = obj.data

bm = bmesh.from_edit_mesh(me)
f = bm.select_history.active

up = Vector((0,0,1))
up1 = Vector((0,-1,0))

center = f.calc_center_median()
normal = f.normal
tangent = f.calc_tangent_edge()

mw = mat.to_3x3()
quat = normal.rotation_difference(mw.inverted() @ up)
rot_mat = mw @ quat.to_matrix()

loc, rot, scale = rv3d.view_matrix.decompose()

mat_scale = Matrix()
for i in range(3):
    mat_scale[i][i] = scale[i]

rv3d.view_matrix = Matrix.Translation(loc) \
    @ rot_mat.to_4x4() \
    @ mat_scale
    
vrot = rv3d.view_rotation
rot_axis = vrot @ up
rot_dir = vrot @ up1

rotdiff = rot_dir.rotation_difference(tangent)
M = mw @ Matrix.Rotation(rotdiff.angle, 3, rot_axis)
rv3d.view_rotation.rotate(M)

if (rv3d.view_rotation @ up1).rotation_difference(tangent).angle != 0:
    rv3d.view_rotation.rotate(M.inverted())
    M = mw @ Matrix.Rotation(-rotdiff.angle, 3, rot_axis)
    rv3d.view_rotation.rotate(M)    

rv3d.view_location = obj.matrix_world @ center
bmesh.update_edit_mesh(me, True)