npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@lightspeed/cirrus-sidebar

v1.0.2

Published

Cirrus Sidebar Component

Downloads

2,206

Readme

Sidebar

The composable and reusable <Sidebar> component. Since these components are very flexible, it's recommended to build your own abstraction specific to your product on top of this.

ℹ️ Note: The implementation of the breakpoints (when to hide) and animation is up to the consumer of this package as of now.

Installation

First, make sure you have been through the install steps steps required to add Flame in your application. Although it's not required to have Flame installed to use Logo, you will need to install its peer dependencies.

If using Yarn:

yarn add @lightspeed/cirrus-sidebar

Or using npm:

npm i -S @lightspeed/cirrus-sidebar

Styles

Because the <Sidebar> is completely unknown in what environment it's being rendered and at what breakpoints the sidebar should hide, we open up a couple of animation styles for you to use.

These styles are exposed at @lightspeed/cirrus-sidebar/styles. These constants are exposed at @lightspeed/cirrus-sidebar/styles/constants.

Example

import styled from '@emotion/styled';
import { slideInDurationMs, slideInBezier } from '@lightspeed/cirrus-sidebar/styles';
import { PAGE_HEADER_HEIGHT, SIDEBAR_WIDTH } from '@lightspeed/cirrus-sidebar/styles/constants';
import { Sidebar } from '@lightspeed/cirrus-sidebar';

const SidebarWrapper = styled.div`
  position: absolute;
  left: -${SIDEBAR_WIDTH}px;
  top: 0;
  bottom: 0;
  transition: left ${slideInDurationMs} ${slideInBezier};

  ${props => props.active && 'left: 0;'}
  @media (min-device-width: 480px) {
    left: 0;
  }
`;

const App = () => (
  <SidebarWrapper>
    <Sidebar>Sidebar content here</Sidebar>
  </SidebarWrapper>
);

export default App;

Full featured Sidebar

Example

import React from 'react';
import { Text } from '@lightspeed/cirrus-text';
import Icon from '@lightspeed/cirrus-icon';
import {
  Sidebar,
  SidebarHeader,
  SidebarAppSwitcher,
  SidebarShopButton,
  SidebarDropdownButton,
  SidebarAccountDropdown,
  SidebarMenu,
  SidebarMenuItem,
  SidebarItem,
  SidebarNotificationBadge,
  SidebarNav,
  SidebarFooter,
  SidebarFooterItem,
} from '@lightspeed/cirrus-sidebar';

const items = [
  { icon: <Icon name="home" />, children: 'Home', href: '/', active: true },
  { icon: <Icon name="statistics" />, children: 'Statistics', href: 'statistics' },
  {
    icon: <Icon name="orders" />,
    children: 'Orders',
    href: 'orders',
    hasSublevel: true,
    notifications: <SidebarNotificationBadge>2</SidebarNotificationBadge>,
  },
  { icon: <Icon name="products" />, children: 'Products', href: 'products', hasSublevel: true },
  { icon: <Icon name="customers" />, children: 'Customers', href: 'customers', hasSublevel: true },
  { icon: <Icon name="design" />, children: 'Design', href: 'themes', hasSublevel: true },
  { icon: <Icon name="content" />, children: 'Content', href: 'pages', hasSublevel: true },
  {
    icon: <Icon name="discount-rules" />,
    children: 'Marketing',
    href: 'discount_codes',
    hasSublevel: true,
  },
  {
    icon: <Icon name="blogs" />,
    children: 'Blogs',
    href: 'blogs',
    onClick: e => {
      e.preventDefault();
      console.log('You can also just hook into the item through onClick!');
    },
    hasSublevel: true,
  },
  {
    icon: <Icon name="apps" />,
    children: 'Apps',
    href: 'store/apps/dashboard',
    disabled: true,
    hasSublevel: true,
  },
  { icon: <Icon name="tools" />, children: 'Tools', href: 'imports', hasSublevel: true },
  { icon: <Icon name="settings" />, children: 'Settings', href: 'settings', disabled: true },
];

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isUserMenuOpen: false,
    };

    this.openUserMenu = this.openUserMenu.bind(this);
    this.closeUserMenu = this.closeUserMenu.bind(this);
  }

  openUserMenu() {
    this.setState(() => ({
      isUserMenuOpen: true,
    }));
  }

  closeUserMenu() {
    this.setState(() => ({
      isUserMenuOpen: true,
    }));
  }

  render() {
    const { isUserMenuOpen } = this.state;

    return (
      <div>
        <Sidebar>
          <SidebarHeader>
            <SidebarAppSwitcher
              currentProduct="ecom"
              canSwitchTo={[{ name: 'retail', href: '/retail' }]}
            />

            <SidebarShopButton>
              <Text color="snow">SEOshop</Text>
              <Text color="snow">http://shop1.webshopapp.dev/</Text>
            </SidebarShopButton>

            <SidebarAccountDropdown
              isOpen={isUserMenuOpen}
              onOpen={this.openUserMenu}
              onClose={this.closeUserMenu}
              target={({ targetProps, targetEvents }) => (
                <SidebarDropdownButton {...targetProps} {...targetEvents} active={isUserMenuOpen}>
                  Awesome Merchant
                </SidebarDropdownButton>
              )}
            >
              <SidebarMenu>
                <SidebarMenuItem href="#">Tasks</SidebarMenuItem>
                <SidebarMenuItem href="#">My Account</SidebarMenuItem>
                <SidebarMenuItem href="#" danger>
                  Logout
                </SidebarMenuItem>
              </SidebarMenu>
            </SidebarAccountDropdown>
          </SidebarHeader>

          <SidebarNav>
            <ul>
              {items.map(item => (
                <SidebarItem key={item.title} {...item} />
              ))}
            </ul>
          </SidebarNav>

          <SidebarFooter>
            <SidebarFooterItem
              icon={<Icon name="help" />}
              href="#"
              target="_blank"
              rel="noopener noreferrer"
            >
              Help
            </SidebarFooterItem>

            <SidebarFooterItem icon={<Icon name="search" />} href="#">
              Search
            </SidebarFooterItem>
          </SidebarFooter>
        </Sidebar>
      </div>
    );
  }
}

