feat: Use tailwind for generated templates

This commit is contained in:
Robert Prehn 2020-09-08 09:20:48 -05:00
parent 35e3c6a608
commit 97eabcc875
13 changed files with 177 additions and 96 deletions

View file

@ -1,7 +1,7 @@
defmodule Admin.Kaffy.EditorExtension do defmodule Admin.Kaffy.EditorExtension do
def stylesheets(_conn) do def stylesheets(_conn) do
[ [
{:safe, ~s(<link rel="stylesheet" href="/js/css/content-editor.css" />)}, {:safe, ~s(<link rel="stylesheet" href="/css/content-editor.css" />)},
{:safe, ~s(<link rel="stylesheet" href="/css/app.css" />)}, {:safe, ~s(<link rel="stylesheet" href="/css/app.css" />)},
] ]
end end

View file

@ -1,18 +1,19 @@
<div class="ui top padded container"> <div class="p-6 mx-auto max-w-2xl">
<div class="ui grid"> <div class="flex pb-6">
<div class="row"> <div class="w-/12 flex-1 text-4xl">
<div class="eight wide column"> <h1 class="ui header">Edit <%= schema.human_singular %></h1>
<h1 class="ui header">Edit <%= schema.human_singular %></h1>
</div>
<div class="eight wide right aligned column">
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index), class: "ui button" %></span>
</div>
</div> </div>
<div class="w-/12 text-4xl text-right">
<%%= styled_button_link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index)%>
</div>
</div>
<div class="centered row"> <div class="centered row">
<div class="center aligned column"> <div class="center aligned column">
<%%= changeset_error_block(@changeset) %> <%%= changeset_error_block(@changeset) %>
<%%= render "form.html", Map.put(assigns, :action, Routes.<%= schema.route_helper %>_path(@conn, :update, @<%= schema.singular %>)) %> <div class="bg-white shadow rounded px-4 py-6 bg-gray-300">
<%%= render "form.html", Map.put(assigns, :action, Routes.<%= schema.route_helper %>_path(@conn, :update, @<%= schema.singular %>)) %>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -4,7 +4,7 @@
<%= input %> <%= input %>
<% end %> <% end %>
<div> <div>
<%%= submit "Save", class: "ui primary fluid large submit button" %> <%%= styled_button "Save" %>
</div> </div>
</div> </div>
<%% end %> <%% end %>

View file

@ -1,46 +1,52 @@
<div class="ui top padded container"> <div class="p-6">
<div class="ui grid"> <div class="flex pb-6">
<div class="row"> <div class="w-/12 flex-1 text-4xl">
<div class="eight wide column"> <h1 class="px-5 -mb-2 mt-2"><%= schema.human_plural %></h1>
<h1 class="ui header"><%= schema.human_plural %></h1> </div>
</div> <div class="w-/12 text-4xl text-right px-5">
<div class="eight wide right aligned column"> <%%= styled_button_link "New <%= schema.human_singular %>", to: Routes.<%= schema.route_helper %>_path(@conn, :new) %>
<span><%%= link "New <%= schema.human_singular %>", to: Routes.<%= schema.route_helper %>_path(@conn, :new), class: "ui primary button" %></span>
</div>
</div> </div>
</div> </div>
<table class="ui celled table"> <div class="shadow rounded px-1 py-1 bg-white">
<thead> <table class="min-w-full leading-normal">
<tr> <thead>
<%= for {k, _} <- schema.attrs do %> <th><%= Phoenix.Naming.humanize(Atom.to_string(k)) %></th> <tr>
<% end %> <%= for {k, _} <- schema.attrs do %> <th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider"><%= Phoenix.Naming.humanize(Atom.to_string(k)) %></th>
<th></th> <% end %>
</tr> <th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider"></th>
</thead> </tr>
<tbody> </thead>
<%%= case @<%= schema.plural %> do %> <tbody>
<%%= [] -> %> <%%= case @<%= schema.plural %> do %>
<tr> <%%= [] -> %>
<td colspan="<%= schema.attrs |> Enum.count() %>"> <tr>
No results. <td class="px-5 py-5 border-b border-gray-200 bg-white text-sm" colspan="<%= (schema.attrs |> Enum.count()) + 1 %>">
</td> No results.
</tr> </td>
<%%= _ -> %> </tr>
<%%= for <%= schema.singular %> <- @<%= schema.plural %> do %> <%%= _ -> %>
<tr> <%%= for <%= schema.singular %> <- @<%= schema.plural %> do %>
<%= for {k, _} <- schema.attrs do %> <td><%%= <%= schema.singular %>.<%= k %> %></td> <tr>
<% end %> <%= for {k, _} <- schema.attrs do %>
<td> <td class="px-5 py-5 border-b border-gray-200 bg-white text-sm">
<div class="ui list"> <%%= link <%= schema.singular %>.<%= k %>, to: Routes.<%= schema.route_helper %>_path(@conn, :show, <%= schema.singular %>) %>
<span class="item"><%%= link "Show", to: Routes.<%= schema.route_helper %>_path(@conn, :show, <%= schema.singular %>) %></span> </td>
<span class="item"><%%= link "Edit", to: Routes.<%= schema.route_helper %>_path(@conn, :edit, <%= schema.singular %>) %></span> <% end %>
<span class="item"><%%= link "Delete", to: Routes.<%= schema.route_helper %>_path(@conn, :delete, <%= schema.singular %>), method: :delete, data: [confirm: "Are you sure?"] %></span> <td class="px-5 py-5 border-b border-gray-200 bg-white text-sm">
</div> <label class="relative">
</td> ...
</tr> <input type="checkbox" class="hidden hidden-options-toggle">
<%% end %> <div class="hidden absolute right-0 rounded bg-white border shadow-lg py-4 w-48">
<%% end %> <%%= link "Edit", to: Routes.<%= schema.route_helper %>_path(@conn, :edit, <%= schema.singular %>), class: "block px-4 py-2 hover:bg-gray-100" %>
</tbody> <%%= link "Delete", to: Routes.<%= schema.route_helper %>_path(@conn, :delete, <%= schema.singular %>), method: :delete, data: [confirm: "Are you sure?"], class: "text-red-600 block px-4 py-2 hover:bg-gray-100" %>
</table> </div>
</label>
</td>
</tr>
<%% end %>
<%% end %>
</tbody>
</table>
</div>
</div> </div>

