Nesse artigo veremos como criar um componente de Tabs com o Blazor. Para melhor entender esse artigo, sugiro que você dê uma olhada nos seguintes Tópicos:
Plano
A ideia é implementarmos a funcionalidade de Tabs com o Blazor. Ou seja, criar um componente que nos permita apresentar conteúdo separado por Tabs (ou Abas).
Na verdade, para alcançar esse objetivo precisaremos criar dois componentes, e não apenas um. Criaremos um componente chamado TabSet.razor, que representará um determinado conjunto de Tabs. E para representar uma Tab dentro do TabSet, vamos criar o componente Tab.razor.
Sendo assim, o componente TabeSet deverá permitir que adicionemos ao seu conteúdo, vários componentes Tab.
Dois conceitos são importantes para alcançarmos esse objetivo. Primeiramente você precisa conhecer o recurso ChildContent, que será utilizado nos dois componentes que serão criados.
E em segundo lugar, você precisa entender como funciona o CascadingValue e o CascadingParameter. Esses elementos são utilizados quando precisamos passar valores de um componente Pai para um componente Filho. E nesse exemplo, como veremos adiante, teremos um cenário desse.
ITab
Para começar, precisamos definir uma interface para representar uma Tab. Essa interface será útil para escrevermos o comportamento das Tabs no componente TabSet.razor. Sendo assim, crie essa interface como nos mostra a Figura 1.

Veja que a interface define apenas a propriedade ChildContent, que o TabSet vai precisar para poder renderizar o conteúdo da Tab Selecionada.
TabSet
Agora que já temos uma representação para uma Tab com o ITab, vamos partir para a codificação do componente TabSet.razor. Comece importando o namespace onde você criou o ITab, como mostra a Figura 2.

Em seguida vamos partir para as propriedades que precisamos criar nesse componente. Veja na Figura 3 que precisamos de 2 propriedades.

Note que temos uma propriedade para representar o Parâmetro ChildContent, onde serão renderizados os títulos das Tabs. E uma outra propriedade chamada TabAtiva do tipo ITab.
Essa segunda propriedade servirá justamente para termos uma referência à Tab que for selecionada pelo usuário.
Com isso já podemos desenhar a interface HTML do componente TabSet. Veja como ele deve ser implementado na Figura 4.

Como você pode ver, estamos usando um CascadingValue para passar uma referência do TabSet, para todos as Tabs que forem inclusas nele. Isso é necessário para que um Tab possa “avisar” o TabSet quando ele for selecionado.
Veja também que dentro do CascadingValue vamosrenderizar o ChildContent do TabSet. O ChildContent do TabSet vai conter apenas os títulos das Tabs. Você verá isso mais claramente na implementação do Tab.
Já no corpo do TabSet iremos renderizar o ChildContent do componente Tab que estiver selecionado, representado aqui pela propriedade TabAtiva.
Para finalizar a implementação do TabSet, precisamos implementar os métodos que serão usados para definir qual é a Tab Selecionada. São dois métodos, que você poder ver na Figura 5.

Esses dois métodos serão utilizados pelas Tabs que forem adicionadas ao TabSet. O principal é o método SelecionaTab, que recebe a tab por parâmetro. Caso a tab não esteja ativa, o método atribui o parâmetro tab à propriedade TabAtiva.
O método StateHasChanged é necessário para que o conteúdo do componente Tab seja devidamente renderizado no corpo do TabSet.
Já o método AddTab serve apenas para definir qual será a Tab que inicialmente estará selecionada. Como você pode ver pela lógica do método, a primeira Tab adicionada ao TabSet será definida como TabAtiva.
Tab
Com o TabSet devidamente implementado, já podemos começar a codificar o componente Tab. Vamos começar importando o namespace do ITab, e definindo que o componente Tab implementa essa interface. Veja Figura 6.

Em seguida nós vamos definir os parâmetros e propriedades do Componente. Confira na Figura 7.

Temos dois parâmetros no componente Tab, o Título da Tab e o seu ChildContent. O ChildContent é o conteúdo da Tab e será renderizado pelo TabSet, quando a Tab estiver ativa.
A propriedade TabSet é do tipo CascadingParameter, e ela será atribuída por cascata pelo TabSet. Veja que usamos o TabSet na propriedade TituloCss, para definir se iremos renderizar a classe css active no título da Tab, indicando assim que ela está selecionada.
Veja na Figura 8 como fica o HTML desse componente.

Como você pode ver, o componente Tab renderiza apenas o seu título, e deixa para o TabSet a renderização do seu ChildContent. Como já foi dito, a propriedade TituloCss é usada para aplicar a css active quando a Tab for selecionada.
Note que o título é criado com um link através da tag <a />. E no evento onclick dessa tag estamos chamando o método Selecionar. Veja na Figura 9 a implementação deste e de outro método necessário no componente Tab.

O primeiro método da Figura 9 é o OnInit. Esse método é sobrecarregado da classe base do componente e é executado na sua inicialização. Aproveitamos esse método apara chamar o método AddTab do TabSet, e com isso, definir que a primeira Tab do TabSet iniciará como a TabAtiva.
Já o método Selecionar será executado pelo click no título da Tab, e irá chamar o método SelecionaTab do TabSet. Com isso você pode ver a importância da referência do TabSet passada por cascata do componente pai para os seus filhos.
Testando
Para testarmos o TabSet e o Tab, vamos incluir esses componentes no Index.razor do nosso projeto de exemplo.
Como você pode ver na Figura 10, devemos incluir a tag TabSet no HTML, e dentro dessa tag vamos adicionando os componentes Tab.

Foram inclusas três Tabs no TabSet. Cada Tab recebeu um Título e um Conteúdo (ChildContent). Para o conteúdo dos Tabs podemos incluir o HTML que quisermos, inclusive outros componentes da nossa aplicação, como você pode conferir no terceiro Tab.
Execute o seu projeto e veja o resultado do nosso TabSet, aqui na Figura 11.

Como você pode ver a nossa implementação de TabSet funciona perfeitamente. Veja que utilizamos os recursos de css do bootstrap para estilizar o nosso componente. Seguindo esse exemplo você pode implementar o seu componente de Tab com as funcionalidades que quiser.
Grande Abraço e até o próximo!