Giter Site home page Giter Site logo

alesgenova / split-me Goto Github PK

View Code? Open in Web Editor NEW
74.0 5.0 13.0 1.13 MB

Universal web component to create resizable split layouts

License: MIT License

CSS 12.26% TypeScript 68.38% HTML 19.36%
split-layout stenciljs javascript html splitter typescript webcomponents

split-me's Introduction

npm package workflow status Published on webcomponents.org Built With Stencil

SplitMe - Universal Splitter

SplitMe is a universal splitter built with Stencil. It can be embedded in projects using any framework or even plain HTML.

See a Live Demo.

demo

Table of Contents

Setup

Option 1 (HTML)

Add the SplitMe script tag to your index.html:

<script src="https://unpkg.com/split-me/dist/split-me.js"></script>

Option 2 (React / Angular / Vue)

Add SplitMe to your project:

npm install --save split-me

Import SplitMe in your index.js:

import { defineCustomElements as defineSplitMe } from 'split-me/loader';

defineSplitMe(window);

Basic Usage

Use the split-me tag anywhere you like. Set the number of slots in the splitter through the n attribute. Set the order the inner elements through the slot attribute:

<split-me n="2">
  <div slot="0" class="fill red"></div>
  <div slot="1" class="fill green"></div>
</split-me>

<style>
  .fill {
    height: 100%;
    width: 100%;
  }
</style>

Splitters can be arbitrarily nested into each other to achieve any layout.

<split-me n="3" sizes="0.3, 0.3, 0.4" min-sizes="0.2, 0.0, 0.0">
  <div slot="0" class="fill red"></div>
  <div slot="1" class="fill green"></div>
  <split-me slot="2" n="2" d="vertical" fixed>
    <div slot="0" class="fill blue"></div>
    <div slot="1" class="fill magenta"></div>
  </split-me>
</split-me>

Advanced Usage

Properties

Property Attribute Description Type
d d The direction of the splitter. "horizontal" | "vertical"
fixed fixed Prevent the splitter from being resized. boolean
maxSizes max-sizes The maximum sizes of the slots. Same format as sizes number[] | string
minSizes min-sizes The minimum sizes of the slots. Same format as sizes number[] | string
n n The number of slots in the splitter. number
sizes sizes The initial sizes of the slots. Acceptable formats are: sizes="0.33, 0.67" or sizes="50%, 25%, 25%" number[] | string
throttle throttle The minimum time (in ms) between resize events while dragging. number

Events

Event Detail Description
slotResized IResizeEvent Emitted every time dragging causes the slots to resize
interface IResizeEvent {
  sizes: number[]; // [0.25, 0.75]
  divider: number; // internal divider index
  originalEvent: MouseEvent | TouchEvent; // event that triggered resize
}

Saving State

function handle(event) {
  // extrapolate details
  const { sizes, divider, originalEvent } = event.detail;
  const sourceElement = event.target;

  console.log(sourceElement, originalEvent);
  console.dir({ divider, sizes });

  // store state
  localStorage.setItem('split-sizes', sizes);
}

const el = document.querySelector('split-me');

// loads sizes, but only if they have not been set yet.
el.sizes = el.sizes || localStorage.getItem('split-sizes');

// listen on changes
el.addEventListener('slotResized', handle);

Styling

SplitMe exposes a few CSS variables that can be overridden in order to adjust the styling of the dividers (gutters) to your liking.

This is the list of variables and their default values:

:host {
  --divider-length: 100%; /* Length of the divider along the principal axis */
  --divider-thickness: 0.15rem; /* Thickness of the divider */
  --divider-color: #eeeeee; /* Background color of the divider */
  --divider-shadow: 0 0 0.3rem black; /* Shadow of the divider */
  --divider-image-h: none; /* Background image of the divider when d="horizontal" */
  --divider-image-v: none; /* Background image of the divider when d="vertical" */
  --divider-background-repeat: no-repeat; /* Repeat rule of the background image */
  --divider-background-position: center; /* Position of the background image */
  --phantom-divider-thickness: 2rem; /* Thickness of the phantom divider used to grab mouse events */
}

Any of these variables can be overridden when using SplitMe in your app. For example, to make the dividers thicker and change their color to yellow:

<split-me n="2">
  <div slot="0" class="fill red"></div>
  <div slot="1" class="fill green"></div>
</split-me>

<style>
  :root split-me {
    --divider-thickness: 0.75rem;
    --divider-color: yellow;
  }
</style>

TODO

  • Prevent resizing
  • Specify initial sizes
  • Specify minimum and maximum sizes
  • Customizable splitter style

split-me's People

Contributors

alesgenova avatar max-scopp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

split-me's Issues

Add a css variable for the phantom-divider thickness

When setting the divider-thickness, the phantom-divider still remains wider, and the drag handle may overlap content to the right (if the split is vertical). It would be nice if we could reduce the drag handle width.

Also, if the split is vertical, and the left item is set to overflow auto/scroll, the phantom-divider (drag handle) overlaps the scrollbar and you can't scroll.

How do I set min-sizes in pixels?

Hi @alesgenova

split-me works really well. Thanks for sharing.

Just a question: How would I set min-sizes in pixels? In my use case (proxy example below) I need the left sidebar to be minimum 200px wide. Is that possible and how?

image

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Split Me Example</title>
    <script src="https://unpkg.com/split-me/dist/split-me.js"></script>
    <style>
        body {
            margin: 0px;
            width: 100vw;
            min-height: 100vh;
        }
        .dark {
            background: black;
            color: white;
        }
        .fill {
            min-height: 100vh;
            width: 100%;
        }
        .red {
            background: red;
        }
        .blue {
            background: blue;
        }
        </style>
    </head>
  <body>
    <split-me n="2" sizes="0.2, 0.8" min-sizes="0.1, 0.0">
        <div slot="0" class="fill dark"></div>
        <div slot="1" class="fill"></div>
      </split-me>
      <style>
        :root split-me {
            --divider-thickness: 8px; /* Thickness of the divider */
            --divider-color: lightgray; /* Background color of the divider */
            --divider-shadow: none; /* Shadow of the divider */
            --divider-image-h: url('https://raw.githubusercontent.com/MarcSkovMadsen/awesome-panel-extensions/master/assets/images/three_dots_vertical_5_18.png'); /* Background image of the divider when d="horizontal" */
            --divider-image-v: url('https://raw.githubusercontent.com/MarcSkovMadsen/awesome-panel-extensions/master/assets/images/three_dots_horizontal_5_18.png'); /* Background image of the divider when d="horizontal" */
        }
      </style>
  </body>

</html>

slotResized's detail shall be more informative

From your feedback from Slack, I'd suggest making an issue.

To stick with the nth's being scaled by percentage like Split.js does is generally not a bad idea. There should be no need to return the index of the divider since you can still differentiate them by assigning their specific handlers.

Personally, I would like a whole object which may be better to maintain. I would also consider extending the event with an originalEvent property in order to detect different behaviors (e.g. touch).

I guess if you're using a lot of instances, people may be better off to use an id instead of an index. That way, you can still re-acquire the NodeElement without much overhead. But I don't have a preference here, just some thoughts. Maybe declaring the divider with an provided id, only otherwise using an index since there will be no other way to make it unique.

Like this:

CustomEvent {
  detail: {
    sizes: [0.25, 0.75],
    divider: number | NodeElement | "id"
  },
  originalEvent: MouseEvent | TouchEvent
}

Let me know you what you think.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.