export default MyComponent;

Sidebar

The wrapper of the sidebar (controls the width and color).

Props

| Prop | Type | Description | | ---------- | --------------- | ---------------------------------------- | | children | React.ReactNode | The content to display inside the button | | ...rest | Any | Any prop you want to add to this element |

Example

import React from 'react';
import { Sidebar } from '@lightspeed/cirrus-sidebar';

const App = () => <Sidebar>My content here</Sidebar>;

export default App;

SidebarHeader

The top part of the sidebar (contains the appswitcher, shopbutton and account menu). This element divides the top part of the sidebar from the main navigation and the footer.

Props

| Prop | Type | Description | | ---------- | --------------- | ----------------------------------------- | | children | React.ReactNode | The content to display inside the sidebar | | ...rest | Any | Any prop you want to add to this element |

Example

import React from 'react';
import { Sidebar, SidebarHeader } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>Your header stuff here</SidebarHeader>

    <nav>Other stuff here</nav>
  </Sidebar>
);

export default App;

SidebarAppSwitcher

This component is responsible for showing the correct current app and what apps the user can switch to.

Props

| Prop | Type | Required? | Description | | ---------------- | ----------------- | --------- | ---------------------------------------------------------------------------- | | currentProduct | ecom|retail | Yes | The current product is that the user is on | | canSwitchTo | Array<ProductT> | No | The list of products that the user can switch to | | logoProps | Object | No | The props you want to pass to the logo (such as href, onClick, etc.) | | triggerProps | Object | No | The props you want to pass to the "switch products" button | | appsConfig | AppsConfig | No | An object that allows you to add new apps to switch to (see info down below) |

AppsConfig

The apps config is an object with the key being the app identifier and the value being the app logo. This allows you to then use these as the currentProduct and within the switchable apps array.

Note: This does not override existing apps (e.g. retail and ecom will still remain available)

Example
const appsConfig = {
  customApp: <svg />,
  anotherApp: <svg />,
};

<SidebarAppSwitcher
  appsConfig={appsConfig}
  currentProduct="customApp"
  canSwitchTo={[{ name: 'retail', href: '/retail' }, { name: 'anotherApp', href: '/another-app' }]}
/>;

Example

User is not able to switch between products
import React from 'react';
import { Sidebar, SidebarHeader, SidebarAppSwitcher } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>
      <SidebarAppSwitcher currentProduct="ecom" />
    </SidebarHeader>
  </Sidebar>
);

export default App;
User can switch to retail
import React from 'react';
import { Sidebar, SidebarHeader, SidebarAppSwitcher } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>
      <SidebarAppSwitcher
        currentProduct="ecom"
        canSwitchTo={[{ name: 'retail', href: '/retail' }]}
      />
    </SidebarHeader>
  </Sidebar>
);

export default App;
User can switch to retail through onClick
import React from 'react';
import { Sidebar, SidebarHeader, SidebarAppSwitcher } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>
      <SidebarAppSwitcher
        currentProduct="ecom"
        canSwitchTo={[
          {
            name: 'retail',
            onClick: e => {
              e.preventDefault();
              router.goTo('/retail');
            },
          },
        ]}
      />
    </SidebarHeader>
  </Sidebar>
);

export default App;
With custom config
import React from 'react';
import { Sidebar, SidebarHeader, SidebarAppSwitcher } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>
      <SidebarAppSwitcher
        appsConfig={{ customProduct: '🔥' }}
        currentProduct="ecom"
        canSwitchTo={[
          { name: 'retail', href: '/retail' },
          { name: 'customProduct', href: '/custom-product' },
        ]}
      />
    </SidebarHeader>
  </Sidebar>
);

