diff --git a/ecosystem/platform/server/Gemfile b/ecosystem/platform/server/Gemfile
index a283daaca7826..114c18bc7d1fa 100644
--- a/ecosystem/platform/server/Gemfile
+++ b/ecosystem/platform/server/Gemfile
@@ -84,6 +84,7 @@ gem 'recaptcha', '~> 5.10'
# gem "image_processing", "~> 1.2"
gem 'tailwindcss-rails', '~> 2.0'
+gem 'view_component', '~> 2.54'
# Monitoring
gem 'lograge', '~> 0.12.0'
diff --git a/ecosystem/platform/server/Gemfile.lock b/ecosystem/platform/server/Gemfile.lock
index 5c5d31924974a..db4f977fecb86 100644
--- a/ecosystem/platform/server/Gemfile.lock
+++ b/ecosystem/platform/server/Gemfile.lock
@@ -417,6 +417,9 @@ GEM
unf_ext
unf_ext (0.0.8.1)
unicode-display_width (2.1.0)
+ view_component (2.54.1)
+ activesupport (>= 5.0.0, < 8.0)
+ method_source (~> 1.0)
warden (1.2.9)
rack (>= 2.0.9)
web-console (4.2.0)
@@ -482,6 +485,7 @@ DEPENDENCIES
tailwindcss-rails (~> 2.0)
turbo-rails
tzinfo-data
+ view_component (~> 2.54)
web-console
webdrivers
diff --git a/ecosystem/platform/server/app/components/button_component.html.erb b/ecosystem/platform/server/app/components/button_component.html.erb
new file mode 100644
index 0000000000000..2ee6239e8833d
--- /dev/null
+++ b/ecosystem/platform/server/app/components/button_component.html.erb
@@ -0,0 +1 @@
+<%= content_tag @tag, content, **@rest %>
diff --git a/ecosystem/platform/server/app/components/button_component.rb b/ecosystem/platform/server/app/components/button_component.rb
new file mode 100644
index 0000000000000..40dbfae4ba810
--- /dev/null
+++ b/ecosystem/platform/server/app/components/button_component.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+# Copyright (c) Aptos
+# SPDX-License-Identifier: Apache-2.0
+
+SCHEME_CLASSES = {
+ primary: 'bg-teal-400 hover:bg-teal-300 text-neutral-800 text-center font-mono uppercase font-bold',
+ secondary: 'border border-teal-400 hover:border-teal-300 text-center text-white font-mono uppercase'
+}.freeze
+
+SIZE_CLASSES = {
+ large: 'px-8 py-4 text-lg rounded',
+ medium: 'p-2 text-lg rounded',
+ small: 'py-1 text-sm rounded'
+}.freeze
+
+class ButtonComponent < ViewComponent::Base
+ def initialize(scheme: :primary,
+ size: :medium,
+ **rest)
+ @rest = rest
+
+ @tag = rest[:href] ? :a : :button
+ rest[:class] = [
+ SCHEME_CLASSES[scheme],
+ SIZE_CLASSES[size],
+ rest[:class]
+ ]
+ end
+end
diff --git a/ecosystem/platform/server/app/views/it1_profiles/_form.html.erb b/ecosystem/platform/server/app/views/it1_profiles/_form.html.erb
index f10ffdb4d64b3..8b8387da299df 100644
--- a/ecosystem/platform/server/app/views/it1_profiles/_form.html.erb
+++ b/ecosystem/platform/server/app/views/it1_profiles/_form.html.erb
@@ -87,7 +87,9 @@
- <%= f.submit "Validate node", class: "w-full bg-teal-400 text-neutral-800 block p-2 text-center font-mono uppercase text-lg rounded font-bold mb-8" %>
+ <%= render(ButtonComponent.new(type: :submit, class: 'w-full mb-8')) do %>
+ Validate node
+ <% end %>
<%= recaptcha_tags theme: :dark %>
diff --git a/ecosystem/platform/server/app/views/layouts/_header.html.erb b/ecosystem/platform/server/app/views/layouts/_header.html.erb
index 813aeecb76f10..c1fa2fe5d0519 100644
--- a/ecosystem/platform/server/app/views/layouts/_header.html.erb
+++ b/ecosystem/platform/server/app/views/layouts/_header.html.erb
@@ -3,7 +3,11 @@
- <%= link_to "Docs", "https://aptos.dev/", class: "font-mono border-teal-400 border rounded w-36 text-center py-1 uppercase text-sm" %>
- <%= link_to "Explorer", "https://explorer.devnet.aptos.dev/", class: "hidden sm:block font-mono border-teal-400 border rounded w-36 text-center py-1 uppercase text-sm" %>
+ <%= render(ButtonComponent.new(href: 'https://aptos.dev', scheme: :secondary, size: :small, class: 'w-36')) do %>
+ Docs
+ <% end %>
+ <%= render(ButtonComponent.new(href: 'https://explorer.devnet.aptos.dev/', scheme: :secondary, size: :small, class: 'hidden sm:block w-36')) do %>
+ Explorer
+ <% end %>
diff --git a/ecosystem/platform/server/app/views/onboarding/email.html.erb b/ecosystem/platform/server/app/views/onboarding/email.html.erb
index 99d213f9548b9..1826a93c36c7a 100644
--- a/ecosystem/platform/server/app/views/onboarding/email.html.erb
+++ b/ecosystem/platform/server/app/views/onboarding/email.html.erb
@@ -1,4 +1,4 @@
-
+
Welcome, <%= @oauth_username %>!
<%= render "layouts/flash" %>
@@ -29,7 +29,9 @@
- <%= f.submit "Verify email", class: "w-72 bg-teal-400 hover:bg-teal-300 cursor-pointer text-neutral-800 block p-2 text-center font-mono uppercase text-lg rounded" %>
+ <%= render(ButtonComponent.new(type: :submit, class: 'w-72')) do %>
+ Verify email
+ <% end %>
diff --git a/ecosystem/platform/server/app/views/welcome/index.html.erb b/ecosystem/platform/server/app/views/welcome/index.html.erb
index 8b57acb2bc5ca..1d7803a3c8bb9 100644
--- a/ecosystem/platform/server/app/views/welcome/index.html.erb
+++ b/ecosystem/platform/server/app/views/welcome/index.html.erb
@@ -33,6 +33,8 @@
- <%= link_to "Sign up for Testnet", "javascript:document.getElementById('login-dialog').showModal()", class: "w-full bg-teal-400 text-neutral-800 block p-2 text-center font-mono uppercase text-lg rounded font-bold mt-auto" %>
+ <%= render(ButtonComponent.new(size: :large, onclick: 'document.getElementById("login-dialog").showModal()', class: 'w-full mt-auto')) do %>
+ Sign up for Testnet
+ <% end %>
diff --git a/ecosystem/platform/server/app/views/welcome/it1.html.erb b/ecosystem/platform/server/app/views/welcome/it1.html.erb
index e1099c95c3929..cad21fc8fc96a 100644
--- a/ecosystem/platform/server/app/views/welcome/it1.html.erb
+++ b/ecosystem/platform/server/app/views/welcome/it1.html.erb
@@ -23,7 +23,9 @@
Register your node, and automatically verify that it is set up correctly.
- <%= link_to "Register", new_it1_profile_path, class: "w-full bg-teal-400 text-neutral-800 block p-2 text-center font-mono uppercase text-lg rounded font-bold mt-auto" %>
+ <%= render(ButtonComponent.new(href: new_it1_profile_path, class: 'w-full mt-auto')) do %>
+ Register
+ <% end %>
@@ -37,7 +39,9 @@
<% if current_user&.kyc_complete? %>
Verification Complete
<% elsif current_user&.it1_profile&.validator_verified? %>
- <%= link_to "Verify", onboarding_kyc_redirect_path, class: "w-full bg-teal-400 text-neutral-800 block p-2 text-center font-mono uppercase text-lg rounded font-bold mt-auto" %>
+ <%= render(ButtonComponent.new(href: onboarding_kyc_redirect_path, class: 'w-full mt-auto')) do %>
+ Verify
+ <% end %>
<% end %>
diff --git a/ecosystem/platform/server/config/tailwind.config.js b/ecosystem/platform/server/config/tailwind.config.js
index 9a55fce88bc71..ac7cde4fff324 100644
--- a/ecosystem/platform/server/config/tailwind.config.js
+++ b/ecosystem/platform/server/config/tailwind.config.js
@@ -2,6 +2,7 @@ const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
content: [
+ './app/components/**/*.{rb,erb}',
'./app/helpers/**/*.rb',
'./app/javascript/**/*.js',
'./app/views/**/*.{erb,haml,html,slim}'
diff --git a/ecosystem/platform/server/spec/components/button_component_spec.rb b/ecosystem/platform/server/spec/components/button_component_spec.rb
new file mode 100644
index 0000000000000..98bc30cb26337
--- /dev/null
+++ b/ecosystem/platform/server/spec/components/button_component_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# Copyright (c) Aptos
+# SPDX-License-Identifier: Apache-2.0
+
+require 'rails_helper'
+
+RSpec.describe ButtonComponent, type: :component do
+ pending "add some examples to (or delete) #{__FILE__}"
+
+ # it "renders something useful" do
+ # expect(
+ # render_inline(described_class.new(attr: "value")) { "Hello, components!" }.css("p").to_html
+ # ).to include(
+ # "Hello, components!"
+ # )
+ # end
+end