Arbalet is a stylus library that provides various mixins. The main purpose is to reduce typing by using the magic of transparent mixins. It also provides utility mixins to make things easier such as debugging or built-in components
npm i -D arbalet
Note that when a mixin has arguments
in it, you can put any args in the mixin although it's not explicitly written between the parentheses in the source code
Imports Remix Icons/Box Icons
source code:
remixicon()
@import url('https://cdn.jsdelivr.net/npm/remixicon@2.2.0/fonts/remixicon.css')
boxicon()
@import url('https://unpkg.com/boxicons@2.1.2/css/boxicons.min.css')
NOTE: this is not the most optimized method, for production consider adding the cdn with the <link>
tag instead
Prints in the console whatever value you passed to it
source code:
@import 'arbalet'
print(thing)
p(thing)
log(thing)
p(thing)
Outlines all elements in black and replace the background to a semi-transparent green. This is useful to debug CSS to see where HTML tags are, how they behave together etc
To use this, you have to add a script to your top-level app file (index.tsx in React for example). It allows you to toggle the debug function on the HTML page directly, and also when you press CTRL, you will see the current element in red, the parent element in orange, and the siblings in blue. This file is written in vanilla javascript
import "arbalet/scripts/debugLive";
To enable it, press CTRL+*. You can also call the mixin debugLive()
to show a toggle button. It can takes arguments, to position the button
@import 'arbalet'
debugLive(bottom left) // defaults to bottom right
Imports a font from Google Fonts
@import 'arbalet'
// Example
importfont('Readex Pro', 400..700)
Arbalet's reset for global CSS, just call the mixin in your global stylus file. Arbalet uses @layer reset
for reset mixin
Compose your focus state, it will be applied to a
tag, tabindex, input
, textarea
, button
. It uses :focus-visible
pseudo-class
// Source
focus()
a:focus-visible,
[tabindex]:focus-visible,
input:focus-visible,
textarea:focus-visible,
button:focus-visible
outline 0
{block}
// Example
@import 'arbalet'
focus()
outline 2px solid #0048ff
outline-offset .15em
Custom your scrollbar. Only works for Chrome for now
{size} // width / height of the scrollbar
{track} // background color of the track
{thumb} // background color of the thumb
{hover} // background color of the thumb when hover. Defaults to darken(thumb, 10%)
{active} // background color of the thumb when active. Defaults to darken(thumb, 20%)
{margin} // optional, it adds space between the thumb and the track
// Example
scrollbar({
size: 15px,
thumb: #999,
margin: 3px
})
Sets the selection background & text color
@import 'arbalet'
selection(#0048ff, white)
Don't write the annoying anymore. Compose your pseudo-elements directly in the mixin
// Without the mixin
a + a
&::after
content '>'
color black
// With the mixin
@import 'arbalet'
a + a
+after('>')
color black
Shorthand for color
property
@import 'arbalet'
.myelement
clr #0048ff
Shorthand for background-color
property
@import 'arbalet'
.myelement
bgclr #e7e7e7
Shorthand for background-image
property
@import 'arbalet'
.myelement
bgimg url("https://lapatrie.org/myimage.png")
Shorthand for background-image: linear-gradient(arguments)
@import 'arbalet'
.myelement
lgradient to right, #0048ff, #ae00ff
Shorthand for background-image: radial-gradient(arguments)
@import 'arbalet'
.myelement
rgradient circle, #0048ff, #ae00ff
Adds a gradient to a text. Only works with linear gradient for now.
@import 'arbalet'
.myelement
textgradient to right, #0048ff, #ae00ff
Shorthand for background
property
@import 'arbalet'
.myelement
bg #232425
Shorthand for backdrop-filter: blur(value)
property. Now works on Firefox as well
@import 'arbalet'
.myelement
bgblur .5rem
Shorthand for background-clip
property.
@import 'arbalet'
.myelement
bgclip text
Sets the opacity to amount
@import 'arbalet'
.myelement
bgclr opacify(black, 20%)
Arbalet uses @layer components
for components mixins
Creates a default styling for CTAs based on BEM naming convention
Creates a default styling form & form components based on BEM naming convention
w() for width, maxw() for max-width, minw() for min-width. Same thing for height, h(), maxh(), minh()
@import 'arbalet'
// Defaults to % if no unit provided
body
w 100 // 100%
maxw calc(100% - 2rem) // no compilation
minh 20rem // 20rem
rel // relative
abs // absolute
// Example
@import 'arbalet'
.myelement
pos rel // relative
dflex()
is one of the most complete and useful mixins because it allows you to chain arguments in whatever order you want. Arbalet is figuring out which arg is what and does the job for you. When you call it with or without argument, it automatically writes display: flex;
jcs // justify-content: start;
jcc // justify-content: center;
jce // justify-content: end;
sb // justify-content: space-between;
// Example
@import 'arbalet'
.myelement
dflex sb // display: flex; justify-content: space-between
ais // align-items: start;
aic // align-items: center;
aie // align-items: end;
// Example
@import 'arbalet'
.myelement
dflex aic
w | wrap // flex-wrap: wrap;
wrev | wraprev // flex-wrap: wrap-reverse;
now | nowrap // flex-wrap: nowrap
// Example
@import 'arbalet'
.myelement
dflex now
col // flex-direction: column
colrev // flex-direction: column-reverse
row // flex-direction: row;
rowrev // flex-direction: row-reverse;
// Example
@import 'arbalet'
.myelement
dflex colrev
gap
is the only unit-typed argument, so just add it to the arguments list
@import 'arbalet'
.myelement
dflex 2rem
This one modify the direct children from the container where you call it
The source code looks like this:
& > *
flex-grow 1
grow // flex-grow: 1;
shrink // flex-shrink: 1;
// Example
@import 'arbalet'
.myelement
dflex grow
// compiles to:
.myelement > *
flex-grow: 1;
Here is a complete example (yes, it saves so much keystrokes)
// with arbalet
.myelement
dflex aic 2rem w grow
// compiles to:
.myelement
display flex
align-items center
gap 2rem
flex-wrap wrap
& > *
flex-grow 1
dgrid()
is like the dflex()
one, you can also chain arguments in whatever order you want
ais // align-items: start;
aic // align-items: center;
aie // align-items: end;
acs // align-content: start;
acc // align-content: center;
ace // align-content: end;
// Example
@import 'arbalet'
.myelement
dgrid aic
pcs // place-content: start;
pcc // place-content: center;
pce // place-content: end;
pis // place-items: start;
pic // place-items: center;
pie // place-items: end;
// Example
@import 'arbalet'
.myelement
dgrid pcc
gap
is the only unit-typed argument, so just add it to the arguments list
@import 'arbalet'
.myelement
dgrid 2rem
// Source code
gtc()
grid-template-columns arguments
gtr()
grid-template-rows arguments
// Example
@import 'arbalet'
.myelement
dgrid()
gtr repeat(2, 1fr)
// Source code
gta()
grid-template-areas arguments
ga()
grid-area arguments
// Example
@import 'arbalet'
.myelement
dgrid 2rem
gta "a b" "a c"
self()
is a special mixin, with a little different syntax but works the same
as // align-self: start;
ac // align-self: center;
ae // align-self: end;
js // justify-self: start;
jc // justify-self: center;
je // justify-self: end;
start // place-self: start;
center // place-self: center;
end // place-self: end;
Just call the dblock() and dnone() mixins
@import 'arbalet'
.myelement
dnone()
&.visible
dblock()
How many times have you tried to change the two top border radiuses with logical properties on first try? Now, use Arbalet's border-radius mixins
// Global
rad()
border-radius arguments
// Top left, top right
radtop()
border-start-start-radius arguments
border-start-end-radius arguments
// Bottom left, bottom right
radbottom()
border-end-start-radius arguments
border-end-end-radius arguments
// Top left, bottom left
radleft()
border-start-start-radius arguments
border-end-start-radius arguments
// Top right, bottom right
radright()
border-start-end-radius arguments
border-end-end-radius arguments
Line clamp is no longer a nightmare. Use lineclamp()
mixin
// Example
@import 'arbalet'
.myelement
lineclamp 5
// compiles to:
.myelement
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 5;
overflow: hidden;
ratio()
aspect-ratio arguments
Arbalet encourages the use of logical properties, so it's all about "inline" or "block" according to the X and Y axis
//// Margins
// block
mb()
margin-block arguments
mbs()
margin-block-start arguments
mbe()
margin-block-end arguments
// inline
mi()
margin-inline arguments
mis()
margin-inline-start arguments
mie()
margin-inline-end arguments
//// Paddings
// block
pb()
padding-block arguments
pbs()
padding-block-start arguments
pbe()
padding-block-end arguments
// inline
pi()
padding-inline arguments
pis()
padding-inline-start arguments
pie()
padding-inline-end arguments
// Source
fs()
font-size arguments
// Example
@import 'arbalet'
.myelement
fs 1.5rem
// Source
fclamp()
font-size clamp(unquote(join(',', arguments)))
// Example
@import 'arbalet'
.myelement
fclamp 1rem 12vw 1.5rem
// Source
fw()
font-weight arguments
// Example
@import 'arbalet'
.myelement
fw 700
// Source
ffam()
font-family arguments
// Example
@import 'arbalet'
.myelement
ffam 'Readex Pro', sans-serif
i | italic // font-style: italic;
uc | uppercase // text-transform: uppercase;
lc | lowercase // text-transform: lowercase;
cc | capitalize // text-transform: capitalize;
u | underline // text-decoration: underline;
nodeco // text-decoration: none;
now | nowrap // white-space: nowrap;
left // text-align: left;
center // text-align: center;
right // text-align: right;
1rem // if unit, font-size
#0048ff // if color, clr (color)
"Readex Pro" // if string, font-family
// Source
deco()
text-decoration arguments
// Example
@import 'arbalet'
a
deco none
This is probably not what you expect, it creates an underline animation when hovered (and also removes the default text-decoration: underline), by using ::before
pseudo-element
// Example
@import 'arbalet'
.link
underline(left)
You can directly access to the variables.styl
file to implement your variables. Some variables are already defaulted (Soon)
Feel free to ask for new features or to contribute. Consider opening a new issue first, to discuss about it
- word-wrap mixin
- overflow mixins
- better folder structure/file naming
- fade-in/out opacity/pointer-events mixin?
- improve resp() & transforms mixins
- add more custom variables