Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tabs works weird #88

Closed
dancixx opened this issue Jan 19, 2024 · 13 comments
Closed

Tabs works weird #88

dancixx opened this issue Jan 19, 2024 · 13 comments

Comments

@dancixx
Copy link

dancixx commented Jan 19, 2024

Hi there. I tried to use the Tabs component that way, but it seems the Tab content is stacking over each other as you can see in the picture below.
Képernyőfotó 2024-01-19 - 16 33 05

The tabs header works properly, but when I try to add more tabs dynamically, this vertical stacking occurs. Im attaching the code below. Thanks for your help.

use leptos::{html::*, *};
use thaw::{Tab, TabProps, Tabs, TabsProps};

use crate::{
  footer, query_editor, query_table, sidebar,
  store::{self, editor::EditorStore},
};

pub fn component() -> impl IntoView {
  let tabs = use_context::<store::tabs::Tabs>().unwrap();
  let mut editors = use_context::<EditorStore>().unwrap();

  div()
    .classes("flex h-screen")
    .child(sidebar::index::component())
    .child(
      div()
        .classes("flex flex-col flex-1 overflow-hidden")
        .child(
          main()
            .classes("flex-1 overflow-y-scroll")
            .child(Tabs(TabsProps {
              value: tabs.selected_tab,
              class: MaybeSignal::Static(String::from("flex flex-col")),
              children: Children::to_children(move || {
                Fragment::new(vec![
                  For(ForProps {
                    each: move || (0..tabs.active_tabs.get()),
                    key: |index| index.to_string(),
                    children: move |index| {
                      Tab(TabProps {
                        key: index.to_string(),
                        label: (index + 1).to_string(),
                        class: MaybeSignal::Static(String::from("flex flex-col")),
                        children: Children::to_children(move || {
                          Fragment::new(vec![div()
                            // .child(query_editor::component(index))
                            // .child(query_table::component())
                            .into_view()])
                        }),
                      })
                    },
                  })
                  .into_view(),
                  button()
                    .on(ev::click, move |_| {
                      tabs.active_tabs.update(|prev| *prev += 1);
                      tabs
                        .selected_tab
                        .update(|prev| *prev = (prev.parse::<usize>().unwrap() + 1).to_string());
                      editors.add_editor();
                    })
                    .child("+")
                    .into_view(),
                ])
              }),
            })),
        )
        .child(footer::component()),
    )
}
@luoxiaozero
Copy link
Collaborator

I'm not sure I know what you mean. Can you write a minimal demo?

@dancixx
Copy link
Author

dancixx commented Jan 19, 2024

@luoxiaozero As initially I have one active tab, but there could be more. So if I increase the number of the tabs the tabs header renders properly but the content stacks over each other as you can see in the picture:

Tab header like this:
Tab 1, Tab2, Tab3, .... TabN

Tab Content:
Tab1Content
Tab2Content
....
TabNContet.

So for some reason, the tab contents are always visible despite which tab is active.

@luoxiaozero
Copy link
Collaborator

Sorry, I can't match your description with the picture, can you provide a minimum demo code?

I tried the following code with no problem.

let value = create_rw_signal(String::from("apple"));
let active_tabs = create_rw_signal(2);

view! {
    <Tabs value>
        <For each=move || (0..active_tabs.get()) key=|index| index.to_string() let:index>
            <Tab key=index.to_string() label=(index + 1).to_string()>
                "index:" {index}
            </Tab>
        </For>
    </Tabs>
    <Button on_click=move |_| active_tabs.update(|p| *p += 1)>"+1"</Button>
}

@dancixx dancixx closed this as completed Jan 20, 2024
@dancixx dancixx reopened this Jan 20, 2024
@dancixx
Copy link
Author

dancixx commented Jan 21, 2024

@luoxiaozero

"index:" {index}

This is the equivalent of using this API and the result you can see below in the picture, if I'm creating multiple tabs the latest tab will contain all the prev tabs' content. So in Tab3 you can see Tab1-2-3, in Tab2 you can see Tab1-2, etc...
Képernyőfotó 2024-01-21 - 1 10 10
Képernyőfotó 2024-01-21 - 1 10 27

Tabs(TabsProps {
              value: tabs.selected_tab,
              class: MaybeSignal::Static(String::new()),
              children: Children::to_children(move || {
                Fragment::new(vec![
                  For(ForProps {
                    each: move || (0..tabs.active_tabs.get()),
                    key: |index| index.to_string(),
                    children: move |index| {
                      Tab(TabProps {
                        class: MaybeSignal::Static(String::new()),
                        key: index.to_string(),
                        label: (index + 1).to_string(),
                        children: Children::to_children(move || {
                          Fragment::new(vec![
                            query_editor::component().into_view(),
                            query_table::component().into_view(),
                          ])
                        }),
                      })
                    },
                  })
                  .into_view(),
                  button()
                    .on(ev::click, move |_| {
                      editors.add_editor();
                      tabs.active_tabs.update(|prev| *prev += 1);
                      tabs
                        .selected_tab
                        .update(|prev| *prev = (tabs.active_tabs.get() - 1).to_string());
                    })
                    .child("+")
                    .into_view(),
                ])
              })

@luoxiaozero
Copy link
Collaborator

The problem seems to be related to the For component. You can modify it as follows.

Tabs(TabsProps {
              value: tabs.selected_tab,
              class: MaybeSignal::Static(String::new()),
              children: Children::to_children(move || {
                Fragment::new(vec![
                  For(ForProps {
                    each: move || (0..tabs.active_tabs.get()),
                    key: |index| index.to_string(),
                    children: move |index| {
+                    Fragment::new(vec![
                      Tab(TabProps {
                        class: MaybeSignal::Static(String::new()),
                        key: index.to_string(),
                        label: (index + 1).to_string(),
                        children: Children::to_children(move || {
                          Fragment::new(vec![
                            query_editor::component().into_view(),
                            query_table::component().into_view(),
                          ])
                        }),
                      })
+                    .into_view()])
                    },
                  })
                  .into_view(),
                  button()
                    .on(ev::click, move |_| {
                      editors.add_editor();
                      tabs.active_tabs.update(|prev| *prev += 1);
                      tabs
                        .selected_tab
                        .update(|prev| *prev = (tabs.active_tabs.get() - 1).to_string());
                    })
                    .child("+")
                    .into_view(),
                ])
              })

@dancixx
Copy link
Author

dancixx commented Jan 21, 2024

@luoxiaozero Thanks a lot, this is working. Can you briefly explain why I have to use Fragment in this case? I have used multiple times the For components but it worked without fragment.

@luoxiaozero
Copy link
Collaborator

I don't know. The reason for the problem is not easy to find.

@dancixx
Copy link
Author

dancixx commented Jan 22, 2024

@luoxiaozero and one more question. Maybe possible to add support for custom nodes for tabs?

@luoxiaozero
Copy link
Collaborator

@dancixx
Copy link
Author

dancixx commented Jan 23, 2024

@luoxiaozero yes, because I would add a close button to the tabs for example.

@luoxiaozero
Copy link
Collaborator

If you just want to add a close button, I can implement it like this https://www.naiveui.com/en-US/light/components/tabs#addable.vue (Do you have any style requirements?)

@dancixx
Copy link
Author

dancixx commented Jan 23, 2024

@luoxiaozero i think the most general case would be if the tabs header can accept a totally customized children, styled nodes with custom logic.

@luoxiaozero
Copy link
Collaborator

Hi, I added this feature in #91 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants