irelia 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +2 -0
- data/app/assets/config/irelia_manifest.js +2 -0
- data/app/frontend/components/application_view_component.rb +5 -0
- data/app/frontend/components/application_view_component_preview.rb +5 -0
- data/app/frontend/components/navbar/button/component.html.erb +8 -0
- data/app/frontend/components/navbar/button/component.rb +13 -0
- data/app/frontend/components/navbar/button/preview.rb +12 -0
- data/app/frontend/components/navbar/container/component.html.erb +5 -0
- data/app/frontend/components/navbar/container/component.rb +8 -0
- data/app/frontend/components/navbar/container/preview.rb +12 -0
- data/app/frontend/components/navbar/dark_mode_switcher/component.html.erb +4 -0
- data/app/frontend/components/navbar/dark_mode_switcher/component.rb +8 -0
- data/app/frontend/components/navbar/dark_mode_switcher/preview.rb +12 -0
- data/app/frontend/components/navbar/menu_items/component.html.erb +3 -0
- data/app/frontend/components/navbar/menu_items/component.rb +8 -0
- data/app/frontend/components/navbar/menu_items/preview.rb +12 -0
- data/app/frontend/components/navbar/navlink/component.html.erb +8 -0
- data/app/frontend/components/navbar/navlink/component.rb +13 -0
- data/app/frontend/components/navbar/navlink/preview.rb +12 -0
- data/app/frontend/components/navbar/right_section/component.html.erb +3 -0
- data/app/frontend/components/navbar/right_section/component.rb +8 -0
- data/app/frontend/components/navbar/right_section/preview.rb +12 -0
- data/app/frontend/components/navbar/select_account/component.html.erb +36 -0
- data/app/frontend/components/navbar/select_account/component.rb +6 -0
- data/app/frontend/components/navbar/select_account/preview.rb +9 -0
- data/app/frontend/components/navbar/separator/component.html.erb +1 -0
- data/app/frontend/components/navbar/separator/component.rb +7 -0
- data/app/frontend/components/navbar/separator/preview.rb +12 -0
- data/app/frontend/components/page/breadcrumbs/component.html.erb +16 -0
- data/app/frontend/components/page/breadcrumbs/component.rb +6 -0
- data/app/frontend/components/page/breadcrumbs/preview.rb +9 -0
- data/app/frontend/components/page/container/component.html.erb +3 -0
- data/app/frontend/components/page/container/component.rb +4 -0
- data/app/frontend/components/page/container/preview.rb +9 -0
- data/app/frontend/components/page/header/component.html.erb +12 -0
- data/app/frontend/components/page/header/component.rb +6 -0
- data/app/frontend/components/page/header/preview.rb +9 -0
- data/app/helpers/navbar_helper.rb +35 -0
- data/app/helpers/page_helper.rb +15 -0
- data/app/javascript/controllers/dark_mode_switcher_controller.js +20 -0
- data/app/javascript/controllers/dropdown_controller.js +3 -0
- data/app/views/devise/registrations/new.html.erb +21 -0
- data/app/views/devise/sessions/new.html.erb +18 -0
- data/app/views/layouts/application.html.erb +11 -0
- data/app/views/layouts/devise.html.erb +23 -0
- data/app/views/layouts/mailer.html.erb +13 -0
- data/app/views/layouts/mailer.text.erb +1 -0
- data/app/views/layouts/teamable.html.erb +31 -0
- data/app/views/shared/_head.html.erb +26 -0
- data/app/views/shared/_navbar.html.erb +30 -0
- data/app/views/shared/_navbar_logo.html.erb +3 -0
- data/app/views/teamable/accounts/new.html.erb +10 -0
- data/app/views/teamable/setup/new.html.erb +8 -0
- data/app/views/teamable/shared/_form.html.erb +4 -0
- data/config/importmap.rb +7 -0
- data/config/initializers/devise.rb +313 -0
- data/config/initializers/simple_form.rb +148 -0
- data/config/initializers/view_component.rb +18 -0
- data/lib/generators/irelia/install_generator.rb +19 -0
- data/lib/generators/templates/irelia.rb +14 -0
- data/lib/generators/view_component/USAGE +15 -0
- data/lib/generators/view_component/templates/component.html.erb.tt +1 -0
- data/lib/generators/view_component/templates/component.rb.tt +8 -0
- data/lib/generators/view_component/templates/component_system_test.rb.tt +13 -0
- data/lib/generators/view_component/templates/component_test.rb.tt +19 -0
- data/lib/generators/view_component/templates/preview.rb.tt +9 -0
- data/lib/generators/view_component/view_component_generator.rb +53 -0
- data/lib/irelia/engine.rb +16 -0
- data/lib/irelia/version.rb +1 -1
- data/lib/irelia.rb +26 -3
- metadata +202 -13
- data/config/routes.rb +0 -2
- data/lib/tasks/irelia_tasks.rake +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: faa3b8e64532f3d512880ee2c611566d88e27606125ea7068bc491f40573fa91
|
4
|
+
data.tar.gz: 5208c6e42837909a6858bff761b7f1add4ace0110f3010e190a57fabada5b6c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9e3f2cf4e9e68599369078e72ce71d7f515dc3ba660d81dadffac22b74c59a9ca0e47e42aead93e8ad24e134e3d6fe7a39926e6082a6f9a5a7a694fca7fae5d
|
7
|
+
data.tar.gz: ff3d6cb4b9770cd64469073ad6b9d62578fdfb36c20d9ee60f0ba346f00254c8f1222d87417ffed9faf8812a82ff48dd5d4f62ad72ad7fe1c167bb626fa98c59
|
data/Rakefile
CHANGED
@@ -0,0 +1,8 @@
|
|
1
|
+
<%= button_to target, class: "inline-flex items-center gap-x-1 py-3 px-4 text-sm leading-3 justify-center rounded transition bg-white hover:bg-neutral-50 dark:bg-dark-900 dark:hover:bg-dark-800 dark:text-neutral-200 whitespace-nowrap cursor-pointer #{custom_class}", method: method do %>
|
2
|
+
<% if icon.present? %>
|
3
|
+
<i class="<%= icon %> w-3 h-3"></i>
|
4
|
+
<% end %>
|
5
|
+
<% if text.present? %>
|
6
|
+
<span class="ml-1"><%= text %></span>
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module Button
|
5
|
+
class Component < ApplicationViewComponent
|
6
|
+
option :target # required
|
7
|
+
option :method, default: proc { :get }
|
8
|
+
option :icon, optional: true # FontAwesome icon class
|
9
|
+
option :text, optional: true
|
10
|
+
option :custom_class, optional: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module Button
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
6
|
+
# You can specify the container class for the default template
|
7
|
+
# self.container_class = "w-1/2 border border-gray-300"
|
8
|
+
|
9
|
+
def default; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<section class="flex sticky left-0 right-0 top-0 z-50 h-[60px] relative bg-white dark:bg-dark-900 gap-x-8 z-40 items-center border-b dark:border-b-dark-700">
|
2
|
+
<div class="container max-w-[1200px] mx-auto px-8 flex items-center h-[60px] gap-x-8">
|
3
|
+
<%= content %>
|
4
|
+
</div>
|
5
|
+
</section>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module Container
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
6
|
+
# You can specify the container class for the default template
|
7
|
+
# self.container_class = "w-1/2 border border-gray-300"
|
8
|
+
|
9
|
+
def default; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<button data-controller="dark-mode-switcher" data-action="click->dark-mode-switcher#toggle" class="inline-flex items-center gap-x-1 py-3 px-4 text-sm leading-3 justify-center rounded transition bg-white hover:bg-neutral-50 dark:bg-dark-900 dark:hover:bg-dark-800 dark:text-neutral-200 whitespace-nowrap cursor-pointer">
|
2
|
+
<i class="fa fa-lightbulb hidden dark:inline"></i>
|
3
|
+
<i class="fa fa-moon inline dark:hidden"></i>
|
4
|
+
</button>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module DarkModeSwitcher
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
6
|
+
# You can specify the container class for the default template
|
7
|
+
# self.container_class = "w-1/2 border border-gray-300"
|
8
|
+
|
9
|
+
def default; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module MenuItems
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
6
|
+
# You can specify the container class for the default template
|
7
|
+
# self.container_class = "w-1/2 border border-gray-300"
|
8
|
+
|
9
|
+
def default; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<%= link_to target, class: "flex items-center px-2 text-sm h-[60px] border-y-2 border-transparent #{active ? "font-bold text-primary-700" : "hover:text-black dark:hover:text-white" } #{custom_class}" do %>
|
2
|
+
<% if icon.present? %>
|
3
|
+
<i class="<%= icon %> w-4 h-4 <%= "mr-3" if text %>"></i>
|
4
|
+
<% end %>
|
5
|
+
<% if text.present? %>
|
6
|
+
<span><%= text %></span>
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module Navlink
|
5
|
+
class Component < ApplicationViewComponent
|
6
|
+
option :target # required
|
7
|
+
option :active, optional: true, default: false
|
8
|
+
option :text, optional: true
|
9
|
+
option :custom_class, optional: true
|
10
|
+
option :icon, optional: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module Navlink
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
6
|
+
# You can specify the container class for the default template
|
7
|
+
# self.container_class = "w-1/2 border border-gray-300"
|
8
|
+
|
9
|
+
def default; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module RightSection
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
6
|
+
# You can specify the container class for the default template
|
7
|
+
# self.container_class = "w-1/2 border border-gray-300"
|
8
|
+
|
9
|
+
def default; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<div data-controller="dropdown" class="relative block text-sm min-w-[20px]">
|
2
|
+
<button class="flex w-full items-center text-left gap-x-4 cursor-pointer" data-action="dropdown#toggle click@window->dropdown#hide">
|
3
|
+
<img class="w-9 h-9 rounded" src="https://picsum.photos/50">
|
4
|
+
<div class="flex flex-col pr-4 gap-y-0.5">
|
5
|
+
<strong class="text-primary-600"><%= current_account.name %></strong>
|
6
|
+
<% if current_account.personal_account? %>
|
7
|
+
<span class="flex text-neutral-500 dark:text-neutral-300 items-center gap-x-1 text-xs">
|
8
|
+
<i class="fas fa-user"></i>
|
9
|
+
Personal account
|
10
|
+
</span>
|
11
|
+
<% else %>
|
12
|
+
<span class="flex text-neutral-500 dark:text-neutral-300 items-center gap-x-1 text-xs">
|
13
|
+
<i class="fas fa-users"></i>
|
14
|
+
Team account
|
15
|
+
</span>
|
16
|
+
<% end %>
|
17
|
+
</div>
|
18
|
+
<i class="fa-solid fa-caret-down mr-2 ml-auto"></i>
|
19
|
+
</button>
|
20
|
+
<div
|
21
|
+
class="hidden w-full transition z-50 text-xs bg-white dark:bg-zinc-800 divide-y absolute mt-4 right-0 border dark:border-zinc-700 dark:divide-zinc-700 dark:text-neutral-200 border-t-0 rounded-b whitespace-nowrap"
|
22
|
+
data-dropdown-target="menu"
|
23
|
+
data-transition-enter-from="opacity-0 scale-95"
|
24
|
+
data-transition-enter-to="opacity-100 scale-100"
|
25
|
+
data-transition-leave-from="opacity-100 scale-100"
|
26
|
+
data-transition-leave-to="opacity-0 scale-95">
|
27
|
+
|
28
|
+
<% User.find(current_user.id).accounts.each do |account| %>
|
29
|
+
<%= button_to switch_account_path(account), class: 'flex w-full p-3 px-4 gap-x-4 items-center hover:bg-neutral-100 hover:text-neutral-900 transition', method: :patch do %>
|
30
|
+
<i class="fas w-4 text-center <%= account.personal_account? ? "fa-user" : "fa-users" %>"></i> <%= account.name %>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
33
|
+
|
34
|
+
<%= link_to 'Create a new team account' , new_account_path, class: 'flex w-full p-3 px-4 gap-x-4 items-center hover:bg-neutral-100 hover:text-neutral-900 transition', method: :delete %>
|
35
|
+
</div>
|
36
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div class="w-[1px] h-10 bg-neutral-100 dark:bg-dark-700"></div>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Navbar
|
4
|
+
module Separator
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
6
|
+
# You can specify the container class for the default template
|
7
|
+
# self.container_class = "w-1/2 border border-gray-300"
|
8
|
+
|
9
|
+
def default; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% if breadcrumbs.any? %>
|
2
|
+
<nav aria-label="breadcrumb" class="bg-white dark:bg-dark-900 border-b dark:border-b-dark-700 text-sm">
|
3
|
+
<div class="container max-w-[1200px] font-semibold mx-auto p-8 py-4">
|
4
|
+
<ol class="flex gap-x-4 text-neutral-500 dark:text-neutral-400">
|
5
|
+
<% breadcrumbs.each do |crumb| %>
|
6
|
+
<% if crumb.current? %>
|
7
|
+
<li class="font-bold text-black dark:text-white"><%= crumb.name %></li>
|
8
|
+
<% else %>
|
9
|
+
<li><%= link_to crumb.name, crumb.url, (crumb.current? ? {"aria-current" => "page"} : {}) %></li>
|
10
|
+
<li><span class="text-neutral-300 dark:text-neutral-600"><i class="fa-solid fa-caret-right"></i></span></li>
|
11
|
+
<% end %>
|
12
|
+
<% end %>
|
13
|
+
</ol>
|
14
|
+
</div>
|
15
|
+
</nav>
|
16
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<header class="flex mb-8 border-b-2 dark:border-b-dark-700 pb-6">
|
2
|
+
<div class="flex flex-1 flex-col gap-y-1">
|
3
|
+
<h1 class="text-lg font-bold uppercase"><%= title %></h1>
|
4
|
+
<% if subtitle.present? %>
|
5
|
+
<p class="text-neutral-400"><%= subtitle %></p>
|
6
|
+
<% end %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="flex items-center justify-center gap-x-3">
|
10
|
+
<%= content %>
|
11
|
+
</div>
|
12
|
+
</header>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NavbarHelper
|
4
|
+
def navbar(&block)
|
5
|
+
render(Navbar::Container::Component.new, &block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def navbar_items(&block)
|
9
|
+
render(Navbar::MenuItems::Component.new, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def navbar_right(&block)
|
13
|
+
render(Navbar::RightSection::Component.new, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def navigation_item(text, target, options = {})
|
17
|
+
active = options[:active] || request.path == target
|
18
|
+
icon = options[:icon] || nil
|
19
|
+
|
20
|
+
render(Navbar::Navlink::Component.new(target:, text:, active:, icon:))
|
21
|
+
end
|
22
|
+
|
23
|
+
def navbar_button(text, target, options = {})
|
24
|
+
active = options[:active] || request.path == target
|
25
|
+
icon = options[:icon] || nil
|
26
|
+
method = options[:method] || :get
|
27
|
+
custom_class = options[:class] || nil
|
28
|
+
|
29
|
+
render(Navbar::Button::Component.new(target:, text:, icon:, method:, custom_class:))
|
30
|
+
end
|
31
|
+
|
32
|
+
def navbar_separator
|
33
|
+
render(Navbar::Separator::Component.new)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PageHelper
|
4
|
+
def container(&block)
|
5
|
+
render(Page::Container::Component.new, &block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def page_header(**arguments)
|
9
|
+
render(Page::Header::Component.new(**arguments))
|
10
|
+
end
|
11
|
+
|
12
|
+
def breadcrumbs
|
13
|
+
render(Page::Breadcrumbs::Component.new(breadcrumbs: breadcrumb_trail))
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
initialize() {
|
5
|
+
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
6
|
+
document.documentElement.classList.add('dark')
|
7
|
+
} else {
|
8
|
+
document.documentElement.classList.remove('dark')
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
toggle() {
|
13
|
+
if (localStorage.theme === 'dark') {
|
14
|
+
localStorage.theme = 'light'
|
15
|
+
} else {
|
16
|
+
localStorage.theme = 'dark'
|
17
|
+
}
|
18
|
+
this.initialize()
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<% title "Create a new account" %>
|
2
|
+
<% content_for :header do %>
|
3
|
+
<h1 class="font-bold font-headings text-neutral-600 dark:text-neutral-100 text-2xl">Create your <strong class="text-primary-600">Irelia</strong> account</h1>
|
4
|
+
<p class="text-neutral-400">Enter your email address and a secure password.</p>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<main class="flex flex-col gap-4 w-full max-w-2xl">
|
8
|
+
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
|
9
|
+
<%= f.input :email, placeholder: "Enter a valid email address", required: true, autofocus: true, input_html: { autocomplete: "email" }%>
|
10
|
+
|
11
|
+
<div class="flex justify-between items-start gap-x-4">
|
12
|
+
<%= f.input :password, placeholder: "Create a secure password", required: true, hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length), input_html: { autocomplete: "new-password" } %>
|
13
|
+
<%= f.input :password_confirmation, placeholder: "Confirm your password", required: true, input_html: { autocomplete: "new-password" } %>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="mt-4 flex justify-between items-center">
|
17
|
+
<%= f.button :submit, "Create your account" %>
|
18
|
+
<p class="dark:text-neutral-200">Already have an account? <%= link_to "Sign in!", new_user_session_path, class: "font-bold transition text-primary-600" %>
|
19
|
+
</div>
|
20
|
+
<% end %>
|
21
|
+
</main>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% title "Sign in to your account" %>
|
2
|
+
<% content_for :header do %>
|
3
|
+
<h1 class="font-bold font-headings text-neutral-600 dark:text-neutral-100 text-2xl">Sign in to <strong class="text-primary-600">Irelia</strong></h1>
|
4
|
+
<p class="text-neutral-400 dark:text-neutral-200">Sign in with your email address and password or select any of the other available options below.</p>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<main class="flex flex-col gap-4 w-full max-w-xl">
|
8
|
+
<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
|
9
|
+
<%= f.input :email, placeholder: "Enter your email", required: true, autofocus: true, input_html: { autocomplete: "email" } %>
|
10
|
+
<%= f.input :password, placeholder: "Enter your password", required: true, input_html: { autocomplete: "current-password" } %>
|
11
|
+
<%= f.input :remember_me, as: :boolean, wrapper: :inline_checkbox if devise_mapping.rememberable? %>
|
12
|
+
|
13
|
+
<div class="flex justify-between items-center">
|
14
|
+
<%= f.button :submit, "Sign in" %>
|
15
|
+
<p class="dark:text-neutral-200">Don't have an account? <%= link_to "Sign up!", new_user_registration_path, class: "font-bold text-primary-600 transition" %></p>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
</main>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<%= render "shared/head" %>
|
5
|
+
</head>
|
6
|
+
<body class="antialiased bg-neutral-50 text-neutral-700 dark:bg-dark-800 dark:text-neutral-100">
|
7
|
+
<%= render "shared/navbar" %>
|
8
|
+
<%= breadcrumbs %>
|
9
|
+
<%= yield %>
|
10
|
+
</body>
|
11
|
+
</html>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<%= render "shared/head" %>
|
5
|
+
</head>
|
6
|
+
<body class="h-screen relative flex justify-center items-center antialiased bg-neutral-50 text-neutral-700 dark:bg-dark-800 dark:text-neutral-100">
|
7
|
+
<div class="fixed top-4 right-4">
|
8
|
+
<%= render(Navbar::DarkModeSwitcher::Component.new) %>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<% flash.each do |key, value| %>
|
12
|
+
<%= content_tag :div, value, class: "flash #{key} fixed top-0 left-0 right-0 bg-white py-2 px-4 inline-block text-center w-full shadow" %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<section class="flex flex-col gap-8 items-center justify-center w-full">
|
16
|
+
<header class="flex flex-col items-center gap-y-2 text-center max-w-lg">
|
17
|
+
<%= yield :header %>
|
18
|
+
</header>
|
19
|
+
|
20
|
+
<%= yield %>
|
21
|
+
</section>
|
22
|
+
</body>
|
23
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= yield %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<%= render "shared/head" %>
|
5
|
+
</head>
|
6
|
+
<body class="h-screen relative bg-neutral-50 text-neutral-700 dark:bg-dark-800 dark:text-neutral-100">
|
7
|
+
<%= render "shared/navbar" %>
|
8
|
+
|
9
|
+
<% flash.each do |key, value| %>
|
10
|
+
<%= content_tag :div, value, class: "flash #{key} fixed top-0 left-0 right-0 bg-white py-2 px-4 inline-block text-center w-full shadow" %>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<div class="h-screen -top-[60px] relative flex justify-center items-center antialiased">
|
14
|
+
<section class="flex flex-1 flex-col">
|
15
|
+
<div class="flex-1 flex items-center justify-center px-8">
|
16
|
+
<section class="flex flex-col gap-8 items-center justify-center w-full max-w-xl">
|
17
|
+
<header class="flex flex-col items-center">
|
18
|
+
<div class="flex flex-col gap-y-2 text-center">
|
19
|
+
<%= yield :header %>
|
20
|
+
</div>
|
21
|
+
</header>
|
22
|
+
|
23
|
+
<main class="flex flex-col gap-4 w-full">
|
24
|
+
<%= yield %>
|
25
|
+
</main>
|
26
|
+
</section>
|
27
|
+
</div>
|
28
|
+
</section>
|
29
|
+
</div>
|
30
|
+
</body>
|
31
|
+
</html>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= display_meta_tags site: Irelia.config.application_name, reverse: true, separator: "—" %>
|
2
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
3
|
+
|
4
|
+
<script>
|
5
|
+
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
6
|
+
document.documentElement.classList.add('dark')
|
7
|
+
}
|
8
|
+
</script>
|
9
|
+
|
10
|
+
<%= csrf_meta_tags %>
|
11
|
+
<%= csp_meta_tag %>
|
12
|
+
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
13
|
+
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
14
|
+
<%= javascript_importmap_tags %>
|
15
|
+
|
16
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
17
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="true" />
|
18
|
+
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet" />
|
19
|
+
<link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet" />
|
20
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
21
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js" integrity="sha512-fD9DI5bZwQxOi7MhYWnnNPlvXdp/2Pj3XSTRrFs5FQa4mizyGLnJcN6tuvUS6LbmgN1ut+XGSABKvjN0H6Aoow==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
22
|
+
|
23
|
+
<style>
|
24
|
+
.valid .input-box { border: 1px green solid; }
|
25
|
+
.invalid .input-box { border: 1px red solid; }
|
26
|
+
</style>
|