1.0.2 • Published 1 year ago

jetpak-css v1.0.2

Weekly downloads
54
License
ISC
Repository
-
Last release
1 year ago

jetpak-css

A dynamic css injection tool for javascript web-apps

A free powerup to launch your app off the ground.


Contents


Usage

  1. Install Jetpak
npm install --save jetpak-css
  1. Initialize the global JetpakCss at the top level of your app structure.
  2. Use the css function throughout your app to dynamically load css into your app.
  3. Run the update function to inject newly added styles into the DOM.

Global Class

const jetpak = new JetpakCss(InitializationConfig)

InitializationConfig:

KeyDescriptionType
themeTheme Configuration ObjectThemeConfig (see below)
baseStyleDefault style object to initialize withStyleConfig (see below)

Usage:

Initialize the class in the root js file of your app so it begins at runtime in the browser:

import { JetpakCss } from 'jetpak-css'
import theme from './theme'

const jetpak = new JetpakCss({
    theme,
    style: {
        // StyleObject containing styles like reset.css and other non-component-specific code
    },
})


// ...the rest of your app initialization here

Initializing the JetpakCss class creates a globally accessible instance of Jetpak. From here, invocations of css() adds to the globals styles stored in this class. Later, running the update function will stringify and inject the style it into the head of your app. This will add window.__JETPAK__ but you shouldn't need to look at this, except when debugging your styles.

See StyleObject


Adding css

const classes = css(StyleObject)

This is the function you use most with Jetpak. It takes in a StyleObject which is an object that Jetpak parses to generate a css string. It's similar to other css-in-javascript solutions, and takes some ways of doing things from sass/scss.

css() returns usable classes

This function returns an object of ClassNames that generated when the css parsed. This object will not contain anything but classnames.

For example, you could have a component structured like this:

const classes = css({
    arcticMonkeys: {
        color: 'blue',

        '&:hover': {
            color: 'black',
        },
        '> alexTurner': {
            fontWeight: 200,
        }
    },
    span: {
        display: 'inline-block',
    },
})

return [
    div({
        class: classes.arcticMonkeys,
        render: [
            div({
                class: classes.alexTurner,
                render: 'Tranquility Base'
            })
        ]
    }),
    span('Hotel & Casino')
]

( This example uses the arsnl app framework )

You would see this as the css output (this injected into the <head> of the page on the next jetpak.update()):

.arctic-monkeys {
    color: blue;
}
.arctic-monkeys:hover {
    color: black;
}
.arctic-monkeys > .alex-turner {
    fontWeight: 200,
}
span {
    display: inline-block;
}

and this as the html output:

<div class="arctic-monkeys">
    <div class="alex-turner">
        Tranquility Base
    </div>
</div>
<span>
    Hotel & Casino
</span>

StyleObject

The StyleObject is the config of style properties that gets passed into the css() function.

A simple example:

import { css } from 'jetpak-css'

const classes = css({ body: { background: 'red' }})

A complex example:

import { css, px, em, colors } from 'jetpak-css'

const classes = css({
    appLogo: {
        margin: px(100),

        svg: {
            height: px(150),
            width: px(150),
        },
    },
    button: {
        padding: em(1),
        color: colors.skyblue,

        '&:hover, &:focus': {
            color: colors.steelblue,
        },
        '&:not(:disabled), &:not(.disabled)': {
            cursor: 'pointer',
        },
    },
    '@media only screen (max-width: 600px)': {
        button: {
            padding: em(0.5),
        }
    }
})
FeatureInput ExampleOutput ExampleNotes
Tag Namesdiv, span, body, etc...div, span, body, etc...Jetpak knows what valid html5 tag names look like so it doesn't turn them into classes accidentally.
Nested Selectors{ ul: { li: { listStyle: 'none'}}}ul li { list-style: none; }You can nest selectors like scss and jetpak will figure out what css you mean to generate.
&{ button: { &:disabled: { opacity: 0.8, &.old { color: 'yellow' }}}}button:disabled { opacity: 0.8; } button:disabled.old { color: yellow; }Any selector starting with an & is expected to be an extension of its parent. When generating the style, it will replace the & with it's parent selector.
Camel To Kebab{ '#someIdHere': { fontWeight: 500 } }#some-id-here { font-weight: 500; }Class names, IDs, and css property names all get turned from camel to kebab case, if they weren't already that way.
Attribute Selectors{ '[disabled="true"] someClassHere': { color: '#ccc' } }[disabled="true"] .some-class-here { color: #ccc; }Attribute selectors are maintained as typed, and aren't altered by the parser.
Media Queries{ '@media only screen (max-width: 940px)': { body: { color: 'green' } } }@media only screen (max-width: 940px) { body { color: green; } }Any key starting with @media must be a top-level property in the style object hierarchy and are not altered by the parser. Media queries are to the end of the stylesheet to come last syntactically.

With Theme Support

You can get quick access to the theme object in the initialized JetpakCss global class by passing in a StyleObject generator function. The only argument passed into it is the theme.

import { css } from 'jetpak-css'

const classes = css((theme) => {
    return {
        body: {
            background: theme.appBackground,
            color: theme.appTextColor,
        }
    }
})

You can put whatever you want in the theme object. Jetpak doesn't do anything with it but pass it into each css function call if the config object it receives is passed in the form of a function.


Update the DOM

As you add css({}) invocations throughout your app the JetpakCss Class will collect all of your style into one object. When your app is rendering a new markup change to the DOM you'll want to call the update() method on the JetpakCss Class. This will compile all of the css and inject it into the style-tag it generated in the <head> of your site. If no style has changed, it will not update the DOM to avoid unnecessary repainting.

// This is the main app file of an arsnl app
import { App } from 'arsnl'
import { getBaseStyles, createTheme } from 'arsnl-kit'
import { JetpakCss } from 'jetpak-css'

import themeConfig from './theme'
import rootComponent from './App'
import routes from './routes'

const theme = createTheme(themeConfig)
const style = getBaseStyles(theme)
const jetpak = new JetpakCss({ theme, style })

new App({
    id: 'app-root',
    routes,
    component: rootComponent,
    onAfterRender: () => {
        jetpak.update()
    },
})

( This example uses the arsnl app framework )

Note: onAfterRender in this example would be run at the end of every render digest cycle, similar to componentDidMount and componentDidUpdate in a ReactComponent.


Debugging


Downsides & Disclaimers

  • Cases for parsing selectors in the StyleObject are probably missing.
  • Calling jetpak.update() could become a big-memory-operation with large apps, yet to be officially tested seeing as this package is new.

Helper Exports


Full Examples

1.0.2

1 year ago

1.0.1

3 years ago

1.0.0

3 years ago