feat: add tailwindcss integration and demo page

- Add tailwindcss-rails gem to Gemfile
- Create application.tailwind.css for Tailwind styles
- Update Procfile.dev for Tailwind CSS watch command
- Add demo action and view for showcasing features
- Update application layout to use Tailwind CSS classes
- Refactor footer and header for improved styling

This commit introduces Tailwind CSS for styling the application, enhancing the UI with utility-first CSS. A new demo page is also added to showcase the application features.
This commit is contained in:
songtianlun 2025-01-16 18:17:08 +08:00
parent 6ebc85c77a
commit cafe820a64
19 changed files with 1851 additions and 252 deletions

View File

@ -77,3 +77,5 @@ gem "jsbundling-rails", "~> 1.3"
group :production do
gem "pg", "~> 1.5"
end
gem "tailwindcss-rails", "~> 3.2"

View File

@ -385,6 +385,14 @@ GEM
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.2)
tailwindcss-rails (3.2.0)
railties (>= 7.0.0)
tailwindcss-ruby
tailwindcss-ruby (3.4.17-aarch64-linux)
tailwindcss-ruby (3.4.17-arm-linux)
tailwindcss-ruby (3.4.17-arm64-darwin)
tailwindcss-ruby (3.4.17-x86_64-darwin)
tailwindcss-ruby (3.4.17-x86_64-linux)
thor (1.3.2)
thruster (0.1.10)
thruster (0.1.10-aarch64-linux)
@ -455,6 +463,7 @@ DEPENDENCIES
solid_queue
sqlite3 (>= 2.1)
stimulus-rails
tailwindcss-rails (~> 3.2)
thruster
turbo-rails
tzinfo-data

View File

@ -1,3 +1,3 @@
web: env RUBY_DEBUG_OPEN=true bin/rails server
css: yarn watch:css
js: yarn build --watch
css: bin/rails tailwindcss:watch

View File

@ -1,2 +1,3 @@
//= link_tree ../images
// = link_tree ../builds
//= link_tree ../builds

View File

@ -0,0 +1 @@
<svg height='100px' width='100px' fill="#000000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 64 64" style="enable-background:new 0 0 64 64;" xml:space="preserve"><g><path d="M15,29c-3.309,0-6,2.691-6,6c0,2.206,1.794,4,4,4s4-1.794,4-4h-2c0,1.103-0.897,2-2,2s-2-0.897-2-2c0-2.206,1.794-4,4-4 c3.309,0,6,2.691,6,6c0,4.411-3.589,8-8,8C7.486,45,3,40.514,3,35c0-4.057,1.984-7.869,5.308-10.195l10.9-7.63 C21.583,15.513,23,12.79,23,9.891C23,4.989,19.011,1,14.109,1C12.395,1,11,2.395,11,4.109v16.371l-3.839,2.687 C3.303,25.867,1,30.291,1,35c0,5.934,4.334,10.863,10,11.819V58c0,1.654-1.346,3-3,3s-3-1.346-3-3c0-0.551,0.449-1,1-1s1,0.449,1,1 v1h2v-1c0-1.654-1.346-3-3-3s-3,1.346-3,3c0,2.757,2.243,5,5,5s5-2.243,5-5V47c5.514,0,10-4.486,10-10C23,32.589,19.411,29,15,29z M13,4.109C13,3.498,13.498,3,14.109,3C17.909,3,21,6.091,21,9.891c0,2.247-1.099,4.357-2.939,5.646L13,19.079V4.109z"></path><path d="M31,45.22l10,2v-8.04l-12-2.4V49h-2c-2.206,0-4,1.794-4,4s1.794,4,4,4s4-1.794,4-4V45.22z M31,39.22l8,1.6v3.96l-8-1.6 V39.22z M29,53c0,1.103-0.897,2-2,2s-2-0.897-2-2s0.897-2,2-2h2V53z"></path><path d="M51,18.895V29h-2c-2.206,0-4,1.794-4,4s1.794,4,4,4s4-1.794,4-4v-5.895l8,0.8V31h-2c-2.206,0-4,1.794-4,4s1.794,4,4,4 s4-1.794,4-4V20.095L51,18.895z M51,33c0,1.103-0.897,2-2,2s-2-0.897-2-2s0.897-2,2-2h2V33z M61,35c0,1.103-0.897,2-2,2 s-2-0.897-2-2s0.897-2,2-2h2V35z M53,25.095v-3.99l8,0.8v3.99L53,25.095z"></path><path d="M43,9h2v12h2V5c0-2.206-1.794-4-4-4s-4,1.794-4,4S40.794,9,43,9z M43,3c1.103,0,2,0.897,2,2v2h-2c-1.103,0-2-0.897-2-2 S41.897,3,43,3z"></path><path d="M29,23c2.206,0,4-1.794,4-4V3h-2v12h-2c-2.206,0-4,1.794-4,4S26.794,23,29,23z M29,17h2v2c0,1.103-0.897,2-2,2 s-2-0.897-2-2S27.897,17,29,17z"></path><path d="M36.792,61.086l0.813,1.828c8.887-3.949,15.894-11.447,19.224-20.572l-1.879-0.686 C51.804,50.275,45.186,57.357,36.792,61.086z"></path><path d="M56.434,16.628c-1.505-3.76-3.624-7.221-6.298-10.286l-1.507,1.314c2.526,2.896,4.527,6.165,5.949,9.715L56.434,16.628z"></path><path d="M53.532,39.309l-1.902-0.617c-3.047,9.39-11.047,16.797-20.879,19.332l0.499,1.937 C41.737,57.256,50.275,49.343,53.532,39.309z"></path><path d="M51.841,16.554c-0.713-1.432-1.547-2.823-2.481-4.134l-1.629,1.16c0.873,1.226,1.653,2.526,2.32,3.866L51.841,16.554z"></path><path d="M34.081,34.615l1.846,0.771C36.639,33.677,37,31.866,37,30c0-2.683-0.761-5.29-2.201-7.539l-1.685,1.078 C34.348,25.466,35,27.7,35,30C35,31.6,34.69,33.152,34.081,34.615z"></path><path d="M41,30c0,2.291-0.424,4.522-1.261,6.631l1.859,0.737C42.528,35.023,43,32.544,43,30c0-6.212-2.815-11.967-7.723-15.79 l-1.229,1.578C38.466,19.229,41,24.409,41,30z"></path></g></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,3 +1,3 @@
@import 'bootstrap/dist/css/bootstrap';
@import 'bootstrap-icons/font/bootstrap-icons';
@import './custom';
//@import './custom';

