irelia 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -0
  3. data/app/assets/config/irelia_manifest.js +2 -0
  4. data/app/frontend/components/application_view_component.rb +5 -0
  5. data/app/frontend/components/application_view_component_preview.rb +5 -0
  6. data/app/frontend/components/navbar/button/component.html.erb +8 -0
  7. data/app/frontend/components/navbar/button/component.rb +13 -0
  8. data/app/frontend/components/navbar/button/preview.rb +12 -0
  9. data/app/frontend/components/navbar/container/component.html.erb +5 -0
  10. data/app/frontend/components/navbar/container/component.rb +8 -0
  11. data/app/frontend/components/navbar/container/preview.rb +12 -0
  12. data/app/frontend/components/navbar/dark_mode_switcher/component.html.erb +4 -0
  13. data/app/frontend/components/navbar/dark_mode_switcher/component.rb +8 -0
  14. data/app/frontend/components/navbar/dark_mode_switcher/preview.rb +12 -0
  15. data/app/frontend/components/navbar/menu_items/component.html.erb +3 -0
  16. data/app/frontend/components/navbar/menu_items/component.rb +8 -0
  17. data/app/frontend/components/navbar/menu_items/preview.rb +12 -0
  18. data/app/frontend/components/navbar/navlink/component.html.erb +8 -0
  19. data/app/frontend/components/navbar/navlink/component.rb +13 -0
  20. data/app/frontend/components/navbar/navlink/preview.rb +12 -0
  21. data/app/frontend/components/navbar/right_section/component.html.erb +3 -0
  22. data/app/frontend/components/navbar/right_section/component.rb +8 -0
  23. data/app/frontend/components/navbar/right_section/preview.rb +12 -0
  24. data/app/frontend/components/navbar/select_account/component.html.erb +36 -0
  25. data/app/frontend/components/navbar/select_account/component.rb +6 -0
  26. data/app/frontend/components/navbar/select_account/preview.rb +9 -0
  27. data/app/frontend/components/navbar/separator/component.html.erb +1 -0
  28. data/app/frontend/components/navbar/separator/component.rb +7 -0
  29. data/app/frontend/components/navbar/separator/preview.rb +12 -0
  30. data/app/frontend/components/page/breadcrumbs/component.html.erb +16 -0
  31. data/app/frontend/components/page/breadcrumbs/component.rb +6 -0
  32. data/app/frontend/components/page/breadcrumbs/preview.rb +9 -0
  33. data/app/frontend/components/page/container/component.html.erb +3 -0
  34. data/app/frontend/components/page/container/component.rb +4 -0
  35. data/app/frontend/components/page/container/preview.rb +9 -0
  36. data/app/frontend/components/page/header/component.html.erb +12 -0
  37. data/app/frontend/components/page/header/component.rb +6 -0
  38. data/app/frontend/components/page/header/preview.rb +9 -0
  39. data/app/helpers/navbar_helper.rb +35 -0
  40. data/app/helpers/page_helper.rb +15 -0
  41. data/app/javascript/controllers/dark_mode_switcher_controller.js +20 -0
  42. data/app/javascript/controllers/dropdown_controller.js +3 -0
  43. data/app/views/devise/registrations/new.html.erb +21 -0
  44. data/app/views/devise/sessions/new.html.erb +18 -0
  45. data/app/views/layouts/application.html.erb +11 -0
  46. data/app/views/layouts/devise.html.erb +23 -0
  47. data/app/views/layouts/mailer.html.erb +13 -0
  48. data/app/views/layouts/mailer.text.erb +1 -0
  49. data/app/views/layouts/teamable.html.erb +31 -0
  50. data/app/views/shared/_head.html.erb +26 -0
  51. data/app/views/shared/_navbar.html.erb +30 -0
  52. data/app/views/shared/_navbar_logo.html.erb +3 -0
  53. data/app/views/teamable/accounts/new.html.erb +10 -0
  54. data/app/views/teamable/setup/new.html.erb +8 -0
  55. data/app/views/teamable/shared/_form.html.erb +4 -0
  56. data/config/importmap.rb +7 -0
  57. data/config/initializers/devise.rb +313 -0
  58. data/config/initializers/simple_form.rb +148 -0
  59. data/config/initializers/view_component.rb +18 -0
  60. data/lib/generators/irelia/install_generator.rb +19 -0
  61. data/lib/generators/templates/irelia.rb +14 -0
  62. data/lib/generators/view_component/USAGE +15 -0
  63. data/lib/generators/view_component/templates/component.html.erb.tt +1 -0
  64. data/lib/generators/view_component/templates/component.rb.tt +8 -0
  65. data/lib/generators/view_component/templates/component_system_test.rb.tt +13 -0
  66. data/lib/generators/view_component/templates/component_test.rb.tt +19 -0
  67. data/lib/generators/view_component/templates/preview.rb.tt +9 -0
  68. data/lib/generators/view_component/view_component_generator.rb +53 -0
  69. data/lib/irelia/engine.rb +16 -0
  70. data/lib/irelia/version.rb +1 -1
  71. data/lib/irelia.rb +26 -3
  72. metadata +202 -13
  73. data/config/routes.rb +0 -2
  74. data/lib/tasks/irelia_tasks.rake +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fca4b000ecd80c6029d5fcb6490a6032e9d9a454bc2a55569c208d803da2cf24
