@@ -71,9 +71,12 @@ const Anchor = (props: AnchorProps): JSX.Element => {
7171 const container = getContainer ( ) ;
7272 const containerRect = container . getBoundingClientRect ( ) ;
7373 const elementRect = element . getBoundingClientRect ( ) ;
74- container . scrollTop += elementRect . top - containerRect . top ;
74+ container . scrollTo ( {
75+ top : container . scrollTop + elementRect . top - containerRect . top ,
76+ behavior : 'smooth' ,
77+ } ) ;
7578 } else {
76- element . scrollIntoView ( true ) ;
79+ element . scrollIntoView ( { behavior : 'smooth' , block : 'start' } ) ;
7780 }
7881 } ,
7982 [ getContainer ]
@@ -117,10 +120,24 @@ const Anchor = (props: AnchorProps): JSX.Element => {
117120 ? container . getBoundingClientRect ( ) . top
118121 : 0 ;
119122
123+ // Check if scrolled to the bottom
124+ let isAtBottom = false ;
125+ if ( container ) {
126+ isAtBottom = container . scrollTop + container . clientHeight >= container . scrollHeight - 1 ;
127+ } else {
128+ isAtBottom =
129+ window . innerHeight + window . scrollY >= document . documentElement . scrollHeight - 1 ;
130+ }
131+
120132 let newActiveId = '' ;
121133 let maxTop = - Infinity ;
122134 let firstId = '' ;
123135 let firstTop = Infinity ;
136+ // Track the last heading visible in the viewport (for bottom-of-page case)
137+ let lastVisibleId = '' ;
138+ let lastVisibleTop = - Infinity ;
139+ const viewportHeight = container ? container . clientHeight : window . innerHeight ;
140+
124141 links . forEach ( ( href ) => {
125142 const id = href . replace ( '#' , '' ) ;
126143 const el = document . getElementById ( id ) ;
@@ -134,8 +151,17 @@ const Anchor = (props: AnchorProps): JSX.Element => {
134151 maxTop = elTop ;
135152 newActiveId = id ;
136153 }
154+ // Track headings visible in the viewport
155+ if ( elTop >= 0 && elTop <= viewportHeight && elTop > lastVisibleTop ) {
156+ lastVisibleTop = elTop ;
157+ lastVisibleId = id ;
158+ }
137159 } ) ;
138- if ( ! newActiveId && firstId ) {
160+
161+ // When scrolled to the bottom, use the last visible heading
162+ if ( isAtBottom && lastVisibleId ) {
163+ newActiveId = lastVisibleId ;
164+ } else if ( ! newActiveId && firstId ) {
139165 newActiveId = firstId ;
140166 }
141167
0 commit comments