View File

@ -0,0 +1,31 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/*
@layer components {
.btn-primary {
@apply py-2 px-4 bg-blue-200;
}
}
*/
@layer base {
h1, h2, h3, h4, h5, h6 {
@apply leading-none;
}
h1 {
@apply text-[3em] tracking-[-2px] mb-[30px] text-center;
}
h2 {
@apply text-[1.2em] tracking-[-1px] mb-[30px] text-center font-normal text-gray-400;
}
p {
@apply text-[1.1em] leading-[1.7];
}
}

View File

@ -10,4 +10,7 @@ class StaticPagesController < ApplicationController
def contact
end
def demo
end
end

View File

@ -1,10 +1,12 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import './add_jquery'
// import './add_jquery'
import "jquery/dist/jquery"
import "bootstrap/dist/js/bootstrap"
// import "jquery/dist/jquery"
// import "bootstrap/dist/js/bootstrap"
import "flowbite/dist/flowbite.turbo"
import "./controllers"

View File

@ -1,13 +1,39 @@
<footer class="footer">
<small>
The <a href="https://www.railstutorial.org">Ruby on Rails Tutorial</a>
by <a href="https://www.michaelhartl.com">Michael Hartl</a>
<footer class="mt-12 pt-5 border-t border-gray-200 text-gray-600">
<div class="container mx-auto px-4">
<div class="flex flex-col md:flex-row md:justify-between items-center">
<!-- 左侧文本 -->
<small class="text-sm mb-4 md:mb-0">
The
<a href="https://www.railstutorial.org"
class="text-gray-600 hover:text-gray-900">
Ruby on Rails Tutorial
</a>
by
<a href="https://www.michaelhartl.com"
class="text-gray-600 hover:text-gray-900">
Michael Hartl
</a>
</small>
<!-- 右侧导航 -->
<nav>
<ul>
<li><%= link_to "About", about_url %></li>
<li><%= link_to "Contact", contact_url %></li>
<li><a href="https://news.railstutorial.org">News</a></li>
<ul class="flex flex-wrap justify-center space-x-4">
<li>
<%= link_to "About", about_url,
class: "text-gray-600 hover:text-gray-900" %>
</li>
<li>
<%= link_to "Contact", contact_url,
class: "text-gray-600 hover:text-gray-900" %>
</li>
<li>
<a href="https://news.railstutorial.org"
class="text-gray-600 hover:text-gray-900">
News
</a>
</li>
</ul>
</nav>
</div>
</div>
</footer>

