Skip to content

Mobile Layout

NPM Version

To further reduce development costs, we have built-in layout functionality through WinJS plugins. With simple configuration, you can have a complete layout including common mobile H5 elements: top title bar, middle content area, and bottom tab bar. This allows users to focus on business logic without worrying about layout implementation.

Note

This solution is only compatible with Vue 3. Since it depends on some Vant components at the underlying level, you need to install Vant when using this plugin.

Setup

  1. Install the plugin
bash
$ npm add @winner-fed/plugin-mobile-layout -D
bash
$ yarn add @winner-fed/plugin-mobile-layout -D
bash
$ pnpm add @winner-fed/plugin-mobile-layout -D
bash
$ bun add @winner-fed/plugin-mobile-layout -D
  1. Add dependency in package.json
json
{
  "dependencies": {
    "vant": "^4.6.5"
  }
}
  1. Enable the plugin in the .winrc configuration file
ts
import { defineConfig } from 'win';

export default defineConfig({
  plugins: [require.resolve('@winner-fed/plugin-mobile-layout')],
  /**
   * @name mobileLayout plugin
   * @doc https://winjs-dev.github.io/winjs-docs/plugins/mobilelayout.html
   */
  mobileLayout: {}
});

Configuration

Runtime Configuration

You can configure the bottom navigation tab bar, default title for all pages, page titles, and page header navigation bar in src/app.(j|t)[s]x.

By exporting the mobileLayout object, it will be passed as configuration to the WinJS mobile layout component. As shown below:

ts
// app.ts
export const mobileLayout = {
  tabBar,
  navBar,
  documentTitle: 'demo',
  titleList
};
PropertyTypeRequiredDescription
tabBarTabBarPropsNoDefine bottom navigation tab bar
navBar_NavBarPropsNoDefine page header navigation bar
documentTitlestringNoDefine default title for all pages
titleListTitleListItem[]NoDefine page titles

Define Bottom Navigation Tab Bar

The TabBarProps type for tabBar is defined as follows:

PropertyTypeRequiredDescription
colorstringYesDefault text color of navigation tabs
selectedColorstringYesText color of navigation tabs when selected
backgroundColorstringYesBackground color of navigation tabs
tabBarItemTabBarItem[]YesList of navigation tabs
tabBeforeChange(navigator: any, name: number | string) => void | Promise<boolean>NoCallback before tab switch, return false to prevent switch, supports Promise
tabChange(navigator: any, name: number | string) => voidNoTriggered when tab is switched

The TabBarItem type for tabBar.tabBarItem is defined as follows:

PropertyTypeRequiredDescription
pagePathstringYesPage path, must be defined in pages first
textstringNoText of navigation tab
iconPathstringNoIcon path of navigation tab
selectedIconPathstringNoIcon path when navigation tab is selected
dotbooleanNoWhether to show red dot on top-right of icon, default false
badgestringNoNumber displayed on top-right of navigation tab icon (badge)
onPress(navigator: any, data?: TabBarItem) => void | Promise<boolean>NoNavigation tab click callback
titlestringNoPage title
iconobject | stringNoCustom navigation tab
selectedIconobject | stringNoCustom selected navigation tab

Define Page Header Navigation Bar

The NavBarProps type for navBar is defined as follows:

PropertyDescriptionTypeDefault
modeStyle modestring'dark' 'dark', 'light'
iconIcon in the left return area of header navigationobject | stringPages not defined in tabsBar will have default left return icon
leftContentContent on the right side of left return areaanyNone
rightContentRight content of header navigationanyNone
leftTextLeft return text of header navigationstringNone
onLeftClickClick callback for left return area(navigator) => voidDefault event with left return icon is to go back to previous page
hideNavBarHide NavBar, NavBar is shown by defaultbooleanfalse
pageTitlePage titlestringNone, highest priority
navListSet navbar for specific pages separatelyNarBarListItemNone

The NavBarListItem type for navList is defined as follows:

PropertyTypeDefaultDescription
pagePathstringNonePage path, must be defined in pages first
navBarNavBarPropsNoneNavBar for current route

Define Page Titles

The TitleListItem[] type for titleList is defined as follows:

PropertyTypeRequiredDescription
pagePathstringYesPage path, must be defined in pages first
titlestringNoPage title

Define Default Title for All Pages

ts
export const mobileLayout = {
  documentTitle: 'Default Title',
};

Page Title Setting Priority

titleList's title > tabBar's list's title > documentTitle.

