@tenoxui/coreThis repository contain a core component of TenoxUI CSS Framework.
inline-styleCSS properties (including prefixes) and valuesCSS variable class names and properties:hover and :focus pseudo classExample for observing only single element.
// create tenoxui instance
const tx = new makeTenoxUI({
// after adding the element, you can actually add classNames directly in the element's class attribute
element: document.querySelector(".my-element"),
property: {
bg: "background",
text: "color",
p: "padding",
px: ["paddingLeft", "paddingRight"]
}
});
// add styles
tx.applyMultiStyles("p-1rem bg-black text-#ccf654");
// or use DOM
tx.htmlElement.classList.add("p-1rem");
tx.htmlElement.classList.add("bg-black");
tx.htmlElement.classList.add("text-#ccf654");
It's not utility-first if it cannot access the element's className directly. So, here's the example :
// this is not only selectors you can use, you can always create something else :p
const selectors = document.querySelectorAll("*[class]");
selectors.forEach(selector => {
const styler = new makeTenoxUI({
element: selector,
property: {
bg: "background",
text: "color",
p: "padding",
br: "border-radius",
mt: "marginTop"
} // add your type and property here
});
selector.classList.forEach(className => {
// this method will every single className and execute it one by one
styler.applyStyles(className);
});
});
Then, inside your html :
<div class="bg-black text-yellow p-1rem br-6px">Hello</div>
npm i @tenoxui/core --save-dev
Add it by importing the makeTenoxUI :
import { makeTenoxUI } from "@tenoxui/core";
<script src="https://cdn.jsdelivr.net/npm/@tenoxui/core"></script>
tenoxui/core only exporting class makeTenoxUI.
makeTenoxUI will take 4 parameters defined as an object :
class makeTenoxUI {
constructor({ element, property = {}, values = {}, breakpoint = [], classes = {} }: MakeTenoxUIParams) {
this.htmlElement = element instanceof HTMLElement ? element : element[0];
this.styleAttribute = property;
this.valueRegistry = values;
this.breakpoints = breakpoint;
this.classes = classes;
}
// selectors
private readonly htmlElement: HTMLElement;
// types and properties
private readonly styleAttribute: Property;
// stored values
private readonly valueRegistry: DefinedValue;
// breakpoints
private readonly breakpoints: Breakpoint[];
// classes
private readonly classes: Classes;
/* ... */
}
elementThis parameter is where the style should applied, you can define the selector here and this is where the style will be applied.
Usage :
new makeTenoxUI({
element: document.querySelector(".my-element")
/* ... */
});
propertyOf course we need to define the CSS properties to work with. This parameter is responsible for handling the type (the CSS property's handler) and property. There are several property you can define :
This is the basic example for defining the type and property :
const props = {
// type: property
m: "margin",
p: "padding"
};
Usage :
<div class="m-1rem p-8px"></div>
Same as :
div {
margin: 1rem;
padding: 8px;
}
You can use an array of property to add same value into multiple propeties, here's the example :
const props = {
d: "display",
size: ["width", "height"],
"flex-parent": ["alignItems", "justify-content"], // you can define with both `camelCase` or `kebab-case`
transition: ["transition", "-webkit-transition"]
};
Usage :
<div class="d-flex flex-parent-center box-100px">hello</div>
Same as :
div {
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
}
-- before the property's name, and it will treated as CSS variable property. Example :const props = {
color: "--my-color",
text: "color"
};
Usage :
<div class="color-blue text-$my-color"></div>
Same as :
div {
--my-color: blue;
color: var(--my-color);
}
You can also define custom value. You can set where the value will take place. Example :
const props = {
gradient: {
property: "background",
value: "linear-gradient(to right, {value}, blue, {value})"
},
blur: {
property: "filter",
value: "blur({value})"
}
};
The {value} will replaced with the value from your class names.
Usage :
<div class="gradient-red blur-10px"></div>
Same as :
div {
background: linear-gradient(to right, red, blue, red);
filter: blur(10px);
}
valuesYou can define your values that class names can use. Example :
new makeTenoxUI({
element: "...",
property: {
w: "width",
p: "padding"
},
values: {
full: "100%",
size: "200px",
2: "4px"
}
/* ... */
});
Usage :
<body class="w-full">
<div class="p-2">Hello</div>
</body>
Same as :
body {
width: 100%;
}
div {
padding: 4px;
}
breakpointThis is where you will store the breakpoints. Example :
new makeTenoxUI({
property: {
bg:"background"
}
breakpoint: [
{ name: "max-md", min: 0, max: 678 },
{ name: "md", min: 678 }
]
});
Usage :
<div class="bg-blue max-md:bg-blue md:bg-red">hello</div>
If you want to use the responsive feature, you must use it like the code above, or else it will have some issues, like the styles not handled properly and else. See more.
interface MakeTenoxUIParams {
element: HTMLElement | NodeListOf<HTMLElement>;
property: Property;
values?: DefinedValue;
breakpoint?: Breakpoint[];
classes?: Classes;
}
type CSSProperty = keyof CSSStyleDeclaration;
type CSSPropertyOrVariable = CSSProperty | `--${string}`;
type GetCSSProperty = CSSPropertyOrVariable | CSSPropertyOrVariable[];
type Property = { [type: string]: GetCSSProperty | { property?: GetCSSProperty; value?: string } };
type Breakpoint = { name: string; min?: number; max?: number };
type DefinedValue = { [type: string]: { [value: string]: string } | string };
type Classes = { [property in CSSPropertyOrVariable]?: { [className: string]: string } };
addStyleThis method will handle all the defined type, property, value, all styling logic, and the styles rules from the class name.
public addStyle(type: string, value: string, unit: string): void {}
Usage :
const styler = new makeTenoxUI();
styler.addStyle("p", "10", "px");
styler.addStyle("m", "1", "rem");
applyStylesThis method will get all class names possibilities and matched it using regexp.
public applyStyles(className: string): void {}
Note: This method will get
onlyone class name!
Usage :
const styler = new makeTenoxUI();
styler.applyStyles("p-10px");
styler.applyStyles("m-1rem");
makeTenoxUI usage example for creating a styles.
Add a simple element with class :
<div class="my-element">Hello</div>
Then, add the styler instance :
// define selector
const selector = document.querySelector(".my-element");
// create tenoxui instance
const styler = new makeTenoxUI({
element: selector,
property: { bg: "background", text: "color" }
});
// apply the styles
styler.applyStyles("bg-red");
styler.applyStyles("text-blue");
Maybe there will be more than one element with same classes :
<main>
<div class="my-element">Hello</div>
<div class="my-element">World</div>
</main>
Then, add the styler instance :
// define selector
const selectors = document.querySelectorAll(".my-element");
selectors.forEach(selector => {
// create tenoxui instance
const styler = new makeTenoxUI({
element: selector,
property: { bg: "background", text: "color" }
});
// apply the styles
styler.applyStyles("bg-red");
styler.applyStyles("text-blue");
});
Creating utility-first compability or auto styler for your project, it will automatically scan the element's classnames and give the styles. By following this steps, you can create your own css framework 🗿 :
First, let's create some html elements with utility-first class names :
<main>
<div class="bg-red p-10px br-6px">Hello</div>
<div class="bg-blue p-2rem br-1rem">World</div>
</main>
types and propertiesLet's add some types and properties you need :
const props = {
bg: "background",
p: "padding",
br: "borderRadius"
};
After defining some types, you need to create a selector from the defined types key's name :
const classes = Object.keys(props).map(className => `[class*="${className}-"]`);
const selectors = document.querySelectorAll(classes.join(", "));
It's done. So, let's create the styler instance from the components we define earlier :
First, we will iterate the selectors :
selectors.forEach(selector => {
/* ... */
});
Adding styler instance :
const styler = new makeTenoxUI({
// get each selector
element: selector,
// the propeties we define earlier
property: props
});
Finally, get all element's class name and applying each styles from the element's classList :
selector.classList.forEach(className => {
styler.applyStyles(className);
});
Or, you can be more specific for scanning only the possible classes :
selector.classList.forEach(className => {
const strippedClassName = className.replace(/^[a-z-]*:/, "");
const prefix = strippedClassName.split("-")[0];
if (props[prefix]) {
styler.applyStyles(className);
console.log(className);
}
});
The final code will looks like this :
const props = {
bg: "background",
text: "color",
p: "padding",
br: "border-radius",
mt: "marginTop"
};
const classes = Object.keys(props).map(className => `[class*="${className}-"]`);
const selectors = document.querySelectorAll(classes.join(", "));
selectors.forEach(selector => {
const styler = new makeTenoxUI({
element: selector,
property: props
});
selector.classList.forEach(className => {
styler.applyStyles(className);
});
});
And done ✅. Easy right? :)