View File

@ -1,42 +1,76 @@
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<%= link_to "sample app", root_url, id: "logo" %>
<nav>
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
<header class="fixed top-0 w-full bg-gray-900 text-white">
<div class="container mx-auto px-4">
<nav class="flex items-center justify-between h-16">
<!-- Logo -->
<%= link_to root_url, class: "text-2xl font-bold uppercase tracking-tighter hover:text-gray-300", id: "logo" do %>
sample app
<% end %>
<!-- Mobile menu button -->
<div class="md:hidden">
<button type="button"
class="text-gray-300 hover:text-white focus:outline-none"
data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1"
data-target="#mobile-menu"
aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<!-- Hamburger icon -->
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
</button>
</div>
<ul class="nav navbar-nav navbar-right collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<li><%= link_to "Home", root_url %></li>
<li><%= link_to "Help", help_url %></li>
<% if logged_in? %>
<li><%= link_to "Users", users_path %></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Account <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", edit_user_path(current_user) %></li>
<li class="divider"></li>
<li>
<%= link_to "Log out", logout_path, data: { turbo_method: :delete } %>
</li>
</ul>
</li>
<% else %>
<li><%= link_to "Log in", login_path %></li>
<% end %>
</ul>
</nav>
</div>
<!-- Desktop menu -->
<div class="hidden md:flex md:items-center md:space-x-4">
<%= link_to "Home", root_url, class: "hover:text-gray-300" %>
<%= link_to "Help", help_url, class: "hover:text-gray-300" %>
<% if logged_in? %>
<%= link_to "Users", users_path, class: "hover:text-gray-300" %>
<!-- Dropdown -->
<div class="relative group">
<button class="flex items-center hover:text-gray-300">
Account
<svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
<!-- Dropdown menu -->
<div class="absolute right-0 hidden group-hover:block mt-2 w-48 bg-white rounded-md shadow-lg py-1">
<%= link_to "Profile", current_user, class: "block px-4 py-2 text-gray-800 hover:bg-gray-100" %>
<%= link_to "Settings", edit_user_path(current_user), class: "block px-4 py-2 text-gray-800 hover:bg-gray-100" %>
<div class="border-t border-gray-100"></div>
<%= link_to "Log out", logout_path,
class: "block px-4 py-2 text-gray-800 hover:bg-gray-100",
data: { turbo_method: :delete } %>
</div>
</div>
<% else %>
<%= link_to "Log in", login_path, class: "hover:text-gray-300" %>
<% end %>
</div>
</nav>
<!-- Mobile menu -->
<div class="md:hidden hidden" id="mobile-menu">
<div class="px-2 pt-2 pb-3 space-y-1">
<%= link_to "Home", root_url, class: "block px-3 py-2 rounded-md hover:bg-gray-700" %>
<%= link_to "Help", help_url, class: "block px-3 py-2 rounded-md hover:bg-gray-700" %>
<% if logged_in? %>
<%= link_to "Users", users_path, class: "block px-3 py-2 rounded-md hover:bg-gray-700" %>
<%= link_to "Profile", current_user, class: "block px-3 py-2 rounded-md hover:bg-gray-700" %>
<%= link_to "Settings", edit_user_path(current_user), class: "block px-3 py-2 rounded-md hover:bg-gray-700" %>
<%= link_to "Log out", logout_path,
class: "block px-3 py-2 rounded-md hover:bg-gray-700",
data: { turbo_method: :delete } %>
<% else %>
<%= link_to "Log in", login_path, class: "block px-3 py-2 rounded-md hover:bg-gray-700" %>
<% end %>
</div>
</div>
</div>
</header>

View File

