Usage

# Plain JavaScript

The most direct way to use a component is to simply import it and attach it to an element with JavaScript. Here's an example with the Carousel component:

<div class="carousel">
	<div class="rail">
		<div class="item">1</div>
		<div class="item">2</div>
		<div class="item">3</div>
		<div class="item">4</div>
	</div>
</div>
.rail {
	display: flex;
	flex-flow: row nowrap;
	position: relative;
}

.rail:not(.is-dragged) {
	transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}

.item {
	flex-shrink: 0;
	width: calc(50% - 10px);
	margin-right: 20px;
}
import { Carousel, Rail, Item } from 'oblik/components/carousel'

let elCarousel = document.querySelector('.carousel')
let elRail = document.querySelector('.rail')
let elItems = document.querySelectorAll('.item')

let carousel = new Carousel(elCarousel)
let rail = new Rail(elRail, { infinite: true }, carousel)

for (let el of elItems) {
	new Item(el, null, rail)
}

carousel.$init()

This gives you low level access to the lifecycle of components, allowing you to adapt them to other frameworks and libraries.

# The Watcher

Having to manually query the needed DOM elements and intialize your components can become annoying and tough to deal with. That's where the Watcher helps. It binds a MutationObserver to an element (like the <body>), then automatically creates and destroys components you've registered:

<div ob-carousel>
	<div ob-carousel-rail="infinite: true">
		<div ob-carousel-rail-item>1</div>
		<div ob-carousel-rail-item>2</div>
		<div ob-carousel-rail-item>3</div>
		<div ob-carousel-rail-item>4</div>
	</div>
</div>
[ob-carousel-rail] {
	display: flex;
	flex-flow: row nowrap;
	position: relative;
}

[ob-carousel-rail]:not(.is-dragged) {
	transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}

[ob-carousel-rail-item] {
	flex-shrink: 0;
	width: calc(50% - 10px);
	margin-right: 20px;
}
import { Watcher } from 'oblik'
import { Carousel } from 'oblik/components/carousel'

let w = new Watcher(document.body, {
	components: {
		carousel: Carousel
	}
})

w.init()

If you look at the HTML, you'll see that you can initialize components and assign options to them via attributes:

<div ob-carousel>
    <div ob-carousel-rail="infinite: true">
        <div ob-carousel-rail-item>1</div>
        <div ob-carousel-rail-item>2</div>
        <div ob-carousel-rail-item>3</div>
        <div ob-carousel-rail-item>4</div>
    </div>
</div>

Learn more about that option syntax here.

# Custom components

Since components are just ES6 classes, you can easily create your own components by extending the base Component class:

<button ob-foo="text: Clicked!">
	Click Me
</button>
import { Watcher, Component } from 'oblik'

class MyComponent extends Component {
	init () {
		this.$element.addEventListener('click', () => {
			this.$element.innerHTML = this.$options.text
		})
	}
}

let w = new Watcher(document.body, {
	components: {
		foo: MyComponent
	}
})

w.init()

# Subcomponents

Similarly, components can have subcomponents by specifying the components static property:

class Child extends Component {
    ...
}

class Parent extends Component {
    static components = {
        child: Child
    }
    ...
}

When using the Watcher, you register the parent component:

let w = new Watcher(document.body, {
    components: {
        parent: Parent
    }
})

...and then just use it in your markup:

<div ob-parent>
    <button ob-parent-child>Child</button>
</div>

Learn more about components here.

# From a CDN

In case you don't want to deal with ES6 and bundling scripts, you can load everything that Oblik has to offer from a CDN:

<div ob-carousel>
	<div ob-carousel-rail="infinite: true">
		<div ob-carousel-rail-item>1</div>
		<div ob-carousel-rail-item>2</div>
		<div ob-carousel-rail-item>3</div>
		<div ob-carousel-rail-item>4</div>
	</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/oblik@latest/dist/oblik.js"></script>
[ob-carousel-rail] {
	display: flex;
	flex-flow: row nowrap;
	position: relative;
}

[ob-carousel-rail]:not(.is-dragged) {
	transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}

[ob-carousel-rail-item] {
	flex-shrink: 0;
	width: calc(50% - 10px);
	margin-right: 20px;
}
var w = new oblik.Watcher(document.body, {
	components: {
		carousel: oblik.components.Carousel
	}
})

w.init()

You can create your own simple components in plain ES5 JavaScript as well:

<button ob-foo="text: Clicked!">
	Click Me
</button>

<script src="https://cdn.jsdelivr.net/npm/oblik@latest/dist/oblik.js"></script>
var MyComponent = function (element, options) {
	element.addEventListener('click', function () {
		element.innerHTML = options.text
	})
}

var w = new oblik.Watcher(document.body, {
	components: {
		foo: MyComponent
	}
})

w.init()

# Wrapping other libraries

At the very least, Oblik can be used to wrap other libraries as components and use the Watcher to make it easier to manage them from your HTML. Here's an example with Tippy.js:

<button ob-tippy="content: This is Tippy!">
	Hover me!
</button>

<button ob-tippy="$content: @sibling, trigger: click">
	Click me!
</button>

<template>
	This is a <strong>Tippy</strong> template!
</template>
import { Watcher, Component } from 'oblik'
import tippy from 'tippy.js'
import 'tippy.js/dist/tippy.css'

class Tippy extends Component {
	init () {
		let template = this.$options?.content?.innerHTML

		if (template) {
			this.$options.content = template
			this.$options.allowHTML = true
		}

		this.tippy = tippy(this.$element, this.$options)
	}

	destroy () {
		this.tippy.destroy()
	}
}

let w = new Watcher(document.body, {
	components: {
		tippy: Tippy
	}
})

w.init()

As you can see, it's easy to add your own layer of functionality on top of Tippy and use Oblik's options syntax to customize tooltip instances and even query their content template:

<button ob-tippy="$content: @sibling, trigger: click">
    Click me!
</button>

<template>
    This is a <strong>Tippy</strong> template!
</template>

Another benefit is that when the [ob-tippy] element is removed from the DOM, the Watcher will automatically destroy the tooltip instance it has created. This allows you to worry less about memory management.

# Utilities

In case Oblik's components are not what you're after, perhaps one of its utilities can help. Here's an example with the Scroll utility:

<button>Scroll to #foo</button>

<p>Vivamus eu volutpat enim. Proin …</p>
<p>Integer ligula eros, mattis ac …</p>
<p>Sed eget imperdiet nulla. Vestibulum …</p>
<h1 id="foo">Foo</h1>
<p>Nam sed dignissim quam. Sed porta orci …</p>

<script src="https://cdn.jsdelivr.net/npm/oblik@latest/dist/oblik.js"></script>
var button = document.querySelector('button')
var foo = document.querySelector('#foo')

button.addEventListener('click', function () {
	oblik.utils.scrollTo({
		target: foo,
		duration: 1000,
		easing: oblik.utils.easeOutQuint
	})
})
← Installation Watcher →