Getting started
Overview
Moon Design System is a collection of reusable components set up and grouped according to simple and clear standards. Moon DS component collection is the single source of truth that can be used to build any number of applications.
Requirements
Moon Design System can be used for new and existing Phoenix project that uses LiveView
Moon Surface components can be used from SLIM and EEX templates , but recommended format is Surface v0.9.x + Tailwind + Moon Surface Components
NB! You need to be using the latest version of Tailwind CSS for the system to work.
Installing elixir, erlang & node.js
We do use adsf here. Add .tool-versions file to the root of your projects:
# .tool-versions erlang 25.2 elixir 1.14.1 nodejs 14.17.6
And run asdf install
Project creating
Create new Phoenix project (if needed) with LiveView enabled. Do not fetch dependencies.
mix archive install hex phx_new
mix phx.new my_super_app --live
cd my_super_app
Installing dependencies
Add Moon Library to mix.exs deps section:
# mix.exs ... {:moon, git: "[email protected]:coingaming/moon.git"} # or {:moon, git: "https://github.com/coingaming/moon.git"}
and fetch dependencies.
mix deps.get
Make sure your phoenix* dependenciesversions do not conflict with the same in moon library.
Add surface & esbuild configurations to the project's confix.exs:
# config/config.exs ... import_config "../deps/moon/config/surface.exs" config :surface, :components, [ # put here your app configs for surface ] config :esbuild, version: "0.16.4", default: [ args: ~w(js/app.js --bundle --target=es2016 --outdir=../priv/static/assets), cd: Path.expand("../assets", __DIR__), env: %{"NODE_PATH" => "/root/project/lib/moon_web/components/deps:./node_modules"} ]
Compile project and dependencies
mix compile
Initialize Surface as described here. Please make sure that surface compiler is configured.
mix surface.init
Moon CSS/JS assets adding
Add two Plug.Static plugs to your endpoint.ex
# lib/my_super_app/web/endpoint.ex ... plug(Plug.Static, at: "/moon/assets", from: :moon, gzip: true, only: ~w(assets themes images fonts svgs favicon.ico robots.txt), cache_control_for_etags: "public, max-age=86400" ) plug(Plug.Static, at: "/moon_icons/", from: :moon_icons, gzip: true, cache_control_for_etags: "public, max-age=86400" ) ...
Import Moon Surface css and themes to project's assets/app.css:
/* assets/css/app.css */ /* this is a default theme - used on surface.moon.io feel free to copy and modify it */ @import '../../deps/moon/priv/static/themes/moon.css'; /* Not really required. Only few classes for components are from there. All tailwind imports are already there, so you can remove them from your own app.css also can import _components.css instead @import '../../deps/moon/assets/css/_components.css'; */ @import '../../deps/moon/assets/css/app.css';
Copy assets/package.json from deps/moon folder, or take two sections from there:
scripts:
# assets.package.json "scripts": { "deploy": "NODE_ENV=production tailwindcss -i css/app.css -o ../priv/static/assets/app.css --postcss --minify", "build": "tailwindcss -i css/app.css -o ../priv/static/assets/app.css --postcss", "watch": "tailwindcss -i css/app.css -o ../priv/static/assets/app.css --postcss --watch" },
dependencies:
# assets.package.json "dependencies": { "@tailwindcss/forms": "^0.4.0", "autoprefixer": "^10.4.2", "postcss": "^8.4.5", "postcss-import": "^14.0.2", "tailwindcss": "^3.1.7", "@popperjs/core": "^2.11.6" },
Create file assets/postcss.config.js
// assets/postcss.config.js module.exports = { plugins: { 'postcss-import': {}, tailwindcss: {}, autoprefixer: {} } }
Create file assets/tailwind.config.js
// assets/tailwind.config.js const tailwind_config = require("../deps/moon/assets/tailwind.config.js"); tailwind_config.content = [ "../lib/**/*.ex", "../lib/**/*.heex", "../lib/**/*.eex", "./js/**/*.js", "../deps/moon/lib/**/*.ex", "../deps/moon/lib/**/*.heex", "../deps/moon/lib/**/*.eex", "../deps/moon/assets/js/**/*.js", ]; module.exports = tailwind_config;
Edit your assets/js/app.js
// assets/js/app.js ... import Hooks from "./_hooks" // the next line should be added import MoonHooks from "../../deps/moon/assets/js/hooks" let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}, hooks: { ...MoonHooks, // here we do use imported hooks ...Hooks }})
Add/modify assets-related aliases in your mix.exs file
# mix.exs ... defp aliases do [ setup: ["deps.get", "assets.setup", "assets.build"], "assets.setup": ["cmd --cd assets npm i", "esbuild.install --if-missing"], "assets.build": ["cmd --cd assets npm run build", "esbuild default"], "assets.deploy": [ "cmd --cd assets npm run deploy", "NODE_ENV=production esbuild default --minify", "phx.digest" ] ] end
Setup assets
mix assets.setup
Add theme-related class (find it in imported theme CSS file) and direction related attribute to your root HTML component, e.g. body in lib/my_super_app_web/components/layouts/root.html.heex
<!-- lib/my_super_app_web/components/layouts/root.html.heex --> <!-- class name should be taken from theme imported --> ... <body class="... theme-moon-light" dir="ltr"> ...
Run project
mix phx.server