From c6de8dce34dd50bba074448a17d49563a0630d0e Mon Sep 17 00:00:00 2001 From: Ivan Reshetnikov Date: Sat, 6 Jul 2024 21:25:42 +0500 Subject: [PATCH] chore: remove tailwind I prefer plain css files over tailwind. I converted some default components, but it's still a work in progress. --- assets/css/app.css | 51 ++- assets/css/core_components.css | 363 ++++++++++++++++++ assets/js/app.js | 1 + assets/tailwind.config.js | 75 ---- config/config.exs | 12 - config/dev.exs | 3 +- .../components/core_components.ex | 133 +++---- .../components/layouts/app.html.heex | 12 +- .../components/layouts/root.html.heex | 2 +- mix.exs | 10 +- mix.lock | 1 - 11 files changed, 481 insertions(+), 182 deletions(-) create mode 100644 assets/css/core_components.css delete mode 100644 assets/tailwind.config.js diff --git a/assets/css/app.css b/assets/css/app.css index 378c8f9..035dc40 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -1,5 +1,48 @@ -@import "tailwindcss/base"; -@import "tailwindcss/components"; -@import "tailwindcss/utilities"; +@import "./core_components.css"; -/* This file is for your main application CSS */ +:root { + --bg: #13151a; + --accent: #b283e5; +} + +html { + font-family: Georgia, serif; + background-color: var(--bg); + background-size: 224px; + color: white; + font-size: 16px; +} + +*::selection { + background-color: var(--accent); + color: var(--bg); +} + +a { + color: var(--accent); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +h1 { + margin-top: 36px; + margin-bottom: 24px; +} + +h2 { + margin-top: 32px; +} + +header, +main, +footer { + justify-content: center; +} +.limiter { + max-width: 800px; + width: 100%; + margin: auto; +} diff --git a/assets/css/core_components.css b/assets/css/core_components.css new file mode 100644 index 0000000..787ecd4 --- /dev/null +++ b/assets/css/core_components.css @@ -0,0 +1,363 @@ +.label { + display: block; + font-size: 0.875rem; + font-weight: 600; + line-height: 1.5rem; +} + +.error { + display: flex; + margin-top: 0.75rem; + font-size: 0.875rem; + line-height: 1.5rem; + gap: 0.75rem; +} + +.list { + margin-top: 3.5rem; +} + +.list-description { + margin-top: -1rem; + margin-bottom: -1rem; + border-top-width: 1px; +} + +.list-item { + display: flex; + padding-top: 1rem; + padding-bottom: 1rem; + font-size: 0.875rem; + line-height: 1.5rem; + gap: 1rem; +} + +@media (min-width: 640px) { + .list-item { + gap: 2rem; + } +} + +.list-item-title { + flex: none; + width: 25%; +} + +.list-item-description { +} + +.modal { + display: none; + position: relative; + z-index: 50; +} + +.modal-bg { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 300ms; +} + +.modal-body { + overflow-y: auto; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + justify-content: center; + align-items: center; + padding: 1rem; + width: 100%; + max-width: 48rem; +} + +@media (min-width: 640px) { + .modal-body { + padding: 1.5rem; + } +} + +@media (min-width: 1024px) { + .modal-body { + padding-top: 2rem; + padding-bottom: 2rem; + } +} + +.modal-close-button-container { + position: absolute; + right: 1.25rem; + top: 1.5rem; +} + +.modal-close-button { + padding: 0.75rem; + margin: -0.75rem; + flex: none; + opacity: 0.2; +} + +.modal-close-button:hover { + opacity: 0.4; +} + +.modal-close-button-icon { + width: 1.25rem; + height: 1.25rem; +} + +.modal-container { + display: none; + position: relative; + padding: 3.5rem; + border-radius: 1rem; + box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + background-color: #ffffff; + transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 300ms; + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); +} + +.flash { + position: fixed; + top: 0.5rem; + right: 0.5rem; + z-index: 50; + padding: 0.75rem; + margin-right: 0.5rem; + border-radius: 0.5rem; + box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + width: 20rem; +} + +@media (min-width: 640px) { + .flash { + width: 24rem; + } +} + +.flash-title { + display: flex; + gap: 0.375rem; + align-items: center; + font-size: 0.875rem; + font-weight: 600; + line-height: 1.5rem; +} + +.flash-close-button { + position: absolute; + top: 0.25rem; + right: 0.25rem; + padding: 0.5rem; +} + +.flash-close-button-icon { + width: 1.25rem; + height: 1.25rem; + opacity: 0.4; +} + +.simple-form { + margin-top: 2rem; + background-color: #ffffff; +} + +.simple-form-action { + display: flex; + margin-top: 0.5rem; + gap: 1.5rem; + justify-content: space-between; + align-items: center; +} + +.button { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + border-radius: 0.5rem; + font-size: 0.875rem; + font-weight: 600; + line-height: 1.5rem; + color: #ffffff; +} + +.input { + display: block; + margin-top: 0.5rem; + border-radius: 0.5rem; + width: 100%; +} + +@media (min-width: 640px) { + .input { + font-size: 0.875rem; + line-height: 1.5rem; + } +} + +.textarea { + display: block; + margin-top: 0.5rem; + border-radius: 0.5rem; + width: 100%; +} + +@media (min-width: 640px) { + .textarea { + font-size: 0.875rem; + line-height: 1.5rem; + } +} + +.select { + display: block; + margin-top: 0.5rem; + border-radius: 0.375rem; + border-width: 1px; + border-color: #D1D5DB; + width: 100%; + background-color: #ffffff; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); +} + +@media (min-width: 640px) { + .select { + font-size: 0.875rem; + line-height: 1.25rem; + } +} + +.checkbox-label { + display: flex; + gap: 1rem; + align-items: center; + font-size: 0.875rem; + line-height: 1.5rem; +} + +.checkbox-input { + border-radius: 0.25rem; +} + +.show { + transition-property: all; + transition-duration: 300ms; + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + --transform-translate-y: 1rem; + opacity: 0; + opacity: 1; +} + +@media (min-width: 640px) { + .show { + --transform-scale-x: 1; + --transform-scale-y: 1; + --transform-translate-y: 0; + } +} + +.hide { + transition-property: all; + transition-duration: 300ms; + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); + --transform-translate-y: 1rem; + opacity: 0; + opacity: 1; +} + +@media (min-width: 640px) { + .hide { + --transform-scale-x: .95; + --transform-scale-y: .95; + --transform-translate-y: 0; + } +} + +.show-modal { + transition-property: all; + transition-duration: 300ms; + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + +.hide-modal { + transition-property: all; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); + opacity: 1; +} + +.back-nav-link { + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 600; + line-height: 1.5rem; +} + +.table-container { + overflow-y: auto; + padding-left: 1rem; + padding-right: 1rem; +} + +@media (min-width: 640px) { + .table-container { + overflow: visible; + padding-left: 0; + padding-right: 0; + } +} + +.table { + margin-top: 2.75rem; + width: 40rem; +} + +@media (min-width: 640px) { + .table { + width: 100%; + } +} + +.thead { + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 1.5rem; + text-align: left; +} + +.th { + padding: 0; + padding-bottom: 1rem; + padding-right: 1.5rem; + font-weight: 400; +} + +.th-actions { + position: relative; + padding: 0; + padding-bottom: 1rem; +} + +.tbody { + position: relative; + border-top-width: 1px; + border-top-width: 1px; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 1.5rem; +} + +.td { + position: relative; + padding: 0; +} diff --git a/assets/js/app.js b/assets/js/app.js index d5e278a..4baf040 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -21,6 +21,7 @@ import "phoenix_html" import {Socket} from "phoenix" import {LiveSocket} from "phoenix_live_view" import topbar from "../vendor/topbar" +import "../css/app.css" let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") let liveSocket = new LiveSocket("/live", Socket, { diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js deleted file mode 100644 index 5a1f710..0000000 --- a/assets/tailwind.config.js +++ /dev/null @@ -1,75 +0,0 @@ -// See the Tailwind configuration guide for advanced usage -// https://tailwindcss.com/docs/configuration - -const plugin = require("tailwindcss/plugin") -const fs = require("fs") -const path = require("path") - -module.exports = { - content: [ - "./js/**/*.js", - "../lib/comfycamp_web.ex", - "../lib/comfycamp_web/**/*.*ex" - ], - theme: { - extend: { - colors: { - brand: "#FD4F00", - } - }, - }, - plugins: [ - require("@tailwindcss/forms"), - // Allows prefixing tailwind classes with LiveView classes to add rules - // only when LiveView classes are applied, for example: - // - //
- // - plugin(({addVariant}) => addVariant("phx-no-feedback", [".phx-no-feedback&", ".phx-no-feedback &"])), - plugin(({addVariant}) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])), - plugin(({addVariant}) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])), - plugin(({addVariant}) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"])), - - // Embeds Heroicons (https://heroicons.com) into your app.css bundle - // See your `CoreComponents.icon/1` for more information. - // - plugin(function({matchComponents, theme}) { - let iconsDir = path.join(__dirname, "../deps/heroicons/optimized") - let values = {} - let icons = [ - ["", "/24/outline"], - ["-solid", "/24/solid"], - ["-mini", "/20/solid"], - ["-micro", "/16/solid"] - ] - icons.forEach(([suffix, dir]) => { - fs.readdirSync(path.join(iconsDir, dir)).forEach(file => { - let name = path.basename(file, ".svg") + suffix - values[name] = {name, fullPath: path.join(iconsDir, dir, file)} - }) - }) - matchComponents({ - "hero": ({name, fullPath}) => { - let content = fs.readFileSync(fullPath).toString().replace(/\r?\n|\r/g, "") - let size = theme("spacing.6") - if (name.endsWith("-mini")) { - size = theme("spacing.5") - } else if (name.endsWith("-micro")) { - size = theme("spacing.4") - } - return { - [`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`, - "-webkit-mask": `var(--hero-${name})`, - "mask": `var(--hero-${name})`, - "mask-repeat": "no-repeat", - "background-color": "currentColor", - "vertical-align": "middle", - "display": "inline-block", - "width": size, - "height": size - } - } - }, {values}) - }) - ] -} diff --git a/config/config.exs b/config/config.exs index c73e937..634e180 100644 --- a/config/config.exs +++ b/config/config.exs @@ -41,18 +41,6 @@ config :esbuild, env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)} ] -# Configure tailwind (the version is required) -config :tailwind, - version: "3.4.0", - comfycamp: [ - args: ~w( - --config=tailwind.config.js - --input=css/app.css - --output=../priv/static/assets/app.css - ), - cd: Path.expand("../assets", __DIR__) - ] - # Configures Elixir's Logger config :logger, :console, format: "$time $metadata[$level] $message\n", diff --git a/config/dev.exs b/config/dev.exs index 535cf1f..7849e68 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -25,8 +25,7 @@ config :comfycamp, ComfycampWeb.Endpoint, debug_errors: true, secret_key_base: "6TPjZ6GJcs5FerDbAdr2pHRL5JASsi04nah6WbeQfbPmnuHz0lAUu4e60HNBkKVv", watchers: [ - esbuild: {Esbuild, :install_and_run, [:comfycamp, ~w(--sourcemap=inline --watch)]}, - tailwind: {Tailwind, :install_and_run, [:comfycamp, ~w(--watch)]} + esbuild: {Esbuild, :install_and_run, [:comfycamp, ~w(--sourcemap=inline --watch)]} ] # ## SSL Support diff --git a/lib/comfycamp_web/components/core_components.ex b/lib/comfycamp_web/components/core_components.ex index 6212324..77dfe6b 100644 --- a/lib/comfycamp_web/components/core_components.ex +++ b/lib/comfycamp_web/components/core_components.ex @@ -48,42 +48,38 @@ defmodule ComfycampWeb.CoreComponents do phx-mounted={@show && show_modal(@id)} phx-remove={hide_modal(@id)} data-cancel={JS.exec(@on_cancel, "phx-remove")} - class="relative z-50 hidden" + class="modal" > - """ @@ -202,9 +198,9 @@ defmodule ComfycampWeb.CoreComponents do def simple_form(assigns) do ~H""" <.form :let={f} for={@for} as={@as} {@rest}> -
+
<%= render_slot(@inner_block, f) %> -
+
<%= render_slot(action, f) %>
@@ -231,8 +227,7 @@ defmodule ComfycampWeb.CoreComponents do