View file

@ -1,18 +1,19 @@
<div class="ui top padded container"> <div class="p-6 mx-auto max-w-2xl">
<div class="ui grid"> <div class="flex pb-6">
<div class="row"> <div class="w-/12 flex-1 text-4xl">
<div class="eight wide column"> <h1 class="-mb-2 mt-2"><%= schema.human_singular %></h1>
<h1 class="ui header">New <%= schema.human_singular %></h1>
</div>
<div class="eight wide right aligned column">
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index), class: "ui button" %></span>
</div>
</div> </div>
<div class="w-/12 text-4xl text-right">
<%%= styled_button_link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index)%>
</div>
</div>
<div class="centered row"> <div class="centered row">
<div class="center aligned column"> <div class="center aligned column">
<%%= changeset_error_block(@changeset) %> <%%= changeset_error_block(@changeset) %>
<%%= render "form.html", Map.put(assigns, :action, Routes.<%= schema.route_helper %>_path(@conn, :create)) %> <div class="bg-white shadow rounded px-4 py-6 bg-gray-300">
<%%= render "form.html", Map.put(assigns, :action, Routes.<%= schema.route_helper %>_path(@conn, :create)) %>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,26 +1,26 @@
<div class="ui top padded container"> <div class="p-6 mx-auto max-w-2xl">
<div class="ui grid"> <div class="flex pb-6">
<div class="row"> <div class="w-/12 flex-1 text-4xl">
<div class="eight wide column"> <h1 class="-mb-2 mt-2"><%= schema.human_singular %></h1>
<h1 class="ui header"><%= schema.human_singular %></h1> </div>
</div> <div class="w-/12 text-4xl text-right">
<div class="eight wide right aligned column"> <%%= styled_button_link "Edit", to: Routes.<%= schema.route_helper %>_path(@conn, :edit, @<%= schema.singular %>) %>
<%%= link "Edit", to: Routes.<%= schema.route_helper %>_path(@conn, :edit, @<%= schema.singular %>), class: "ui button primary" %> <%%= styled_button_link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index) %>
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index), class: "ui button" %></span>
</div>
</div> </div>
</div> </div>
<div class="ui segment"> <div class="centered row">
<div class="ui list"> <div class="center aligned column">
<%= for {k, _} <- schema.attrs do %> <div class="bg-white shadow rounded px-4 py-6 bg-white">
<div class="item"> <%= for {k, _} <- schema.attrs do %>
<div class="content"> <div class="item">
<strong><%= Phoenix.Naming.humanize(Atom.to_string(k)) %>:</strong> <div class="content">
<%%= @<%= schema.singular %>.<%= k %> %> <strong><%= Phoenix.Naming.humanize(Atom.to_string(k)) %>:</strong>
<%%= @<%= schema.singular %>.<%= k %> %>
</div>
</div> </div>
</div> <% end %>
<% end %> </div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -4,12 +4,11 @@
style="min-height: 75vh;" style="min-height: 75vh;"
> >
<div <div
class="absolute top-0 w-full h-full bg-center bg-cover" class="absolute top-0 w-full h-full bg-center bg-cover bg-gray-700"
style='background-image: url("https://images.unsplash.com/photo-1557804506-669a67965ba0?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1267&amp;q=80");'
> >
<span <span
id="blackOverlay" id="blackOverlay"
class="w-full h-full absolute opacity-75 bg-black" class="w-full h-full absolute opacity-75 bg-gray-700"
></span> ></span>
</div> </div>
<div class="container relative mx-auto"> <div class="container relative mx-auto">