export default App;
Add link to logo
import React from 'react';
import { Sidebar, SidebarHeader, SidebarAppSwitcher } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>
      <SidebarAppSwitcher logoProps={{ href: '/' }} currentProduct="ecom" />
    </SidebarHeader>
  </Sidebar>
);

export default App;
Add data attribute to trigger button
import React from 'react';
import { Sidebar, SidebarHeader, SidebarAppSwitcher } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>
      <SidebarAppSwitcher
        triggerProps={{ 'data-test': 'sidebar-product-trigger' }}
        currentProduct="ecom"
      />
    </SidebarHeader>
  </Sidebar>
);

export default App;

SidebarShopButton

The button that is all around the current shop and register.

Props

| Prop | Type | Description | | ---------- | --------------- | ------------------------------------------- | | children | React.ReactNode | The content to display inside the button | | active | boolean | Whether the shop button is currently active | | ...rest | Any | Any prop you want to add to this element |

Example

import React from 'react';
import { Text } from '@lightspeed/cirrus-text';
import { SidebarShopButton } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>
      <SidebarShopButton onClick={() => router.goTo('/switch')}>
        <Text color="snow">SEOshop</Text>
        <Text color="snow">http://shop1.webshopapp.dev/</Text>
      </SidebarShopButton>
    </SidebarHeader>
  </Sidebar>
);

export default App;

SidebarDropdownButton

The dropdown button that is used for opening menus (contains an icon that indicates that a menu will open). See <SidebarAccountDropdown> for an example.

Props

| Prop | Type | Description | | ---------- | --------------- | ---------------------------------------- | | children | React.ReactNode | The content to display inside the button | | ...rest | Any | Any prop you want to add to this element |

SidebarMenu

See <SidebarAccountDropdown> for an example.

Props

| Prop | Type | Description | | ---------- | --------------- | ---------------------------------------- | | children | React.ReactNode | The content to display inside the button | | ...rest | Any | Any prop you want to add to this element |

SidebarMenuItem

The menu item for the <SidebarMenu>. See <SidebarAccountDropdown> for an example.

Props

| Prop | Type | Description | | ---------- | --------------- | ---------------------------------------- | | children | React.ReactNode | The content to display inside the button | | danger | boolean | Whether the item is danger styled | | ...rest | Any | Any prop you want to add to this element |

Example

SidebarAccountDropdown

The Sidebar popover menu. Renders a cirrus-popover with some customized positional styles.

Props

| Prop | Type | Description | | ----------------------- | --------------- | ------------------------------------------- | | children | React.ReactNode | The content to display inside the button | | ...cirrusPopoverProps | Object | Any props defined within the cirrus-popover |

Example

import React from 'react';
import { Text } from '@lightspeed/cirrus-text';
import {
  Sidebar,
  SidebarHeader,
  SidebarAccountDropdown,
  SidebarDropdownButton,
  SidebarMenu,
  SidebarMenuItem,
} from '@lightspeed/cirrus-sidebar';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isUserMenuOpen: false,
    };

    this.openUserMenu = this.openUserMenu.bind(this);
    this.closeUserMenu = this.closeUserMenu.bind(this);
  }

  openUserMenu() {
    this.setState(() => ({
      isUserMenuOpen: true,
    }));
  }

  closeUserMenu() {
    this.setState(() => ({
      isUserMenuOpen: true,
    }));
  }

  render() {
    const { isUserMenuOpen } = this.state;

    return (
      <Sidebar>
        <SidebarHeader>
          <SidebarAccountDropdown
            isOpen={isUserMenuOpen}
            onOpen={this.openUserMenu}
            onClose={this.closeUserMenu}
            target={({ targetProps, targetEvents }) => (
              <SidebarDropdownButton {...targetProps} {...targetEvents} active={isUserMenuOpen}>
                Awesome Merchant
              </SidebarDropdownButton>
            )}
          >
            <SidebarMenu>
              <SidebarMenuItem href="#">Tasks</SidebarMenuItem>
              <SidebarMenuItem href="#">My Account</SidebarMenuItem>
              <SidebarMenuItem href="#" danger>
                Logout
              </SidebarMenuItem>
            </SidebarMenu>
          </SidebarAccountDropdown>
        </SidebarHeader>
      </Sidebar>
    );
  }
}

export default MyComponent;

SidebarNav

The <nav> element styled for the Sidebar.

Note: Automatically removes the list-style from a direct child <ul> tag.

Props

| Prop | Type | Description | | ---------- | --------------- | ---------------------------------------- | | children | React.ReactNode | The content to display inside the button | | ...rest | Any | Any prop you want to add to this element |