4
- data.tar.gz: 36706bbd38af5a8f5735448eabdba2d38a1f791b65c46e9388d0c7e8ba968cc3
3
+ metadata.gz: faa3b8e64532f3d512880ee2c611566d88e27606125ea7068bc491f40573fa91
4
+ data.tar.gz: 5208c6e42837909a6858bff761b7f1add4ace0110f3010e190a57fabada5b6c7
5
5
  SHA512:
6
- metadata.gz: 31f718e64ba4b0f760c4a29bc2f38a73b7169052b8a728ddde5c152e73ecffc91572360b20b3d93e72524fa40d0f8f0bf26298e8e1193d823a7d90440775d5bb
7
- data.tar.gz: 1f694a67c08bc294f734d5b5e13988a21d44c09a3913c6dd68f7ac009b5b85d20a9730276df89f1b0af3ecd14303d591696975cc95cba074d5a186dcbb417127
6
+ metadata.gz: e9e3f2cf4e9e68599369078e72ce71d7f515dc3ba660d81dadffac22b74c59a9ca0e47e42aead93e8ad24e134e3d6fe7a39926e6082a6f9a5a7a694fca7fae5d
7
+ data.tar.gz: ff3d6cb4b9770cd64469073ad6b9d62578fdfb36c20d9ee60f0ba346f00254c8f1222d87417ffed9faf8812a82ff48dd5d4f62ad72ad7fe1c167bb626fa98c59
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/setup"
2
4
 
3
5
  APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
@@ -0,0 +1,2 @@
1
+ //= link_tree ../../javascript .js
2
+ //= link_tree ../../assets/images .svg
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationViewComponent < ViewComponentContrib::Base
4
+ extend Dry::Initializer
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationViewComponentPreview < ViewComponentContrib::Preview::Base
4
+ self.abstract_class = true
5
+ end
@@ -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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Navbar
4
+ module Container
5
+ class Component < ApplicationViewComponent
6
+ end
7
+ end
8
+ end
@@ -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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Navbar
4
+ module DarkModeSwitcher
5
+ class Component < ApplicationViewComponent
6
+ end
7
+ end
8
+ end
@@ -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,3 @@
1
+ <nav class="flex items-center gap-x-8">
2
+ <%= content %>
3
+ </nav>
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Navbar
4
+ module MenuItems
5
+ class Component < ApplicationViewComponent
6
+ end
7
+ end
8
+ 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,3 @@
1
+ <div class="ml-auto flex items-center gap-x-4">
2
+ <%= content %>
3
+ </div>
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Navbar
4
+ module RightSection
5
+ class Component < ApplicationViewComponent
6
+ end
7
+ end
8
+ 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,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Navbar::SelectAccount::Component < ApplicationViewComponent
4
+ option :current_user, required: true
5
+ option :current_account, required: true
6
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Navbar::SelectAccount::Preview < ApplicationViewComponentPreview
4
+ # You can specify the container class for the default template
5
+ # self.container_class = "w-1/2 border border-gray-300"
6
+
7
+ def default
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ <div class="w-[1px] h-10 bg-neutral-100 dark:bg-dark-700"></div>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Navbar
4
+ module Separator
5
+ class Component < ApplicationViewComponent; end
6
+ end
7
+ end
@@ -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,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Page::Breadcrumbs::Component < ApplicationViewComponent
4
+ # with_collection_parameter :breadcrumbs
5
+ option :breadcrumbs
6
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Page::Breadcrumbs::Preview < ApplicationViewComponentPreview
4
+ # You can specify the container class for the default template
5
+ # self.container_class = "w-1/2 border border-gray-300"
6
+
7
+ def default
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ <div class="container max-w-[1200px] mx-auto p-8">
2
+ <%= content %>
3
+ </div>
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Page::Container::Component < ApplicationViewComponent
4
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Page::Container::Preview < ApplicationViewComponentPreview
4
+ # You can specify the container class for the default template
5
+ # self.container_class = "w-1/2 border border-gray-300"
6
+
7
+ def default
8
+ end
9
+ 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,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Page::Header::Component < ApplicationViewComponent
4
+ option :title
5
+ option :subtitle, optional: true
6
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Page::Header::Preview < ApplicationViewComponentPreview
4
+ # You can specify the container class for the default template
5
+ # self.container_class = "w-1/2 border border-gray-300"
6
+
7
+ def default
8
+ end
9
+ end
@@ -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,3 @@
1
+ import Dropdown from 'stimulus-dropdown'
2
+
3
+ export default class extends Dropdown { }
@@ -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,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <style>
6
+ /* Email styles need to be inline */
7
+ </style>
8
+ </head>
9
+
10
+ <body>
11
+ <%= yield %>
12
+ </body>
13
+ </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&amp;display=swap" rel="stylesheet" />
19
+ <link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500;600;700;800;900&amp;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>