Complete Example

Here's an example:

ts
// Custom TabarIcon
import TabbarIcon from '@/components/TabbarIcon';

import type {
  NavBarListItem,
  NavBarProps,
  TabBarItem,
  TabBarProps,
  TitleListItem,
  MobileLayoutProps
} from 'winjs';

const titleList: TitleListItem[] = [
  {
    pagePath: '/',
    title: 'Registration',
  },
  {
    pagePath: '/signIn',
    title: 'Sign In',
  },
  {
    pagePath: '/query',
    title: 'Query',
  },
  {
    pagePath: '/other',
    title: 'Other',
  },
];

const navList: NavBarListItem = [
  {
    pagePath: '/',
    navBar: {},
  },
  {
    pagePath: '/signIn',
    navBar: {},
  },
  {
    pagePath: '/query',
    navBar: {},
  },
  {
    pagePath: '/other',
    navBar: {},
  },
]
const navBar: NavBarProps = {
  navList,
  fixed: true,
  mode: 'light',
  hideNavBar: true
};

const tabList: TabBarItem[] = [
  {
    pagePath: '/',
    text: 'Registration',
    icon: <TabbarIcon icon - name = "icon-sign-up" / >,
    selectedIcon: <TabbarIcon icon - name = "icon-sign-up" / >,
    title: 'Registration',
  },
  {
    pagePath: '/signIn',
    text: 'Sign In',
    icon: <TabbarIcon icon - name = "icon-sign-in" / >,
    selectedIcon: <TabbarIcon icon - name = "icon-sign-in" / >,
    title: 'Sign In'
  },
  {
    pagePath: '/query',
    text: 'Query',
    icon: <TabbarIcon icon - name = "icon-query" / >,
    selectedIcon: <TabbarIcon icon - name = "icon-query" / >,
    title: 'Query'
  },
  {
    pagePath: '/other',
    text: 'Other',
    icon: <TabbarIcon icon - name = "icon-other" / >,
    selectedIcon: <TabbarIcon icon - name = "icon-other" / >,
    title: 'Other'
  },
];
const tabBar: TabBarProps = {
  color: `#929292`,
  selectedColor: '#00b38a',
  tabBarItem: tabList,
};

export const mobileLayout: MobileLayoutProps = {
  theme: 'light',
  documentTitle: 'Demo',
  navBar,
  titleList,
  tabBar,
};
vue
<!--TabbarIcon.vue-->
<script setup lang="ts">
defineProps({
  iconName: {
    type: String,
    required: true
  }
});

</script>

<template>
  <i class="icon" :class="iconName"></i>
</template>

Detailed property configuration description:

ts
export interface TitleListItem {
  // Page route
  pagePath: string;
  // Title
  title: string;
}

export interface TabBarItem {
  pagePath: string;
  // Tab bar bottom text
  text?: string;
  iconPath?: string;
  selectedIconPath?: string;
  // Whether to show red dot on top-right of icon
  dot?: boolean;
  // Content of badge on top-right of icon
  badge?: number | string;
  title?: string;
  icon?: string;
  selectedIcon?: string;
  onPress?: (navigator: any, data?: TabBarItem) => void | Promise<boolean>;
}

export interface TabBarProps {
  // Whether to fix at bottom
  fixed?: boolean;
  // Color of unselected tabs
  color?: string;
  // Color of selected tabs
  selectedColor?: string;
  tabBarItem?: TabBarItem[];
  // Callback before tab switch, return false to prevent switch, supports Promise
  tabBeforeChange?: (
    navigator: any,
    name: number | string,
  ) => void | Promise<boolean>;
  tabChange?: (navigator: any, name: number | string) => void;
}

export interface _NavBarProps {
  mode?: 'dark' | 'light';
  icon?: object | string;
  leftText?: string;
  leftContent?: any;
  rightContent?: any;
  onLeftClick?: (navigator: any) => void;
  hideNavBar?: boolean;
  pageTitle?: string;
}

export interface NavBarListItem {
  pagePath: string;
  navBar?: _NavBarProps;
}

export interface NavBarProps extends _NavBarProps {
  fixed?: boolean;
  navList?: NavBarListItem[];
}

export interface TitleItems {
  pagePath: string;
  title?: string;
}

export interface MobileLayoutProps {
  theme?: 'dark' | 'light';
  tabBar?: TabBarProps;
  navBar?: NavBarProps;
  documentTitle?: string;
  titleList?: TitleItems[];
}

Released under the MIT License.