Example

import React from 'react';
import { Text } from '@lightspeed/cirrus-text';
import { Sidebar, SidebarHeader, SidebarNav } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>The header here</SidebarHeader>

    <SidebarNav>
      <ul>
        <li>Your nav items here</li>
      </ul>
    </SidebarNav>
  </Sidebar>
);

export default App;

SidebarItem

The sidebar navigation link (<a>).

Props

| Prop | Type | Description | | --------------- | ---------- | --------------------------------------------------------------- | | icon | React.Node | Can render any icon (preferably the a cirrus-icon) | | children | React.Node | The navigation item's title | | href | string | The url of the navigation item (should be present) | | active | boolean | Whether the navigation link is currently active | | disabled | boolean | Whether the navigation link is disabled (only appears disabled) | | notifications | React.Node | Allows for showing notifications for this navigation link | | hasSublevel | boolean | Whether this navigation link has a sub level navigation | | ...rest | Any | Any prop you want to add to this element |

Example

Using href
import React from 'react';
import Icon from '@lightspeed/cirrus-icon';
import { Text } from '@lightspeed/cirrus-text';
import { Sidebar, SidebarHeader, SidebarNav, SidebarItem } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>The header here</SidebarHeader>

    <SidebarNav>
      <ul>
        <li>
          <SidebarItem icon={<Icon name="home" />} href="/">
            Home
          </SidebarItem>
        </li>
      </ul>
    </SidebarNav>
  </Sidebar>
);

export default App;
Using onClick

When passing onClick, you should still pass a href as well, to indicate that the element is interactable.

import React from 'react';
import Icon from '@lightspeed/cirrus-icon';
import { Text } from '@lightspeed/cirrus-text';
import { Sidebar, SidebarHeader, SidebarNav, SidebarItem } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>The header here</SidebarHeader>

    <SidebarNav>
      <ul>
        <li>
          <SidebarItem
            icon={<Icon name="home" />}
            href="/"
            onClick={e => {
              e.preventDefault();
              router.goTo('/');
            }}
          >
            Home
          </SidebarItem>
        </li>
      </ul>
    </SidebarNav>
  </Sidebar>
);

export default App;

SidebarNotificationBadge

The notification badge that can be used within the <SidebarItem />'s notifications prop.

Props

| Prop | Type | Description | | ---------- | --------------- | ---------------------------------------- | | children | React.ReactNode | The content to display inside the button | | ...rest | Any | Any prop you want to add to this element |

Example

import React from 'react';
import Icon from '@lightspeed/cirrus-icon';
import { Text } from '@lightspeed/cirrus-text';
import {
  Sidebar,
  SidebarHeader,
  SidebarNav,
  SidebarItem,
  SidebarNotificationBadge,
} from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>The header here</SidebarHeader>

    <SidebarNav>
      <ul>
        <li>
          <SidebarItem
            icon={<Icon name="home" />}
            href="/"
            notifications={<SidebarNotificationBadge>2</SidebarNotificationBadge>}
          >
            Home
          </SidebarItem>
        </li>
      </ul>
    </SidebarNav>
  </Sidebar>
);

export default App;

SidebarFooter

The <footer> styled for the Sidebar

Props

| Prop | Type | Description | | ---------- | --------------- | ---------------------------------------- | | children | React.ReactNode | The content to display inside the button | | ...rest | Any | Any prop you want to add to this element |

Example

import React from 'react';
import Icon from '@lightspeed/cirrus-icon';
import { Text } from '@lightspeed/cirrus-text';
import { Sidebar, SidebarHeader, SidebarNav, SidebarFooter } from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>The header here</SidebarHeader>
    <SidebarNav>Nav here</SidebarNav>
    <SidebarFooter>The Footer goes here</SidebarFooter>
  </Sidebar>
);

export default App;

SidebarFooterItem

The items that go inside the footer (renders a <a>).

Props

| Prop | Type | Description | | ---------- | --------------- | --------------------------------------------- | | children | React.ReactNode | The content to display inside the footer item | | icon | React.ReactNode | The icon to render inside the footer item | | ...rest | Any | Any prop you want to add to this element |

Example

import React from 'react';
import Icon from '@lightspeed/cirrus-icon';
import { Text } from '@lightspeed/cirrus-text';
import {
  Sidebar,
  SidebarHeader,
  SidebarNav,
  SidebarFooter,
  SidebarFooterItem,
} from '@lightspeed/cirrus-sidebar';

const App = () => (
  <Sidebar>
    <SidebarHeader>The header here</SidebarHeader>
    <SidebarNav>Nav here</SidebarNav>
    <SidebarFooter>
      <SidebarFooterItem icon={<Icon name="help" />} href="/help">
        Help
      </SidebarFooterItem>
    </SidebarFooter>
  </Sidebar>
);

export default App;