Solidjs is a new Javascript Framework which introduce the clear concept of fine-grained reactivity system.
Every Component executes once and it is the Hooks and bindings that execute many times as their dependencies update.
In this post i will show how we can combine tailwindcss and solidjs to create simple todo.
For icons i have used heroicons
create new solid js application using vite
npx degit solidjs/templates/js todo
cd todo
pnpm i
setup tailwindcss
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
npx tailwindcss init
src/styles/index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
tailwind.config.js
const { rule } = require("postcss");
module.exports = {
purge: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
darkMode: false, // or 'media' or 'class',
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
};
src/index.jsx
import { render } from "solid-js/web";
import "./styles/index.css";
import App from "./App";
render(App, document.getElementById("root"));
src/components/Button.jsx
function Button(props) {
return (
<button
onClick={props.onClick}
class={`bg-${props.bg}-500 text-${props.bg}-50 hover:bg-${props.bg}-700 focus:outline-none focus:ring-2 focus:ring-${props.bg}-600 focus:ring-opacity-50 px-1 py-1 md:px-4 md:py-2 rounded-lg ${props.class}`}
>
{props.children}
</button>
);
}
export default Button;
src/components/InputField.jsx
function InputField(props) {
return (
<input
type="text"
class={`border-2 border-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-600 px-1 py-1 md:px-2 md:py-2 rounded-lg ${props.class}`}
onInput={props.onInput}
value={props.value}
/>
);
}
export default InputField;
src/components/CheckBox.jsx
function CheckBox(props) {
return (
<input
type="checkbox"
checked={props.checked}
onChange={props.onChange}
class="w-4 h-4 md:w-6 md:h-6 flex-shrink-0"
/>
);
}
export default CheckBox;
src/components/Navbar.jsx
function Navbar() {
return (
<nav className="flex items-center justify-between px-2 py-4 bg-gray-100">
<div>
<h6 class="text-2xl font-bold">SolidJs Todo App</h6>
</div>
<ul>
<li>
<a
href="https://github.com/harshmangalam/solidjs-tailwindcss-todo"
class="flex items-center space-x-2 bg-black text-white rounded-full p-1 md:px-4 md:py-2"
>
<svg fill="currentColor" class="h-6 w-6 text-white ">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12 2C6.477 2 2 6.463 2 11.97c0 4.404 2.865 8.14 6.839 9.458.5.092.682-.216.682-.48 0-.236-.008-.864-.013-1.695-2.782.602-3.369-1.337-3.369-1.337-.454-1.151-1.11-1.458-1.11-1.458-.908-.618.069-.606.069-.606 1.003.07 1.531 1.027 1.531 1.027.892 1.524 2.341 1.084 2.91.828.092-.643.35-1.083.636-1.332-2.22-.251-4.555-1.107-4.555-4.927 0-1.088.39-1.979 1.029-2.675-.103-.252-.446-1.266.098-2.638 0 0 .84-.268 2.75 1.022A9.606 9.606 0 0112 6.82c.85.004 1.705.114 2.504.336 1.909-1.29 2.747-1.022 2.747-1.022.546 1.372.202 2.386.1 2.638.64.696 1.028 1.587 1.028 2.675 0 3.83-2.339 4.673-4.566 4.92.359.307.678.915.678 1.846 0 1.332-.012 2.407-.012 2.734 0 .267.18.577.688.48C19.137 20.107 22 16.373 22 11.969 22 6.463 17.522 2 12 2z"
></path>
</svg>
<span class="hidden md:block">Github</span>
</a>
</li>
</ul>
</nav>
);
}
export default Navbar;
src/App.jsx
import { createEffect, createSignal, For } from "solid-js";
import { createStore } from "solid-js/store";
import Navbar from "./components/Navbar";
import InputField from "./components/InputField";
import Button from "./components/Button";
import CheckBox from "./components/CheckBox";
function App() {
const [store, setStore] = createStore({
todos: [],
});
const [text, setText] = createSignal("");
createEffect(() =>
console.log(
store.todos.map((s) => ({ text: s.text, completed: s.completed }))
)
);
return (
<div class="min-h-screen flex flex-col justify-between space-y-4">
<header>
<Navbar />
</header>
<main class="container md:max-w-lg mx-auto flex-grow">
<section class=" flex items-center space-x-2 bg-purple-100 px-2 md:px-4 py-6">
<InputField
value={text()}
onInput={(e) => setText(e.currentTarget.value)}
/>
<Button
bg="purple"
class="flex items-center space-x-1"
onClick={() => {
setStore({
todos: [
...store.todos,
{
text: text(),
completed: false,
},
],
});
setText("");
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/>
</svg>
<span>Add</span>
</Button>
</section>
<section class="py-4 grid grid-cols-1 gap-2">
<For each={store.todos}>
{(todo, i) => {
const { completed, text } = todo;
return (
<div class="flex items-center space-x-2 bg-green-100 px-2 md:px-4 py-4">
<CheckBox
checked={completed}
onChange={(e) =>
setStore("todos", i(), { completed: e.target.checked })
}
/>
<InputField
value={text}
onInput={(e) =>
setStore("todos", i(), { text: e.currentTarget.value })
}
/>
<Button
bg="red"
class="flex items-center space-x-1"
onClick={() =>
setStore("todos", (t) => [
...t.slice(0, i()),
...t.slice(i() + 1),
])
}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 text-white"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
</Button>
</div>
);
}}
</For>
</section>
</main>
<footer class="py-2 bg-gray-100">
<p class="text-center">SolidJs Todo - {new Date().getFullYear()}</p>
</footer>
</div>
);
}
export default App;
github repo here
Top comments (0)