View file

@ -3,3 +3,21 @@
@import "tailwindcss/components"; @import "tailwindcss/components";
@import "tailwindcss/utilities"; @import "tailwindcss/utilities";
input[type="checkbox"]::after {
content: "";
color: currentColor;
width: 100%;
height: 100%;
display: inline-flex;
align-items: center;
justify-content: center;
}
input[type="checkbox"]:checked::after {
content: "✓";
}
.hidden-options-toggle:checked+.hidden {
display: block;
}

View file

@ -6,6 +6,8 @@ module.exports = {
theme: { theme: {
extend: {}, extend: {},
}, },
variants: {}, variants: {
backgroundColor: ['responsive', 'hover', 'focus', 'checked'],
},
plugins: [], plugins: [],
} }

View file

@ -22,6 +22,7 @@ module.exports = (env, options) => {
entry: { entry: {
'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']), 'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
'content-editor': ['./js/content-editor.js'], 'content-editor': ['./js/content-editor.js'],
'tailwind': ['./tailwind.config.js'],
}, },
output: { output: {
filename: 'js/[name].js', filename: 'js/[name].js',

View file

@ -1,4 +1,4 @@
<nav class="flex items-center justify-between flex-wrap bg-grey-dark p-6 fixed w-full z-10 pin-t"> <nav class="flex items-center justify-between flex-wrap bg-grey-dark p-6 w-full z-10 bg-gray-800">
<div class="flex items-center flex-no-shrink text-white mr-6"> <div class="flex items-center flex-no-shrink text-white mr-6">
<a class="text-white no-underline hover:text-white hover:no-underline" href="/"> <a class="text-white no-underline hover:text-white hover:no-underline" href="/">
<span class="text-2xl pl-2"><i class="em em-grinning"></i> <%= I18n.t! "en", "site.title" %></span> <span class="text-2xl pl-2"><i class="em em-grinning"></i> <%= I18n.t! "en", "site.title" %></span>

View file

@ -12,7 +12,7 @@
<body class="text-gray-800 antialiased"> <body class="text-gray-800 antialiased">
<main role="main"> <main role="main">
<!-- Page Contents --> <!-- Page Contents -->
<div class="pusher"> <div class="bg-gray-100 min-h-screen">
<div class="ui inverted vertical masthead center aligned segment"> <div class="ui inverted vertical masthead center aligned segment">
<%= render "_menu.html", assigns %> <%= render "_menu.html", assigns %>
</div> </div>

View file

@ -53,8 +53,10 @@ defmodule CoreWeb.Helpers do
end end
def styled_input(f, field, opts, options, do: content) do def styled_input(f, field, opts, options, do: content) do
{icon, rest_opts} = Keyword.pop(opts, :icon, "") {type, rest_opts} = Keyword.pop(opts, :type, input_type(f, field))
{classes, rest_opts} = Keyword.pop(rest_opts, :class, "px-3 py-3 placeholder-gray-400 text-gray-700 bg-white rounded text-sm shadow focus:outline-none focus:shadow-outline w-full") IO.inspect(type)
{icon, rest_opts} = Keyword.pop(rest_opts, :icon, "")
{classes, rest_opts} = Keyword.pop(rest_opts, :class, default_classes_for_type(type))
{label_text, rest_opts} = Keyword.pop(rest_opts, :label) {label_text, rest_opts} = Keyword.pop(rest_opts, :label)
{input_helper, rest_opts} = Keyword.pop(rest_opts, :input_helper, :text_input) {input_helper, rest_opts} = Keyword.pop(rest_opts, :input_helper, :text_input)
@ -74,11 +76,7 @@ defmodule CoreWeb.Helpers do
<% end %> <% end %>
<i class="<%= icon %> icon"></i> <i class="<%= icon %> icon"></i>
<%= if options == nil do %> <%= do_styled_input_tag(type, input_helper, f, field, options, opts, classes, error_classes) %>
<%= apply(Phoenix.HTML.Form, input_helper, [f, field, rest_opts ++ [class: Enum.join([classes, error_classes], " ")]]) %>
<% else %>
<%= apply(Phoenix.HTML.Form, input_helper, [f, field, options, rest_opts ++ [class: Enum.join([classes, error_classes], " ")]]) %>
<% end %>
<%= content %> <%= content %>
<%= error_tag f, field, class: "text-red-500 italic" %> <%= error_tag f, field, class: "text-red-500 italic" %>
@ -86,12 +84,67 @@ defmodule CoreWeb.Helpers do
""" """
end end
defp do_styled_input_tag(type, input_helper, f, field, nil, opts, classes, error_classes) when type in [:date_select, :time_select, :datetime_select] do
default_child_opts = [
month: [
class: "appearance-none border-b-2 border-dashed",
options: [
{("Jan"), "1"},
{("Feb"), "2"},
{("Mar"), "3"},
{("Apr"), "4"},
{("May"), "5"},
{("Jun"), "6"},
{("Jul"), "7"},
{("Aug"), "8"},
{("Sep"), "9"},
{("Oct"), "10"},
{("Nov"), "11"},
{("Dec"), "12"},
]
],
day: [class: "appearance-none border-b-2 border-dashed"],
year: [class: "appearance-none border-b-2 border-dashed"],
hour: [class: "appearance-none border-b-2 border-dashed"],
minute: [class: "appearance-none border-b-2 border-dashed"],
second: [class: "appearance-none border-b-2 border-dashed"],
]
{child_opts, rest_opts} = Keyword.pop(opts, :child_opts, default_child_opts)
~E"""
<%= content_tag :div, class: Enum.join([classes, error_classes], " ") do %>
<%= apply(Phoenix.HTML.Form, input_helper, [f, field, rest_opts ++ child_opts]) %>
<% end %>
"""
end
defp do_styled_input_tag(type, input_helper, f, field, nil, opts, classes, error_classes) do
apply(Phoenix.HTML.Form, input_helper, [f, field, opts ++ [class: Enum.join([classes, error_classes], " ")]])
end
defp do_styled_input_tag(type, input_helper, f, field, options, opts, classes, error_classes) do
apply(Phoenix.HTML.Form, input_helper, [f, field, options, opts ++ [class: Enum.join([classes, error_classes], " ")]])
end
defp default_classes_for_type(type) when type in [:date_select, :time_select, :datetime_select] do
"bg-white shadow rounded p-3"
end
defp default_classes_for_type(:checkbox), do: "appearance-none h-10 w-10 bg-white checked:bg-gray-500 rounded shadow focus:outline-none focus:shadow-outline text-white text-xl font-bold mb-2"
defp default_classes_for_type(_), do: "px-3 py-3 placeholder-gray-400 text-gray-700 bg-white rounded text-sm shadow focus:outline-none focus:shadow-outline w-full"
def styled_button(text) do def styled_button(text) do
~E""" ~E"""
<%= submit text, class: "bg-gray-900 text-white active:bg-gray-700 text-sm font-bold uppercase px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full" %> <%= submit text, class: "bg-gray-900 text-white active:bg-gray-700 text-sm font-bold uppercase px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full" %>
""" """
end end
def styled_button_link(text, opts) do
~E"""
<%= link text, opts ++ [class: "bg-gray-900 text-white active:bg-gray-700 text-sm font-bold uppercase px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full"] %>
"""
end
def floating_form(title, changeset, do: content) do def floating_form(title, changeset, do: content) do
~E""" ~E"""
<h1 class="relative text-white text-xl font-semibold text-center pb-6"><%= title %></h1> <h1 class="relative text-white text-xl font-semibold text-center pb-6"><%= title %></h1>