Rail

This composable offers a very handy way to show and control complex navigation in real-world apps.

Learn more about t-rail.

Get started

In your template, add a t-rail component without children. Then, use createRail to create an instance of use-rail in this context or anywhere in a parent context.

import { TRail } from "@dija/tohama-components";
import { createRail } from "@dija/tohama-use";

defineComponent({
  setup() {
    createRail({
      active: "account",
      items: [
        {
          key: "home",
          label: "Home",
        },
        {
          key: "account",
          label: "Account",
        },
      ],
    });

    return () => <TRail />;
  },
});

Methods

You can also control the active item or change the items at anytime using the exposed methods and events.

import { TRail, TButton } from "@dija/tohama-components";
import { createRail } from "@dija/tohama-use";

defineComponent({
  setup() {
    const rail = createRail({
      active: "account",
      items: [
        {
          key: "home",
          label: "Home",
        },
        {
          key: "account",
          label: "Account",
        },
      ],
    });

    const update = () => {
      rail.select("home");
    };

    return () => (
      <TCell>
        <TRail />

        <TButton onClick={update}>Update</TButton>
      </TCell>
    );
  },
});

Typescript

This composable supports assigning a generic type to make adding and controlling items much easier and safer.

import { TRail, TButton } from "@dija/tohama-components";
import { createRail } from "@dija/tohama-use";

type Section = "home" | "account";

defineComponent({
  setup() {
    createRail<Section>({
      active: "settings", // throws an error
      items: [
        {
          key: "home",
          label: "Home",
        },
        {
          key: "settings", // throws an error
          label: "Settings",
        },
      ],
    });

    return () => <TRail />;
  },
});

Model Value

Instead of controlling t-rail manually, you can control it using model values for both the active item and the items list. You can also use a computed reference which will update t-rail automatically.

import { TRail, TButton } from "@dija/tohama-components";
import { createRail, TUseRailItem } from "@dija/tohama-use";

type Group = "family" | "friends";

defineComponent({
  setup() {
    const active = ref<Group>();
    const items = ref<TUseRailItem<Group>[]>([
      {
        key: "family",
        label: "Family",
      },
    ]);

    createRail<Group>({
      active: active,
      items: items,
    });

    const updateActive = () => {
      active.value = "family";
    };
    const updateItems = () => {
      items.value = [
        {
          key: "friends",
          label: "Friends",
        },
      ];
    };

    return () => (
      <TCell>
        <TRail />

        <TButton onClick={updateActive}>Update Active</TButton>
        <TButton onClick={updateItems}>Update Items</TButton>
      </TCell>
    );
  },
});

Example

Active: messages-new


Model Value:


Programmatically:

import { TButton, TCard, TCell, TDivider, TFlex, TRail, TText } from "@dija/tohama-components";
import { createRail } from "@dija/tohama-use";

type Page =
  | "home"
  | "likes"
  | "featured"
  | "trends"
  | "account"
  | "messages"
  | "messages-new"
  | "messages-sent"
  | "posts"
  | "settings";

export default defineComponent({
  setup() {
    const active = ref<Page | undefined>("messages-new");

    const rail = createRail<Page>({
      active: active,
      onChange: (value) => {
        active.value = value;
      },
      items: [
        {
          key: "home",
          label: "Home",
          icon: "mdi:home",
          color: "success",
          items: [
            {
              key: "likes",
              label: "Likes",
            },
            {
              key: "featured",
              label: "Featured",
            },
            {
              key: "trends",
              label: "Trends",
            },
          ],
        },
        {
          key: "account",
          label: "Account",
          icon: "mdi:account",
          color: "info",
          items: [
            {
              key: "messages",
              label: "Messages",
              items: [
                {
                  key: "messages-new",
                  label: "Messages New",
                },
                {
                  key: "messages-sent",
                  label: "Messages Sent",
                },
              ],
            },
            {
              key: "posts",
              label: "Posts",
            },
          ],
        },
        {
          key: "settings",
          label: "Settings",
          icon: "mdi:cog",
          color: "danger",
        },
      ],
    });

    const readable = computed(() => {
      return `Active: ${active.value}`;
    });

    return () => (
      <TCell>
        <TCard design="outlined" mb p>
          <TRail push />
        </TCard>

        <TCard design="flat" p="md">
          <TText size="md" value={readable.value} />

          <TDivider my />

          <TText size="sm" mb="xs">
            Model Value:
          </TText>
          <TFlex>
            <TButton size="sm" onClick={() => (active.value = "home")} me="sm">
              Select home
            </TButton>
            <TButton size="sm" onClick={() => (active.value = "featured")} me="sm">
              Select featured
            </TButton>
            <TButton size="sm" onClick={() => (active.value = "posts")} me="sm">
              Select posts
            </TButton>
            <TButton size="sm" onClick={() => (active.value = "messages-new")}>
              Select messages-new
            </TButton>
          </TFlex>

          <TDivider my />

          <TText size="sm" mb="xs">
            Programmatically:
          </TText>
          <TFlex>
            <TButton size="sm" onClick={() => rail.select("home")} me="sm">
              Select home
            </TButton>
            <TButton size="sm" onClick={() => rail.select("featured")} me="sm">
              Select featured
            </TButton>
            <TButton size="sm" onClick={() => rail.select("posts")} me="sm">
              Select posts
            </TButton>
            <TButton size="sm" onClick={() => rail.select("messages-new")}>
              Select messages-new
            </TButton>
          </TFlex>
        </TCard>
      </TCell>
    );
  },
});