Repository: ant-design-blazor/ant-design-blazor (csharp)

Issue:
When Card is used, the Tabs component's tag position is always in bottom
<!--

请尽量使用英语，因为我们有来自全球的贡献者，使用英语会让您的问题和需求得到更迅速的响应和解决。
推荐使用：https://cn.bing.com/translator

Please use English as much as possible, as we have contributors from all over the world,
using English will allow your questions and needs to be responded to and resolved more quickly.
-->

### Describe the bug

When Card is used, the Tabs component's tag position is always in bottom
----------------------translate---------------------
当使用了Card时，Tabs组件的标签位置一直都在下方

![image](https://user-images.githubusercontent.com/3509249/116208381-73c06b80-a773-11eb-9aa1-189cd277acdd.png)


### Steps to reproduce (please include code)
use Tabs in a card:
```
<AntDesign.Card>
	<Tabs DefaultActiveKey="1">
		<TabPane Key="1">
			<Tab>TabName1</Tab>
			<ChildContent>Content1</ChildContent>
		</TabPane>
		<TabPane Key="2">
			<Tab>TabName2</Tab>
			<ChildContent>Content2</ChildContent>
		</TabPane>
	</Tabs>	
</AntDesign.Card>
```

### Exceptions (if any)
<!-- 
Include the exception you get when facing this issue
-->

### Further technical details
- AntDesign Nuget Package version: 0.8.0
- Include the output of `dotnet --info`
- The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version: VS16.10.0 Preview2.1

Pull request:
<!--
First of all, thank you for your contribution! 😄

New feature please send pull request to feature branch, and rest to master branch.
Pull request will be merged after one of collaborators approve.
Please makes sure that these form are filled before submitting your pull request, thank you!

[[中文版模板 / Chinese template](https://github.com/ant-design-blazor/ant-design-blazor/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)]

-->

### 🤔 This is a ...

- [ ] New feature
- [x] Bug fix
- [ ] Site / documentation update
- [ ] Demo update
- [ ] Component style update
- [ ] Bundle size optimization
- [x] Performance optimization
- [x] Refactoring
- [ ] Code style optimization
- [ ] Test Case
- [ ] Branch merge
- [ ] Other (about what?)

### 🔗 Related issue link

<!--
1. Describe the source of requirement, like related issue link.
-->

fixed #3887 
fixed #4061 
fixed #1424

### 💡 Background and solution

<!--
1. Describe the problem and the scenario.
2. GIF or snapshot should be provided if includes UI/interactive modification.
3. How to fix the problem, and list final API implementation and usage sample if that is an new feature.
-->

### 📝 Changelog

<!--
Describe changes from userside, and list all potential break changes or other risks.
--->

| Language   | Changelog |
| ---------- | --------- |
| 🇺🇸 English |           |
| 🇨🇳 Chinese |           |

### ☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

- [ ] Doc is updated/provided or not needed
- [ ] Demo is updated/provided or not needed
- [ ] Changelog is provided or not needed

Patch:
diff --git a/components/card/Card.razor.cs b/components/card/Card.razor.cs
index d3765dd521..564f8b7a9b 100644
--- a/components/card/Card.razor.cs
+++ b/components/card/Card.razor.cs
@@ -112,10 +112,6 @@ public partial class Card : AntDomComponentBase
         [Parameter]
         public RenderFragment Extra { get; set; }
 
-        /// <summary>
-        /// Tab content rendered below title
-        /// </summary>
-        [Parameter]
         public RenderFragment CardTabs { get; set; }
 
         private bool _hasGrids;
@@ -147,6 +143,16 @@ internal void MarkHasGrid()
             StateHasChanged();
         }
 
+        internal void InvokeStateHasChagned()
+        {
+            StateHasChanged();
+        }
+
+        internal void SetTabs(RenderFragment tabs)
+        {
+            this.CardTabs = tabs;
+        }
+
         internal void SetBody(RenderFragment body)
         {
             this.Body = body;
diff --git a/components/tabs/TabPane.razor b/components/tabs/TabPane.razor
index 188a764a6c..093ca8a211 100644
--- a/components/tabs/TabPane.razor
+++ b/components/tabs/TabPane.razor
@@ -1,74 +1,78 @@
 ﻿@namespace AntDesign
+@using Microsoft.AspNetCore.Components.Rendering
 @inherits AntDomComponentBase
 
-@if (_hasClosed)
-{
-    return;
-}
+@code{
+    internal void RenderTab(RenderTreeBuilder __builder)
+    {
+        if (_hasClosed)
+            return;
 
-@if (IsTab)
-{
-    var ondragoverPreventDefault = _isActive;
-    var onclickStopPropagation = !_isActive;
+        var ondragoverPreventDefault = _isActive;
+        var onclickStopPropagation = !_isActive;
 
-    <div @key="Key"
-     @ref="_tabRef"
-     @onclick:stopPropagation="@onclickStopPropagation"
-     @onclick="@(e => Parent.HandleTabClick(this))"
-     @ondragover:preventDefault="@ondragoverPreventDefault"
-     @ondragstart="@(e => Parent.HandleDragStart(e, this))"
-     @ondrop="@(_ => Parent.HandleDrop(this))"
-     class="@ClassMapper.Class"
-     draggable="@Parent.Draggable.ToString()"
-     id="@TabId"
-     ondragover="event.preventDefault();">
-        <div @onkeydown="@HandleKeydown"
-             @ref="_tabBtnRef"
-             role="tab"
-             aria-selected="@(_isActive ? "true" : "false")"
-             class="ant-tabs-tab-btn"
-             aria-controls="@($"rc-tabs-{Id}-panel-{Key}")"
-             tabindex="0">
-            @if (TabTemplate != null)
-            {
-                @TabTemplate
-            }
-            else
+        <div @key="Key"
+             @ref="_tabRef"
+             @onclick:stopPropagation="@onclickStopPropagation"
+             @onclick="@(() => Parent.HandleTabClick(this))"
+             @ondragover:preventDefault="@ondragoverPreventDefault"
+             @ondragstart="@(EventUtil.AsNonRenderingEventHandler<DragEventArgs>(e => Parent.HandleDragStart(e, this)))"
+             @ondrop="@(()=> Parent.HandleDrop(this))"
+             class="@ClassMapper.Class"
+             draggable="@Parent.Draggable.ToString()"
+             id="@TabId"
+             ondragover="event.preventDefault();">
+            <div @onkeydown="@HandleKeydown"
+                 @ref="_tabBtnRef"
+                 role="tab"
+                 aria-selected="@(_isActive ? "true" : "false")"
+                 class="ant-tabs-tab-btn"
+                 aria-controls="@($"rc-tabs-{Id}-panel-{Key}")"
+                 tabindex="0">
+                @if (TabTemplate != null)
+                {
+                    @TabTemplate
+                }
+                else
+                {
+                    @Tab
+                }
+            </div>
+            @if (Parent.Type == TabType.EditableCard && Closable)
             {
-                @Tab
+                <button type="button" aria-label="remove" tabindex="0" class="ant-tabs-tab-remove" @onclick="(e) => Parent.RemoveTab(this)" @onclick:stopPropagation>
+                    <Icon Type="close" />
+                </button>
             }
         </div>
-        @if (Parent.Type == TabType.EditableCard && Closable)
+
+        @if (TabContextMenu != null)
         {
-            <button type="button" aria-label="remove" tabindex="0" class="ant-tabs-tab-remove" @onclick="(e) => Parent.RemoveTab(this)" @onclick:stopPropagation>
-                <Icon Type="close" />
-            </button>
+            <Dropdown Trigger="new[]{ Trigger.ContextMenu }" TriggerReference="_tabRef">
+                <Overlay>
+                    @TabContextMenu
+                </Overlay>
+            </Dropdown>
         }
-    </div>
+    }
 
-    @if (TabContextMenu != null)
+    internal void RenderPane(RenderTreeBuilder __builder)
     {
-        <Dropdown Trigger="new[]{ Trigger.ContextMenu }" TriggerReference="_tabRef">
-            <Overlay>
-                @TabContextMenu
-            </Overlay>
-        </Dropdown>
+        if (_hasClosed)
+            return;
+
+        <div @key="Key"
+             tabindex="@(_isActive ? "0" : "-1")"
+             class="@_tabPaneClassMapper.Class"
+             id="@($"rc-tabs-{Id}-panel-{Key}")"
+             role="tabpanel"
+             aria-hidden="@(_isActive ? "false" : "true")"
+             aria-labelledby="@($"rc-tabs-{Id}-tab-{Key}")">
+            @if (_isActive || _hasRendered || ForceRender)
+            {
+                _hasRendered = true;
+                @ChildContent
+            }
+        </div>
     }
-}
-else if (IsPane)
-{
-    <div @key="Key"
-     tabindex="@(_isActive ? "0" : "-1")"
-     class="@_tabPaneClassMapper.Class"
-     id="@($"rc-tabs-{Id}-panel-{Key}")"
-     role="tabpanel" 
-     aria-hidden="@(_isActive ? "false" : "true")"
-     aria-labelledby="@($"rc-tabs-{Id}-tab-{Key}")"
-     >
-        @if (_isActive || _hasRendered || ForceRender)
-        {
-            _hasRendered = true;
-            @ChildContent
-        }
-    </div>
 }
\ No newline at end of file
diff --git a/components/tabs/TabPane.razor.cs b/components/tabs/TabPane.razor.cs
index a9c9d3ea3c..3996fbd8e4 100644
--- a/components/tabs/TabPane.razor.cs
+++ b/components/tabs/TabPane.razor.cs
@@ -10,12 +10,6 @@ namespace AntDesign
 {
     public partial class TabPane : AntDomComponentBase
     {
-        [CascadingParameter(Name = "IsTab")]
-        internal bool IsTab { get; set; }
-
-        [CascadingParameter(Name = "IsPane")]
-        internal bool IsPane { get; set; }
-
         [CascadingParameter]
         private Tabs Parent { get; set; }
 
@@ -70,6 +64,8 @@ public partial class TabPane : AntDomComponentBase
 
         private bool HasTabTitle => Tab != null || TabTemplate != null;
 
+        internal int TabIndex => _tabIndex;
+
         internal ElementReference TabRef => _tabRef;
 
         internal string TabId => $"rc-tabs-{Id}-tab-{Key}";
@@ -88,6 +84,7 @@ public partial class TabPane : AntDomComponentBase
         private bool _hasClosed;
 
         private bool _hasRendered;
+        private int _tabIndex;
 
         protected override void OnInitialized()
         {
@@ -102,7 +99,7 @@ protected override void OnAfterRender(bool firstRender)
         {
             base.OnAfterRender(firstRender);
 
-            if (IsTab && HasTabTitle)
+            if (HasTabTitle)
             {
                 _hasRendered = true;
             }
@@ -133,11 +130,6 @@ private void SetClass()
                 ;
         }
 
-        internal void SetKey(string key)
-        {
-            Key = key;
-        }
-
         internal void SetActive(bool isActive)
         {
             if (_isActive != isActive)
@@ -147,6 +139,11 @@ internal void SetActive(bool isActive)
             }
         }
 
+        internal void SetIndex(int index)
+        {
+            _tabIndex = index;
+        }
+
         internal void Close()
         {
             _hasClosed = true;
@@ -163,32 +160,7 @@ protected override void Dispose(bool disposing)
 
         internal void ExchangeWith(TabPane other)
         {
-            var temp = other.Clone();
-            other.SetPane(this);
-            this.SetPane(temp);
-        }
-
-        private TabPane Clone()
-        {
-            return new TabPane
-            {
-                Key = Key,
-                Tab = this.Tab,
-                TabTemplate = this.TabTemplate,
-                Disabled = this.Disabled,
-                Closable = this.Closable,
-            };
-        }
-
-        private void SetPane(TabPane tabPane)
-        {
-            Key = tabPane.Key;
-            Tab = tabPane.Tab;
-            TabTemplate = tabPane.TabTemplate;
-            Disabled = tabPane.Disabled;
-            Closable = tabPane.Closable;
-
-            StateHasChanged();
+            (_tabIndex, other._tabIndex) = (other._tabIndex, _tabIndex);
         }
 
         private Task HandleKeydown(KeyboardEventArgs e)
diff --git a/components/tabs/Tabs.razor b/components/tabs/Tabs.razor
index f59dec98dc..2758227760 100644
--- a/components/tabs/Tabs.razor
+++ b/components/tabs/Tabs.razor
@@ -1,78 +1,100 @@
 @namespace AntDesign
+@using Microsoft.AspNetCore.Components.Rendering
 @inherits AntDomComponentBase
 
 <CascadingValue Value="this" IsFixed="@true">
-	<div class="@ClassMapper.Class" style="@Style" id="@Id">
-		<!--Tab bar-->
-		<div role="tablist" class="@_tabBarClassMapper.Class" style="@TabBarStyle">
 
-			@if (TabBarExtraContentLeft != null)
-			{
-				<div class="ant-tabs-extra-content">
-					  @TabBarExtraContentLeft
-				</div>
-			}
+    @ChildContent
 
-			<div class="@_tabsNavWarpPingClassMapper.Class" @ref="@_navWarpRef" id="@(Id)-nav-warpper">
-				<div class="ant-tabs-nav-list" style="@_navListStyle" @ref="@_navListRef" id="@(Id)-nav-list">
-					<CascadingValue Value="true" Name="IsTab" IsFixed="true">
-						@ChildContent
-					</CascadingValue>
-					@if (HasAddButton)
-					{
-						<button type="button" class="ant-tabs-nav-add" aria-label="Add tab" @onclick="OnAddClick">
-							<Icon Type="plus" />
-						</button>
-					}
-					<div class="@_inkClassMapper.Class" style="@_inkStyle"></div>
-				</div>
-			</div>
-			<Dropdown OnVisibleChange="OnVisibleChange">
-				<Overlay>
-					<ul tabindex="0" class="ant-tabs-dropdown-menu ant-tabs-dropdown-menu-root ant-tabs-dropdown-menu-vertical" id="@($"rc-tabs-{Id}-more-popup")" role="listbox" aria-label="expanded dropdown">
-						@foreach (var pane in _invisibleTabs)
-						{
-							<li class="ant-tabs-dropdown-menu-item @(pane.Disabled?$"ant-tabs-dropdown-menu-item-disabled":string.Empty)" id="@($"rc-tabs-{Id}-more-popup-{pane.Key}")" role="option" aria-disabled="false" aria-selected="false" aria-controls="@($"rc-tabs-{Id}-more-popup-{pane.Key}")"
-							    @onclick="(e)=>HandleTabClick(pane)">
-                                @if (pane.TabTemplate != null)
-                                {
-                                    @pane.TabTemplate
-                                }
-                                else
-                                {
-                                    @pane.Tab
-                                }
-                            </li>
-						}
-					</ul>
-				</Overlay>
-				<Unbound>
-					<div @ref="context.Current" class="@_operationClass" @onclick:preventDefault>
-						<button tabindex="-1" class="ant-tabs-nav-more" id="rc-tabs-0-more" aria-expanded="false" aria-haspopup="listbox" aria-hidden="true" aria-controls="rc-tabs-0-more-popup"
-								style="@_operationStyle" type="button">
-							<Icon Type="ellipsis" />
-						</button>
-					</div>
-				</Unbound>
-			</Dropdown>
+    <Template>
+        @{
+            this.Complete();
+            if (Card is null)
+            {
+                @RenderTabs
+            }
+        }
+    </Template>
+</CascadingValue>
 
-	  		@if (TabBarExtraContent != null || TabBarExtraContentRight != null || (Card?.Extra != null && Card?.Title == null && Card?.TitleTemplate == null))
-			{
-				<div class="ant-tabs-extra-content">
-					@(TabBarExtraContent ?? TabBarExtraContentRight ?? Card?.Extra)
-				</div>
-			}
-		</div>
-		<!--Tab content-->
-		@if (Card == null)
-		{
-			<div class="ant-tabs-content-holder ">
-				<div class="@_contentClassMapper.Class">
-					<CascadingValue Value="true" Name="IsPane" IsFixed="true">
-						@ChildContent
-					</CascadingValue>
-				</div>
-			</div>
-		}
-	</div>
-</CascadingValue>
\ No newline at end of file
+@code {
+    internal void RenderTabs(RenderTreeBuilder __builder)
+    {
+        <div class="@ClassMapper.Class" style="@Style" id="@Id">
+            <!--Tab bar-->
+            <div role="tablist" class="@_tabBarClassMapper.Class" style="@TabBarStyle">
+
+                @if (TabBarExtraContentLeft != null)
+                {
+                    <div class="ant-tabs-extra-content">
+                        @TabBarExtraContentLeft
+                    </div>
+                }
+
+                <div class="@_tabsNavWarpPingClassMapper.Class" @ref="@_navWarpRef" id="@(Id)-nav-warpper">
+                    <div class="ant-tabs-nav-list" style="@_navListStyle" @ref="@_navListRef" id="@(Id)-nav-list">
+                        @foreach (var tab in _tabs.OrderBy(x => x.TabIndex))
+                        {
+                            @tab.RenderTab
+                        }
+                        @if (HasAddButton)
+                        {
+                            <button type="button" class="ant-tabs-nav-add" aria-label="Add tab" @onclick="OnAddClick">
+                                <Icon Type="plus" />
+                            </button>
+                        }
+                        <div class="@_inkClassMapper.Class" style="@_inkStyle"></div>
+                    </div>
+                </div>
+                <Dropdown OnVisibleChange="OnVisibleChange">
+                    <Overlay>
+                        <ul tabindex="0" class="ant-tabs-dropdown-menu ant-tabs-dropdown-menu-root ant-tabs-dropdown-menu-vertical" id="@($"rc-tabs-{Id}-more-popup")" role="listbox" aria-label="expanded dropdown">
+                            @foreach (var pane in _invisibleTabs)
+                            {
+                                <li class="ant-tabs-dropdown-menu-item @(pane.Disabled?$"ant-tabs-dropdown-menu-item-disabled":string.Empty)" id="@($"rc-tabs-{Id}-more-popup-{pane.Key}")" role="option" aria-disabled="false" aria-selected="false" aria-controls="@($"rc-tabs-{Id}-more-popup-{pane.Key}")"
+                                    @onclick="(e)=>HandleTabClick(pane)">
+                                    @if (pane.TabTemplate != null)
+                                    {
+                                        @pane.TabTemplate
+                                    }
+                                    else
+                                    {
+                                        @pane.Tab
+                                    }
+                                </li>
+                            }
+                        </ul>
+                    </Overlay>
+                    <Unbound>
+                        <div @ref="context.Current" class="@_operationClass" @onclick:preventDefault>
+                            <button tabindex="-1" class="ant-tabs-nav-more" id="rc-tabs-0-more" aria-expanded="false" aria-haspopup="listbox" aria-hidden="true" aria-controls="rc-tabs-0-more-popup"
+                                    style="@_operationStyle" type="button">
+                                <Icon Type="ellipsis" />
+                            </button>
+                        </div>
+                    </Unbound>
+                </Dropdown>
+
+                @if (TabBarExtraContent != null || TabBarExtraContentRight != null || (Card?.Extra != null && Card?.Title == null && Card?.TitleTemplate == null))
+                {
+                    <div class="ant-tabs-extra-content">
+                        @(TabBarExtraContent ?? TabBarExtraContentRight ?? Card?.Extra)
+                    </div>
+                }
+            </div>
+            <!--Tab content-->
+            @if (Card == null)
+            {
+                <div class="ant-tabs-content-holder ">
+                    <div class="@_contentClassMapper.Class">
+                        @foreach (var pane in _tabs)
+                        {
+                            @pane.RenderPane
+                        }
+                    </div>
+                </div>
+            }
+        </div>
+
+    }
+}
\ No newline at end of file
diff --git a/components/tabs/Tabs.razor.cs b/components/tabs/Tabs.razor.cs
index 0c205881bf..a1788a32ab 100644
--- a/components/tabs/Tabs.razor.cs
+++ b/components/tabs/Tabs.razor.cs
@@ -213,7 +213,6 @@ public string ActiveKey
         private const string PrefixCls = "ant-tabs";
         private bool IsHorizontal => TabPosition.IsIn(TabPosition.Top, TabPosition.Bottom);
 
-        private TabPane _activePane;
         private TabPane _activeTab;
         private HtmlElement _activeTabElement;
         private Dictionary<string, HtmlElement> _itemRefs;
@@ -244,7 +243,6 @@ public string ActiveKey
         private readonly ClassMapper _tabsNavWarpPingClassMapper = new ClassMapper();
         private readonly ClassMapper _tabBarClassMapper = new ClassMapper();
 
-        private readonly List<TabPane> _panes = new List<TabPane>();
         private readonly List<TabPane> _tabs = new List<TabPane>();
         private List<TabPane> _invisibleTabs = new List<TabPane>();
 
@@ -298,15 +296,11 @@ protected override void OnInitialized()
             _tabBarClassMapper
                 .Add($"{PrefixCls}-nav")
                 .If(TabBarClass, () => !string.IsNullOrWhiteSpace(TabBarClass));
-        }
 
-        protected override Task OnFirstAfterRenderAsync()
-        {
             if (Card is not null)
             {
-                this.Complete();
+                Card.SetTabs(RenderTabs);
             }
-            return base.OnFirstAfterRenderAsync();
         }
 
         /// <summary>
@@ -317,42 +311,15 @@ protected override Task OnFirstAfterRenderAsync()
         /// <exception cref="ArgumentException">An AntTabPane with the same key already exists</exception>
         internal void AddTabPane(TabPane tabPane)
         {
-            if (tabPane.IsTab)
-            {
-                _tabs.Add(tabPane);
-                if (Card is not null)
-                {
-                    _panes.Add(tabPane);
-                }
-            }
-            else
-            {
-                _panes.Add(tabPane);
-            }
-
-            if (string.IsNullOrWhiteSpace(tabPane.Key))
-            {
-                if (tabPane.IsTab)
-                {
-                    tabPane.SetKey($"ant-tabs-{_tabs.Count}");
-                }
-                else
-                {
-                    tabPane.SetKey(_tabs[_panes.Count - 1].Key);
-                }
-            }
-
-            if (_tabs.Count == _panes.Count && Card is null)
-            {
-                this.Complete();
-            }
+            tabPane.SetIndex(_tabs.Count);
+            _tabs.Add(tabPane);
         }
 
         internal void Complete()
         {
             if (!string.IsNullOrWhiteSpace(ActiveKey))
             {
-                var activedPane = _panes.Find(x => x.Key == ActiveKey);
+                var activedPane = _tabs.Find(x => x.Key == ActiveKey);
                 if (activedPane?.IsActive == false)
                 {
                     ActivatePane(activedPane.Key);
@@ -360,16 +327,16 @@ internal void Complete()
             }
             else if (!string.IsNullOrWhiteSpace(DefaultActiveKey))
             {
-                var defaultPane = _panes.FirstOrDefault(x => x.Key == DefaultActiveKey);
+                var defaultPane = _tabs.FirstOrDefault(x => x.Key == DefaultActiveKey);
                 if (defaultPane != null)
                 {
                     ActivatePane(defaultPane.Key);
                 }
             }
 
-            if (_activePane == null || _panes.All(x => !x.IsActive))
+            if (_activeTab == null || _tabs.All(x => !x.IsActive))
             {
-                ActivatePane(_panes.FirstOrDefault()?.Key);
+                ActivatePane(_tabs.FirstOrDefault()?.Key);
             }
 
             if (AfterTabCreated.HasDelegate)
@@ -377,7 +344,8 @@ internal void Complete()
                 AfterTabCreated.InvokeAsync(_activeKey);
             }
 
-            _needUpdateScrollListPosition = true;
+            // Only update scroll list position once the tabs have not been rendered
+            _needUpdateScrollListPosition = !_afterFirstRender;
         }
 
         public async Task RemoveTab(TabPane tab)
@@ -386,10 +354,8 @@ public async Task RemoveTab(TabPane tab)
             {
                 var tabKey = tab.Key;
                 var index = _tabs.IndexOf(tab);
-                var pane = _panes.Find(x => x.Key == tab.Key);
 
                 tab.Close();
-                pane.Close();
 
                 if (OnClose.HasDelegate)
                 {
@@ -404,22 +370,7 @@ internal void RemovePane(TabPane tab)
             if (IsDisposed)
                 return;
 
-            if (tab.IsTab)
-            {
-                var index = _tabs.IndexOf(tab);
-
-                _tabs.Remove(tab);
-
-                if (tab.IsActive && _tabs.Count > 0)
-                {
-                    var p = index > 1 ? _tabs[index - 1] : _tabs[0];
-                    ActivatePane(p.Key);
-                }
-            }
-            else
-            {
-                _panes.Remove(tab);
-            }
+            _tabs.Remove(tab);
 
             _needUpdateScrollListPosition = true;
         }
@@ -459,35 +410,31 @@ private async Task NavigateToTab(TabPane tabPane)
 
         private void ActivatePane(string key)
         {
-            if (_panes.Count == 0)
+            if (_tabs.Count == 0)
                 return;
 
             var tabIndex = _tabs.FindIndex(p => p.Key == key);
             var tab = _tabs.Find(p => p.Key == key);
-            var tabPane = _panes.Find(p => p.Key == key);
 
-            if (tab == null || tabPane == null)
+            if (tab == null)
                 return;
 
             // Even if a TabPane is disabled, it is allowed to be activated at initial load time (at initial load time, _activeTab is null)
             // fixed https://github.com/ant-design-blazor/ant-design-blazor/issues/2732
-            if (_activeTab != null && tabPane.Disabled)
+            if (_activeTab != null && tab.Disabled)
             {
                 return;
             }
 
-            _activePane?.SetActive(false);
             _activeTab?.SetActive(false);
 
             tab.SetActive(true);
-            tabPane.SetActive(true);
 
             _activeTab = tab;
-            _activePane = tabPane;
 
-            if (_activeKey != _activePane.Key)
+            if (_activeKey != _activeTab.Key)
             {
-                _activeKey = _activePane.Key;
+                _activeKey = _activeTab.Key;
                 if (ActiveKeyChanged.HasDelegate)
                 {
                     ActiveKeyChanged.InvokeAsync(_activeKey);
@@ -495,11 +442,24 @@ private void ActivatePane(string key)
             }
             if (OnChange.HasDelegate)
             {
-                OnChange.InvokeAsync(_activePane.Key);
+                OnChange.InvokeAsync(_activeTab.Key);
             }
             TryRenderInk();
 
-            Card?.SetBody(_activePane.ChildContent);
+            Card?.SetBody(_activeTab.ChildContent);
+
+            // render the classname of the actived tab
+            // Needs to be optimized to render only one tab instead all the tabs
+            StateHasChanged();
+        }
+
+        public override Task SetParametersAsync(ParameterView parameters)
+        {
+            if (parameters.IsParameterChanged(nameof(TabPosition), TabPosition))
+            {
+                _needUpdateScrollListPosition = true;
+            }
+            return base.SetParametersAsync(parameters);
         }
 
         protected override async Task OnAfterRenderAsync(bool firstRender)
@@ -527,6 +487,11 @@ protected override void OnParametersSet()
             _shouldRender = true;
         }
 
+        protected override bool ShouldRender()
+        {
+            return _shouldRender || _renderedActivePane != _activeTab;
+        }
+
         private async Task ResetSizes()
         {
             ElementReference[] refs = [_navListRef, _navWarpRef, .. _tabs.Select(x => x.TabRef).ToArray()];
@@ -601,7 +566,7 @@ private void OnWheel(string json)
             SetNavListStyle();
 
             StateHasChanged();
-            _renderedActivePane = _activePane;
+            _renderedActivePane = _activeTab;
         }
 
         private void SetNavListStyle()
@@ -625,23 +590,28 @@ private void SetNavListStyle()
 
         private void TryRenderInk()
         {
-            if (!_afterFirstRender)
+            if (_itemRefs is not { Count: > 0 })
             {
-                _needUpdateScrollListPosition = true;
-                StateHasChanged();
                 return;
             }
-
-            if (_itemRefs is not { Count: > 0 })
+            if (!_itemRefs.TryGetValue(_activeTab.TabId, out _activeTabElement))
             {
                 return;
             }
-            if (!_itemRefs.TryGetValue(_activeTab.TabId, out _activeTabElement))
+
+            // the tabs maybe inside other components like modal, it can't get the element info at the first time
+            // so here is retrying to get the element info again.
+            // Fixed https://github.com/ant-design-blazor/ant-design-blazor/issues/4061
+            if (_activeTabElement.ClientWidth <= 0 || _activeTabElement.ClientHeight <= 0)
             {
+                _needUpdateScrollListPosition = true;
+                StateHasChanged();
                 return;
             }
+
             if (IsHorizontal)
             {
+
                 _inkStyle = $"left: {_activeTabElement.OffsetLeft}px; width: {_activeTabElement.ClientWidth}px";
 
                 var additionalWidth = HasAddButton ? _addBtnWidth : 0;
@@ -677,14 +647,16 @@ private void TryRenderInk()
                 }
             }
 
-            _shouldRender = true;
-            StateHasChanged();
-            _renderedActivePane = _activePane;
-        }
-
-        protected override bool ShouldRender()
-        {
-            return _shouldRender || _renderedActivePane != _activePane;
+            if (Card is not null)
+            {
+                Card.InvokeStateHasChagned();
+            }
+            else
+            {
+                _shouldRender = true;
+                StateHasChanged();
+            }
+            _renderedActivePane = _activeTab;
         }
 
         internal void UpdateTabsPosition()
@@ -773,6 +745,7 @@ internal void HandleDrop(TabPane tab)
                 _draggingTab = null;
                 _shouldRender = true;
                 _renderedActivePane = null;
+                _needUpdateScrollListPosition = true;
 
                 ActivatePane(_activeKey);
             }
@@ -784,7 +757,6 @@ protected override void Dispose(bool disposing)
         {
             DomEventListener.DisposeExclusive();
 
-            _panes.Clear();
             _tabs.Clear();
             _invisibleTabs.Clear();
 
diff --git a/site/AntDesign.Docs/Demos/Components/Card/demo/Tabs1.razor b/site/AntDesign.Docs/Demos/Components/Card/demo/Tabs1.razor
index 5fe6c67ce6..29644268b8 100644
--- a/site/AntDesign.Docs/Demos/Components/Card/demo/Tabs1.razor
+++ b/site/AntDesign.Docs/Demos/Components/Card/demo/Tabs1.razor
@@ -3,7 +3,7 @@
         <Extra>
             <a>More</a>
         </Extra>
-        <CardTabs>
+        <ChildContent>
             <Tabs DefaultActiveKey="1">
                 <TabPane Key="1">
                     <TabTemplate>Tab 1</TabTemplate>
@@ -18,7 +18,7 @@
                     <ChildContent>Content of Tab Pane 3</ChildContent>
                 </TabPane>
             </Tabs>
-        </CardTabs>
+        </ChildContent>
     </Card>
     <br />
     <br />
@@ -26,24 +26,22 @@
         <Extra>
             <a>More</a>
         </Extra>
-        <CardTabs>
+        <ChildContent>
             <Tabs DefaultActiveKey="1">
-                <ChildContent>
-                    <TabPane Key="1">
-                        <TabTemplate>Article</TabTemplate>
-                        <ChildContent>Content of Tab Pane 1</ChildContent>
-                    </TabPane>
-                    <TabPane Key="2">
-                        <TabTemplate>App</TabTemplate>
-                        <ChildContent>Content of Tab Pane 2</ChildContent>
-                    </TabPane>
-                    <TabPane Key="3">
-                        <TabTemplate>Project</TabTemplate>
-                        <ChildContent>Content of Tab Pane 3</ChildContent>
-                    </TabPane>
-                </ChildContent>
+                <TabPane Key="1">
+                    <TabTemplate>Article</TabTemplate>
+                    <ChildContent>Content of Tab Pane 1</ChildContent>
+                </TabPane>
+                <TabPane Key="2">
+                    <TabTemplate>App</TabTemplate>
+                    <ChildContent>Content of Tab Pane 2</ChildContent>
+                </TabPane>
+                <TabPane Key="3">
+                    <TabTemplate>Project</TabTemplate>
+                    <ChildContent>Content of Tab Pane 3</ChildContent>
+                </TabPane>
             </Tabs>
-        </CardTabs>
+        </ChildContent>
     </Card>
 </div>
 


Test patch:
diff --git a/tests/AntDesign.Tests/Card/Card.Render.Tests.razor b/tests/AntDesign.Tests/Card/Card.Render.Tests.razor
index 2bdd0e7d2c..6cae955159 100644
--- a/tests/AntDesign.Tests/Card/Card.Render.Tests.razor
+++ b/tests/AntDesign.Tests/Card/Card.Render.Tests.razor
@@ -34,18 +34,16 @@
         JSInterop.Setup<Dictionary<string, HtmlElement>>("AntDesign.interop.domInfoHelper.getElementsInfo", _ => true);
         var cut = Render<AntDesign.Card>(
             @<Card Title=@("Card title")>        
-                <CardTabs>
-                    <Tabs DefaultActiveKey="1">
-                        <TabPane Key="1">
-                            <TabTemplate>Tab 1</TabTemplate>
-                            <ChildContent>Content of Tab Pane 1</ChildContent>
-                        </TabPane>
-                        <TabPane Key="2">
-                            <TabTemplate>Tab 2</TabTemplate>
-                            <ChildContent>Content of Tab Pane 2</ChildContent>
-                        </TabPane>
-                    </Tabs>
-                </CardTabs>
+                <Tabs DefaultActiveKey="1">
+                    <TabPane Key="1">
+                        <TabTemplate>Tab 1</TabTemplate>
+                        <ChildContent>Content of Tab Pane 1</ChildContent>
+                    </TabPane>
+                    <TabPane Key="2">
+                        <TabTemplate>Tab 2</TabTemplate>
+                        <ChildContent>Content of Tab Pane 2</ChildContent>
+                    </TabPane>
+                </Tabs>
             </Card>
     );
         //Act
@@ -95,21 +93,19 @@
         JSInterop.Setup<HtmlElement>(JSInteropConstants.DomInfoHelper.GetInfo, _ => true).SetResult(new());
         JSInterop.Setup<Dictionary<string, HtmlElement>>("AntDesign.interop.domInfoHelper.getElementsInfo", _ => true);
         var cut = Render<AntDesign.Card>(
-            @<Card Title=@("Card title")>        
-                <CardTabs>
-                    <Tabs DefaultActiveKey="1">
-                        <TabPane Key="1">
-                            <TabTemplate>Tab 1</TabTemplate>
-                            <ChildContent>Content of Tab Pane 1</ChildContent>
-                        </TabPane>
-                        <TabPane Key="2">
-                            <TabTemplate>Tab 2</TabTemplate>
-                            <ChildContent>Content of Tab Pane 2</ChildContent>
-                        </TabPane>
-                    </Tabs>
-                </CardTabs>
-    </Card>
-    );
+            @<Card Title=@("Card title")>
+                <Tabs DefaultActiveKey="1">
+                    <TabPane Key="1">
+                        <TabTemplate>Tab 1</TabTemplate>
+                        <ChildContent>Content of Tab Pane 1</ChildContent>
+                    </TabPane>
+                    <TabPane Key="2">
+                        <TabTemplate>Tab 2</TabTemplate>
+                        <ChildContent>Content of Tab Pane 2</ChildContent>
+                    </TabPane>
+                </Tabs>
+            </Card>
+        );
         //Act
         var tab2 = cut.FindAll("div.ant-tabs-tab")[1];
         tab2.Click();
diff --git a/tests/AntDesign.Tests/tabs/TabsTests.cs b/tests/AntDesign.Tests/tabs/TabsTests.cs
index 666ac7cbb0..099ca63f69 100644
--- a/tests/AntDesign.Tests/tabs/TabsTests.cs
+++ b/tests/AntDesign.Tests/tabs/TabsTests.cs
@@ -25,9 +25,9 @@ public partial class TabsTests : AntDesignTestBase
             jsRuntime.Setup(u => u.InvokeAsync<Dictionary<string, HtmlElement>>(JSInteropConstants.GetElementsDomInfo, It.IsAny<object[]>()))
                 .ReturnsAsync(new Dictionary<string, HtmlElement>()
                 {
-                    ["1-nav-list"] = new HtmlElement() { },
-                    ["1-nav-warpper"] = new HtmlElement() { },
-                    ["rc-tabs-2-tab-2"] = new HtmlElement() { },
+                    ["1-nav-list"] = new HtmlElement() { ClientWidth = 45, ClientHeight = 45, },
+                    ["1-nav-warpper"] = new HtmlElement() { ClientWidth = 45, ClientHeight = 45, },
+                    ["rc-tabs-2-tab-2"] = new HtmlElement() { ClientWidth = 45, ClientHeight = 45, },
                 });
 
             Context.Services.AddScoped(_ => jsRuntime.Object);