Mini lets you add interactivity to your web apps without leaving your HTML.
To add Mini to your project, simply save this file to your codebase and load it when your page loads.
<script src="/mini.js" ></script>
Alternatively you can also load Mini directly from our CDN if you prefer.
<script src="https://cdn.mini-js.com/1.0.20.js" ></script>
Mini is an extremely easy to use way to add UI Behaviour to your web software. It's not designed to store all of your state — for example it doesn't include routing or authentication — so it works best when paired with a Server-side Rendered approach.
The best way to understand where Mini shines is to see some examples.
<button :click="showMenu = !showMenu" :clickout="showMenu = false">
<div :class="showMenu ? 'rotate-180' : '' " ></div>
Show Menu
</button>
<div :class="showMenu ? 'transform opacity-100 scale-100' : 'transform opacity-0 scale-95 pointer-events-none' "></div>
:
to let them evaluate javascriptFor example, for form inputs, use :value
to set an input's value
.
<input type="text" :value="window.navigator.userAgent" />
This will display this ⤵
class
, use the :class
attributestyle
, use the :style
attributeVariables default to the global namespace, so you can define your data anywhere in your page and use it later.
<script>
firstName="Michael"
lastName="Scott"
</script>
<input type="text" :value="firstName + ` ` +lastName" />
This will display this ⤵
Mini extends the browser's native events with shorthand attributes like :click
, :change
, :press
, :clickout
and a few others. For example, you can use the:click
attribute to respond to elements being clicked
<script>
firstName="Michael"
lastName="Scott"
</script>
<button :click="firstName = 'Pamela'" />
<button :click="lastName = 'Halpert'" />
<input type="text" :value="firstName + ` ` +lastName" />
Being able to set state using javascript variables, update state in response to interactions, and mutate the dom depending on the state, unlocks a lot of UI patterns.
Now that you've learned the basics, here are a few more tricks you can use.
:text
to set the inner text of an element<span :text="`My lucky number is: `+Math.floor(Math.random() * 100) + 1;" />
This will display:
:change
to monitor form inputs, and this.value
to get their values<input type="text" :change="firstName=this.value" />
<span :text="`Your first name is: ` + firstName">
event
to get the current eventYou can also access the current event with the event
keyword.
<button :click="console.log(event)">Click Me</button>
:each
to loop through arrays or objectsWhile we don't recommend storing deep state, we do provide the ability to iterate through and display collections of objects, like so.
<script>
todos = [
{ name: "Clean Dishes", complete: true },
{ name: "Vacuum Floors", complete: false}
]
</script>
<div :each="todo in todos">
<div :text="todo.name"></div>
</div>
:load
to execute code when an element is loadedSometimes we want code to be executed as soon as the page, or a specific element on the page, is loaded.
<div :load="console.log('I was loaded')"></div>
This is also useful when looping through arrays with :each
.
We often need to group together elements which draw from the same state. To do this, first we add the :scope
attribute to the outer HTML element, then we prefix our variables with scope.
.
<div :scope>
<button :click="scope.showDropdown = true">First Dropdown</button>
<div :class="scope.showDropdown ? 'block' : 'hidden'"></div>
</div>
<div :scope>
<button :click="scope.showDropdown = true">Second Dropdown</button>
<div :class="scope.showDropdown ? 'block' : 'hidden'"></div>
</div>
We can also set the default values within a scoped group when they load.
<div :scope="showDropdown=true">
<button :click="scope.showDropdown = true">First Dropdown</button>
<div :class="scope.showDropdown ? 'block' : 'hidden'"></div>
</div>
el.
to scope state to a specific dom elementThe benefit of scope is that you can have groups of dom elements that all share state. But sometimes your state only needs to exist on a single element. In this case you can use the el.
prefix before your variables.
<div
:load="el.bgColor=bg-green-900"
:class="el.bgColor">
</div>
The basic premise of Mini is to let attributes execute javascript. This means you can do anything javascript can do, including, for example:
Basic, If Else statements
<div
:class="if (selectedTab === 'when') {
'bg-white shadow-lg'
} else {
'hover:bg-gray-300'
}"
></div>
Nested Ternaries
<div
:class="(selectedTab === 'When' ? 'bg-white shadow-lg' : 'hover:bg-gray-300')
(whenSelectedTab === 'Dates' ? 'hidden' : '')"
></div>
Because javascript is quite verbose, putting it inside of our attributes can get unwieldy quickly. So we added some helper methods that make doing common things like setting timeouts and working with arrays, a little more tidy.
await wait()
instead of setTimeout()
<button :click="alert('Starting');await wait(3000);alert('Ended')">
</button>
<script>
fruits=['Apple','Banana','Pear','Strawberry','Grape','Pineapple']
filteredFruits = fruits
</script>
<input type="text" :change="filteredFruits = fruits.search(this.value);">
<div :each="fruit in filteredFruits">
<div :text="fruit"></div>
</div>
See all the custom methods in the Reference here.
For keyboard events, you can listen to them using :keyup
, :keydown
, and :keypress
:
<input type="text" :keyup="console.log(event)" />
You can also do cool stuff like chaining keyboard modifiers together. See The Reference for more info.