@ -5,13 +5,13 @@
<title><%= full_title(yield(:title)) %></title>
<%= render 'layouts/rails_default' %>
<%= render 'layouts/shim' %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<div class="container pt-16">
<% flash.each do |message_type, message| %>
<%= content_tag(:div, message, class: "alert alert-#{message_type}") %>
<!-- <div class="alert alert-<%#= message_type %>"><%#= message %></div>-->
@ -19,9 +19,39 @@
<%= yield %>
<%= render 'layouts/footer' %>
<%#= debug(params) if Rails.env.development? %>
<%= debug(params.to_yaml) if Rails.env.development? %>
<%= debug(session) if Rails.env.development? %>
<%= debug(Time.now) if Rails.env.development? %>
<%#= debug(params.to_yaml) if Rails.env.development? %>
<%#= debug(session) if Rails.env.development? %>
<%#= debug(Time.now) if Rails.env.development? %>
<% if Rails.env.development? %>
<div class="container mx-auto px-4 mb-8 pt-4">
<div class="max-w-4xl mx-auto border-2 border-gray-300 rounded-lg p-6 bg-gray-100">
<!-- Params -->
<div class="mb-6">
<h3 class="text-gray-700 font-bold mb-2">Params:</h3>
<pre class="bg-white p-4 rounded shadow overflow-x-auto text-sm text-gray-600 border border-gray-200">
<%= params.to_yaml %>
</pre>
</div>
<!-- Session -->
<div class="mb-6">
<h3 class="text-gray-700 font-bold mb-2">Session:</h3>
<pre class="bg-white p-4 rounded shadow overflow-x-auto text-sm text-gray-600 border border-gray-200">
<%= session %>
</pre>
</div>
<!-- Time -->
<div>
<h3 class="text-gray-700 font-bold mb-2">Current Time:</h3>
<pre class="bg-white p-4 rounded shadow overflow-x-auto text-sm text-gray-600 border border-gray-200">
<%= Time.now %>
</pre>
</div>
</div>
</div>
<% end %>
</div>
</body>
</html>

View File

@ -0,0 +1,10 @@
<div class="flex justify-center">
<div class="mx-4 order-last">
<%= image_tag("music.svg", alt:"music", width: "100") %>
</div>
<div class="mx-4 self-center">
<h1>Welcome to NorthBy</h1>
<h2>A premium in sight and sound</h2>
<button>Learn More</button>
</div>
</div>

View File

@ -1,6 +1,6 @@
#!/usr/bin/env sh
if gem list --no-installed --exact --silent foreman; then
if ! gem list foreman -i --silent; then
echo "Installing foreman..."
gem install foreman
fi
@ -8,4 +8,9 @@ fi
# Default to port 3000 if not specified
export PORT="${PORT:-3000}"
exec foreman start -f Procfile.dev --env /dev/null "$@"
# Let the debug gem allow remote connections,
# but avoid loading until `debugger` is called
export RUBY_DEBUG_OPEN="true"
export RUBY_DEBUG_LAZY="true"
exec foreman start -f Procfile.dev "$@"

View File

@ -1,6 +1,6 @@
Rails.application.routes.draw do
get "password_resets/new"
get "password_resets/edit"
# get "password_resets/new"
# get "password_resets/edit"
# get "sessions/new"
# get "users/new"
# get "static_pages/home"
@ -10,6 +10,8 @@ Rails.application.routes.draw do
root "static_pages#home"
get "/demo", to: "static_pages#demo"
get "/help", to: "static_pages#help"
get "/about", to: "static_pages#about"
get "/contact", to: "static_pages#contact"
@ -19,6 +21,8 @@ Rails.application.routes.draw do
post "/login", to: "sessions#create"
delete "/logout", to: "sessions#destroy"
get "pages/home"
resources :users
resources :account_activations, only: [ :edit ]
resources :password_resets, only: [ :new, :create, :edit, :update ]

25
config/tailwind.config.js Normal file
View File

@ -0,0 +1,25 @@
const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
content: [
'./public/*.html',
'./app/helpers/**/*.rb',
'./app/javascript/**/*.js',
'./app/views/**/*.{erb,haml,html,slim}',
'./node_modules/flowbite/**/*.js'
],
theme: {
extend: {
fontFamily: {
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [
require('@tailwindcss/typography'),
// require('flowbite/plugin')
// require('@tailwindcss/forms'),
// require('@tailwindcss/typography'),
// require('@tailwindcss/container-queries'),
]
}

1032
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@
"autoprefixer": "^10.4.20",
"bootstrap": "3",
"bootstrap-icons": "^1.11.3",
"flowbite": "^2.5.2",
"jquery": "^3.7.1",
"nodemon": "^3.1.9",
"postcss": "^8.4.49",
@ -25,6 +26,7 @@
"defaults"
],
"devDependencies": {
"@tailwindcss/typography": "^0.5.16",
"esbuild": "^0.24.2"
}
}

764
yarn.lock

File diff suppressed because it is too large Load Diff