All Projects → moxystudio → Next Layout

moxystudio / Next Layout

Licence: mit
Add persistent and nested layouts to your Next.js projects in a declarative way

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Next Layout

React Page Layout
Create layouts for react
Stars: ✭ 117 (-2.5%)
Mutual labels:  layout, page
Flexlib
FlexLib是一个基于flexbox模型,使用xml文件进行界面布局的框架,融合了web快速布局的能力,让iOS界面开发像写网页一样简单快速
Stars: ✭ 1,569 (+1207.5%)
Mutual labels:  layout
Form
Form is an iOS Swift library for building and styling UIs
Stars: ✭ 99 (-17.5%)
Mutual labels:  layout
Hierarchy
Layout algorithms for visualizing hierarchical data.
Stars: ✭ 110 (-8.33%)
Mutual labels:  layout
Pdflayouttextstripper
Converts a pdf file into a text file while keeping the layout of the original pdf. Useful to extract the content from a table in a pdf file for instance. This is a subclass of PDFTextStripper class (from the Apache PDFBox library).
Stars: ✭ 1,369 (+1040.83%)
Mutual labels:  layout
Doormat
Let's take a scroll!
Stars: ✭ 111 (-7.5%)
Mutual labels:  layout
Flexlayout
FlexLayout adds a nice Swift interface to the highly optimized facebook/yoga flexbox implementation. Concise, intuitive & chainable syntax.
Stars: ✭ 1,342 (+1018.33%)
Mutual labels:  layout
Paging
js分页控件paging,jquery分页插件。
Stars: ✭ 108 (-10%)
Mutual labels:  page
Flutter layout grid
A grid-based layout system for Flutter, inspired by CSS Grid Layout
Stars: ✭ 109 (-9.17%)
Mutual labels:  layout
Column Setter
Custom responsive grids in Sass that work in older browsers.
Stars: ✭ 117 (-2.5%)
Mutual labels:  layout
Autoresponsive React
Auto Responsive Layout Library For React
Stars: ✭ 1,475 (+1129.17%)
Mutual labels:  layout
Mui Treasury
A collection of ready-to-use components based on Material-UI
Stars: ✭ 1,821 (+1417.5%)
Mutual labels:  layout
X6
🚀 JavaScript diagramming library that uses SVG and HTML for rendering.
Stars: ✭ 2,686 (+2138.33%)
Mutual labels:  layout
Muuri
Infinite responsive, sortable, filterable and draggable layouts
Stars: ✭ 9,797 (+8064.17%)
Mutual labels:  layout
Open React Template
A free React landing page template designed to showcase open source projects, SaaS products, online services, and more. Made by
Stars: ✭ 1,956 (+1530%)
Mutual labels:  page
Flowlayout
An Android Layout Manager to create a gridview with cells of different sizes inspired by Flow Layout for iOS.
Stars: ✭ 98 (-18.33%)
Mutual labels:  layout
Snapkitextend
SnapKit的扩展,SnapKit类似于Masonry,但是其没有对Arry的设置和对等间距排列的布局等,此扩展是类似Masonry的写法对SnapKit的补充,同时补充九宫格布局方式
Stars: ✭ 110 (-8.33%)
Mutual labels:  layout
Flutter Animations
Flutter animation tutorials, such common animation, flare animation.
Stars: ✭ 119 (-0.83%)
Mutual labels:  layout
Stack Up.js
Create fixed width, variable height grid layouts.
Stars: ✭ 117 (-2.5%)
Mutual labels:  layout
Draggablemenu
A draggable menu that shows a thumbnail preview of an image grid
Stars: ✭ 117 (-2.5%)
Mutual labels:  layout

next-layout

NPM version Downloads Build Status Coverage Status Dependency status Dev Dependency status

Add persistent and nested layouts to your Next.js projects in a declarative way.

Installation

$ npm install @moxy/next-layout

This library is written in modern JavaScript and is published in both CommonJS and ES module transpiled variants. If you target older browsers please make sure to transpile accordingly.

Motivation

Next.js projects usually have the need to have one or more layouts. Layouts are the "shell" of your app and usually contain navigation elements, such as an header and a footer. In more complex projects, you might also need to have nested layouts which are often associated with nested routes.

In the ideal scenario, each page would be able to say which layout they want to use, including tweaking its properties dynamically, such as variant="light". However, we also want to keep the layout persistent in the React tree, to avoid having to remount it every time a user navigate between pages.

Historically, projects overlook the need of multiple layouts or the ability to change layout props between pages. They start off with a simple layout and only later they handle this need, often with poor and non-scalable solutions.

This library solves the need for multi-layouts and changing layout props dynamically in a consistent and reusable way.

Usage

Setup <LayoutTree> in your pages/_app.js component:

import React from 'react';
import { LayoutTree } from '@moxy/next-layout';

const App = ({ Component, pageProps }) => (
    <LayoutTree
        Component={ Component }
        pageProps={ pageProps } />
);

export default App;

...and then use withLayout in your page components, e.g.: in pages/about.js:

import React from 'react';
import { withLayout } from '@moxy/next-layout';
import { PrimaryLayout } from '../components';
import styles from './about.module.css';

const About = () => (
    <div className={ styles.about }>
        <h1>About</h1>
    </div>
);

export default withLayout(<PrimaryLayout variant="light" />)(About);

ℹ️ The PrimaryLayout component will receive the page to be rendered as the children prop.

Nested layouts

Nested layouts are as easy as nesting them in the withLayout. Let's say that you have two account pages, pages/account/profile.js and pages/account/settings.js, and you want them to be wrapped by an AccountLayout. You would define the pages like so:

// pages/account/profile.js
import React from 'react';
import { withLayout } from '@moxy/next-layout';
import { PrimaryLayout, AccountLayout } from '../components';
import styles from './.account-profile.module.css';

const AccountProfile = () => (
    <div className={ styles.accountProfile }>
        <h1>Account Profile</h1>
    </div>
);

export default withLayout(
    <PrimaryLayout>
        <AccountLayout />
    <PrimaryLayout />
)(AccountProfile);
// pages/account/settings.js
import React from 'react';
import { withLayout } from '@moxy/next-layout';
import { PrimaryLayout, AccountLayout } from '../components';
import styles from './account-settings.module.css';

const AccountSettings = () => (
    <div className={ styles.accountSettings }>
        <h1>Account Settings</h1>
    </div>
);

export default withLayout(
    <PrimaryLayout>
        <AccountLayout />
    <PrimaryLayout />
)(AccountSettings);

ℹ️ The PrimaryLayout component will receive AccountLayout as a children, which in turn will receive the page as children too.

ℹ️ You could create a withAccountLayout HOC to avoid repeating the layout tree in every account page.

⚠️ The layout tree specified in withLayout must be a unary tree, that is, a tree where nodes just have one child.

API

@moxy/next-layout exposes a <LayoutTree> component and a withLayout HOC to be used in pages.

<LayoutTree>

A component that infers the layout tree based on what the active page specifies. It keeps the layout persistent between page transitions whenever possible (e.g.: when the layout is the same).

Here's the list of props it supports:

Component

Type: ReactElementType

The page component, which maps to your App Component prop.

pageProps

Type: object

The page component props, which maps to your App pageProps prop.

pageKey?

Type: string

The page key used to uniquely identify this page. Useful for dynamic routes, where the Component is the same, but you still want the page to be re-mounted. For such cases, you may use router.asPath.replace(/\?.+/, '').

defaultLayout

Type: ReactElement

The default layout tree to be used when a child page doesn't explicitly sets one.

// pages/_app.js
import React from 'react';
import { LayoutTree } from '@moxy/next-layout';
import { PrimaryLayout } from '../components';

const App = ({ Component, pageProps }) => (
    <LayoutTree
        Component={ Component }
        pageProps={ pageProps }
        defaultLayout={ <PrimaryLayout /> } />
);

export default App;

children

Type: function

A render prop to override the default render behavior, which just regularly renders the tree.

Its signature is (tree) => <ReactElement>, where: tree is the React's tree composed by layout elements and a leaf page element.

This might be useful if you want to add animations between page transitions.

withLayout(mapLayoutStateToLayoutTree?, initialLayoutState?)(Page)

Sets up a Page component with the ability to specify which layout tree to use. Moreover, it injects a setLayoutState prop so that you may dynamically update the layout tree.

mapLayoutStateToLayoutTree

Type: ReactElement or function

In simple cases, you may define a "static" layout tree, like so:

export default withLayout(<PrimaryLayout variant="light" />)(Home);

However, you might have external props, component state or other mutations influencing the layout tree. In those cases, you may pass a function that maps layout state into a tree, with the following signature: (layoutState) => <ReactElement>. Here's an example:

const mapLayoutStateToLayoutTree = ({ variant }) => <PrimaryLayout variant={ variant } />;

export default withLayout(mapLayoutStateToLayoutTree, { variant: 'light' })(Home);

The function is run initially and every time the layout state changes.

initialLayoutState

Type: object or function

The initial layout state to be passed to mapLayoutStateToLayoutTree. If your initial layout state depends on the props you receive, you may pass a function with the following signature: (props) => <object>.

Page

Type: ReactElementType

The page component to wrap.

Injected setLayoutState

Type: function

Allows dynamic changes to the layout state. Has the following signature: (newState | updater?).

The behavior of setLayoutState is exactly the same as setState of class components: it merges properties and it supports both an object or an updater function.

// pages/about.js
import React, { useCallback } from 'react';
import { withLayout } from '@moxy/next-layout';
import { PrimaryLayout } from '../components';

import styles from './about.module.css';

const About = ({ setLayoutState }) => {
    const handleSetToDark = useCallback(() => {
        setLayoutState({ variant: 'dark' });
        // ..or setLayoutState((layoutState) => ({ variant: 'dark' }));
    }, [setLayoutState]);

    return (
        <div className={ styles.about }>
            <h1>About</h1>
            <button onClick={ handleSetToDark }>Enable dark mode</button>
        </div>
    );
};

const mapLayoutStateToLayoutTree = ({ variant }) => <PrimaryLayout variant={ variant } />;

export default withLayout(mapLayoutStateToLayoutTree, { variant: 'light' })(About);

Tests

$ npm test
$ npm test -- --watch # during development

License

Released under the MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].