Skip to content

Commit

Permalink
feat: Adds dark theme support for public portal [CW-2525] (#7979)
Browse files Browse the repository at this point in the history
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
  • Loading branch information
nithindavid and iamsivin committed Oct 4, 2023
1 parent 6a73953 commit b71a580
Show file tree
Hide file tree
Showing 20 changed files with 178 additions and 80 deletions.
9 changes: 9 additions & 0 deletions app/controllers/public/api/v1/portals/base_controller.rb
@@ -1,5 +1,6 @@
class Public::Api::V1::Portals::BaseController < PublicController
before_action :show_plain_layout
before_action :set_color_scheme
around_action :set_locale
after_action :allow_iframe_requests

Expand All @@ -9,6 +10,14 @@ def show_plain_layout
@is_plain_layout_enabled = params[:show_plain_layout] == 'true'
end

def set_color_scheme
@theme = if %w[dark light].include?(params[:theme])
params[:theme]
else
''
end
end

def set_locale(&)
switch_locale_with_portal(&) if params[:locale].present?
switch_locale_with_article(&) if params[:article_slug].present?
Expand Down
11 changes: 11 additions & 0 deletions app/helpers/portal_helper.rb
@@ -0,0 +1,11 @@
module PortalHelper
def generate_portal_bg_color(portal_color, theme)
base_color = theme == 'dark' ? 'black' : 'white'
"color-mix(in srgb, #{portal_color} 10%, #{base_color})"
end

def generate_portal_bg(portal_color, theme)
bg_image = theme == 'dark' ? 'grid_dark.svg' : 'grid.svg'
"background: url(/assets/images/hc/#{bg_image}) #{generate_portal_bg_color(portal_color, theme)}"
end
end
8 changes: 4 additions & 4 deletions app/javascript/portal/components/PublicSearchInput.vue
@@ -1,16 +1,16 @@
<template>
<div
class="w-full flex items-center rounded-md border-solid border-2 h-16 bg-white px-4 py-2 text-slate-600"
class="w-full flex items-center rounded-md border-solid border-2 h-16 bg-white dark:bg-slate-900 px-4 py-2 text-slate-600 dark:text-slate-200"
:class="{
'shadow border-woot-100': isFocused,
'border-slate-50 shadow-sm': !isFocused,
'shadow border-woot-100 dark:border-woot-700': isFocused,
'border-slate-50 dark:border-slate-800 shadow-sm': !isFocused,
}"
>
<fluent-icon icon="search" />
<input
:value="value"
type="text"
class="w-full focus:outline-none text-base h-full bg-white px-2 py-2 text-slate-700 placeholder-slate-500"
class="w-full focus:outline-none text-base h-full bg-white dark:bg-slate-900 px-2 py-2 text-slate-700 dark:text-slate-100 placeholder-slate-500"
:placeholder="searchPlaceholder"
role="search"
@input="onChange"
Expand Down
21 changes: 15 additions & 6 deletions app/javascript/portal/components/SearchSuggestions.vue
@@ -1,24 +1,30 @@
<template>
<div
class="shadow-md bg-white mt-2 max-h-72 scroll-py-2 p-4 rounded overflow-y-auto text-sm text-slate-700"
class="shadow-md bg-white dark:bg-slate-900 mt-2 max-h-72 scroll-py-2 p-4 rounded overflow-y-auto text-sm text-slate-700 dark:text-slate-100"
>
<div v-if="isLoading" class="font-medium text-sm text-slate-400">
<div
v-if="isLoading"
class="font-medium text-sm text-slate-400 dark:text-slate-700"
>
{{ loadingPlaceholder }}
</div>
<h3 v-if="shouldShowResults" class="font-medium text-sm text-slate-400">
<h3
v-if="shouldShowResults"
class="font-medium text-sm text-slate-400 dark:text-slate-700"
>
{{ resultsTitle }}
</h3>
<ul
v-if="shouldShowResults"
class="bg-white mt-2 max-h-72 scroll-py-2 overflow-y-auto text-sm text-slate-700"
class="bg-white dark:bg-slate-900 mt-2 max-h-72 scroll-py-2 overflow-y-auto text-sm text-slate-700 dark:text-slate-100"
role="listbox"
>
<li
v-for="(article, index) in items"
:id="article.id"
:key="article.id"
class="group flex cursor-default select-none items-center rounded-md p-2 mb-1"
:class="{ 'bg-slate-25': index === selectedIndex }"
:class="{ 'bg-slate-25 dark:bg-slate-800': index === selectedIndex }"
role="option"
tabindex="-1"
@mouseover="onHover(index)"
Expand All @@ -32,7 +38,10 @@
</li>
</ul>

<div v-if="showEmptyResults" class="font-medium text-sm text-slate-400">
<div
v-if="showEmptyResults"
class="font-medium text-sm text-slate-400 dark:text-slate-700"
>
{{ emptyPlaceholder }}
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/javascript/portal/components/TableOfContents.vue
Expand Up @@ -4,7 +4,7 @@
<nav class="max-w-2xl">
<h2
id="on-this-page-title"
class="text-slate-800 font-semibold tracking-wide border-b mb-3 leading-7"
class="text-slate-800 dark:text-slate-50 font-semibold tracking-wide border-b mb-3 leading-7"
>
{{ tocHeader }}
</h2>
Expand All @@ -14,7 +14,7 @@
<a
:href="`#${element.slug}`"
data-turbolinks="false"
class="text-base text-slate-800 cursor-pointer"
class="text-base text-slate-800 dark:text-slate-50 cursor-pointer"
>
{{ element.title }}
</a>
Expand Down
9 changes: 7 additions & 2 deletions app/views/layouts/portal.html.erb
Expand Up @@ -28,8 +28,8 @@ By default, it renders:
<% end %>
</head>
<body>
<div class="antialiased">
<main class="main-content min-h-screen flex flex-col" role="main">
<div class="antialiased <%= @theme %>">
<main class="main-content min-h-screen flex flex-col bg-white dark:bg-slate-900" role="main">
<% if !@is_plain_layout_enabled %>
<%= render "public/api/v1/portals/header", portal: @portal %>
<% end %>
Expand All @@ -40,6 +40,11 @@ By default, it renders:
</main>
</div>
</body>
<style>
:root {
color-scheme: '<%= @theme %>';
}
</style>
<script>
window.portalConfig = {
portalSlug: '<%= @portal.slug %>',
Expand Down
18 changes: 9 additions & 9 deletions app/views/public/api/v1/portals/_category-block.html.erb
@@ -1,7 +1,7 @@
<section class="bg-white lg:container w-full py-6 px-4 flex flex-col h-full">
<section class="lg:container w-full py-6 px-4 flex flex-col h-full">
<div class="flex justify-between items-center w-full">
<h3 class="text-xl text-slate-800 font-medium leading-relaxed hover:underline">
<a href="/hc/<%= portal.slug %>/<%= category.locale %>/categories/<%= category.slug %>">
<h3 class="text-xl text-slate-800 dark:text-slate-50 font-medium leading-relaxed hover:underline">
<a href="/hc/<%= portal.slug %>/<%= category.locale %>/categories/<%= category.slug %><%= @theme.present? ? '?theme='+@theme : '' %>">
<%= category.name %>
</a>
</h3>
Expand All @@ -11,20 +11,20 @@
</div>
<div class="py-4 w-full mt-2 flex-grow">
<% if category.articles.published.size == 0 %>
<div class="h-full flex items-center justify-center bg-slate-50 rounded-xl mb-4">
<div class="h-full flex items-center justify-center bg-slate-50 dark:bg-slate-800 rounded-xl mb-4">
<p class="text-sm text-slate-500"><%= I18n.t('public_portal.common.no_articles') %></p>
</div>
<% else %>
<% category.articles.published.order(position: :asc).take(5).each do |article| %>
<a
class="text-slate-800 hover:underline leading-8"
href="/hc/<%= portal.slug %>/articles/<%= article.slug %>"
class="text-slate-800 dark:text-slate-50 hover:underline leading-8"
href="/hc/<%= portal.slug %>/articles/<%= article.slug %><%= @theme.present? ? '?theme='+@theme : '' %>"
>
<div class="flex justify-between content-center my-1 -mx-1 p-1 rounded-lg hover:bg-slate-25">
<div class="flex justify-between content-center my-1 -mx-1 p-1 rounded-lg hover:bg-slate-25 dark:hover:bg-slate-800">
<%= article.title %>
<span class="flex items-center">
<svg
class="w-4 h-4 fill-current text-slate-700"
class="w-4 h-4 fill-current text-slate-700 dark:text-slate-200"
width="24"
height="24"
fill="none"
Expand All @@ -42,7 +42,7 @@
</div>
<div>
<a
href="/hc/<%= portal.slug %>/<%= category.locale %>/categories/<%= category.slug %>"
href="/hc/<%= portal.slug %>/<%= category.locale %>/categories/<%= category.slug %><%= @theme.present? ? '?theme='+@theme : '' %>"
class="flex flex-row items-center text-base font-medium text-woot-500 hover:underline mt-4"
style="color: <%= portal.color %>"
>
Expand Down
2 changes: 1 addition & 1 deletion app/views/public/api/v1/portals/_footer.html.erb
@@ -1,7 +1,7 @@

<footer class="pt-16 pb-8 flex flex-col items-center justify-center">
<div class="mx-auto max-w-2xl">
<p class="text-slate-700 py-2 text-center">
<p class="text-slate-700 dark:text-slate-100 py-2 text-center">
<%= I18n.t('public_portal.footer.made_with') %> <a class="hover:underline" href="https://www.chatwoot.com" target="_blank" rel="noopener noreferrer nofoll/ow">Chatwoot</a> 馃挋
</p>
</div>
Expand Down
16 changes: 8 additions & 8 deletions app/views/public/api/v1/portals/_header.html.erb
@@ -1,19 +1,19 @@

<header class="bg-white w-full shadow-sm sticky top-0 z-50">
<nav class=" flex bg-white mx-auto max-w-6xl px-8" aria-label="Top">
<header class="bg-white dark:bg-slate-900 w-full shadow-sm sticky top-0 z-50">
<nav class=" flex mx-auto max-w-6xl px-8" aria-label="Top">
<div class="w-full py-5 flex items-center">
<a href="/hc/<%= @portal.slug %>/<%= @portal.config['default_locale'] || params[:locale] %>/" class="h-10 text-lg flex items-center text-slate-900 font-semibold">
<a href="/hc/<%= @portal.slug %>/<%= @portal.config['default_locale'] || params[:locale] %>/<%= @theme.present? ? '?theme='+@theme : '' %>" class="h-10 text-lg flex items-center text-slate-900 dark:text-white font-semibold">
<% if @portal.logo.present? %>
<img src="<%= url_for(@portal.logo) %>" class="h-10 w-auto mr-2" />
<% end %>
<%= @portal.name %>
</a>
<% if @portal.homepage_link %>
<div class="ml-8 border-l-1 border-slate-50 hidden md:block">
<div class="ml-8 border-l-1 border-slate-50 dark:border-slate-800 hidden md:block">
<div class="flex-grow flex-shrink-0">
<a target="_blank" rel="noopener noreferrer nofollow" href="<%= @portal.homepage_link %>" class="flex flex-row items-center text-sm font-medium text-slate-700 hover:text-slate-800 hover:underline"> <%= I18n.t('public_portal.header.go_to_homepage') %>
<a target="_blank" rel="noopener noreferrer nofollow" href="<%= @portal.homepage_link %>" class="flex flex-row items-center text-sm font-medium text-slate-700 dark:text-slate-200 hover:text-slate-800 dark:hover:text-slate-300 hover:underline"> <%= I18n.t('public_portal.header.go_to_homepage') %>
<span class="ml-2">
<svg class="w-4 h-4 fill-current text-slate-600" width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13.267 4.209a.75.75 0 0 0-1.034 1.086l6.251 5.955H3.75a.75.75 0 0 0 0 1.5h14.734l-6.251 5.954a.75.75 0 0 0 1.034 1.087l7.42-7.067a.996.996 0 0 0 .3-.58.758.758 0 0 0-.001-.29.995.995 0 0 0-.3-.578l-7.419-7.067Z" /></svg>
<svg class="w-4 h-4 fill-current text-slate-600 dark:text-slate-200" width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13.267 4.209a.75.75 0 0 0-1.034 1.086l6.251 5.955H3.75a.75.75 0 0 0 0 1.5h14.734l-6.251 5.954a.75.75 0 0 0 1.034 1.087l7.42-7.067a.996.996 0 0 0 .3-.58.758.758 0 0 0-.001-.29.995.995 0 0 0-.3-.578l-7.419-7.067Z" /></svg>
</span>
</a>
</div>
Expand All @@ -25,13 +25,13 @@
<div class="inline-flex relative w-24">
<select
data-portal-slug="<%= @portal.slug %>"
class="appearance-none w-full bg-white px-3 py-2 pr-8 rounded leading-tight focus:outline-none focus:shadow-outline locale-switcher hover:bg-slate-75 cursor-pointer"
class="appearance-none w-full bg-white dark:bg-slate-900 dark:text-slate-100 px-3 py-2 pr-8 rounded leading-tight focus:outline-none focus:shadow-outline locale-switcher hover:bg-slate-75 dark:hover:bg-slate-800 cursor-pointer"
>
<% @portal.config["allowed_locales"].each do |locale| %>
<option <%= locale == params[:locale] ? 'selected': '' %> value="<%= locale %>"><%= locale %></option>
<% end %>
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-slate-700 dark:text-slate-200">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg>
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions app/views/public/api/v1/portals/_hero.html.erb
@@ -1,10 +1,10 @@
<% if !@is_plain_layout_enabled %>
<section class="pt-8 pb-16 md:py-20 w-full bg-woot-50 shadow-inner" style="background: url(/assets/images/hc/grid.svg) color-mix(in srgb, <%= @portal.color %> 10%, white)">
<section class="pt-8 pb-16 md:py-20 w-full bg-woot-50 dark:bg-woot-900 shadow-inner" style="<%= generate_portal_bg(@portal.color, @theme) %>">
<div class="mx-auto max-w-6xl px-8 flex flex-col items-center sm:items-start">
<h1 class="text-2xl md:text-4xl text-slate-900 font-semibold leading-normal">
<h1 class="text-2xl md:text-4xl text-slate-900 dark:text-white font-semibold leading-normal">
<%= portal.header_text %>
</h1>
<p class="text-slate-600 text-center text-lg leading-normal pt-4 pb-4"><%= I18n.t('public_portal.hero.sub_title') %></p>
<p class="text-slate-600 dark:text-slate-200 text-center text-lg leading-normal pt-4 pb-4"><%= I18n.t('public_portal.hero.sub_title') %></p>
<div id="search-wrap"></div>
</div>
</section>
Expand Down
12 changes: 6 additions & 6 deletions app/views/public/api/v1/portals/_uncategorized-block.html.erb
@@ -1,6 +1,6 @@
<section class="bg-white lg:container w-full py-6 px-4 flex flex-col h-full">
<section class="lg:container w-full py-6 px-4 flex flex-col h-full">
<div class="flex justify-between items-center w-full">
<h3 class="text-xl text-slate-900 font-semibold leading-relaxed hover:underline">
<h3 class="text-xl text-slate-900 dark:text-white font-semibold leading-relaxed hover:underline">
<%= category %>
</h3>
<span class="text-slate-500">
Expand All @@ -10,14 +10,14 @@
<div class="py-4 w-full mt-2 flex-grow">
<% portal.articles.published.where(category_id: nil).order(position: :asc).take(5).each do |article| %>
<a
class="text-slate-800 hover:underline leading-8"
href="/hc/<%= portal.slug %>/articles/<%= article.slug %>"
class="text-slate-800 dark:text-slate-100 hover:underline leading-8"
href="/hc/<%= portal.slug %>/articles/<%= article.slug %><%= @theme.present? ? '?theme='+@theme : '' %>"
>
<div class="flex justify-between content-center my-1 -mx-1 p-1 rounded-lg hover:bg-slate-25">
<div class="flex justify-between content-center my-1 -mx-1 p-1 rounded-lg hover:bg-slate-25 dark:hover:bg-slate-800">
<%= article.title %>
<span class="flex items-center">
<svg
class="w-4 h-4 fill-current text-slate-700"
class="w-4 h-4 fill-current text-slate-700 dark:text-slate-200"
width="24"
height="24"
fill="none"
Expand Down
@@ -1,4 +1,4 @@
<h1 class="text-3xl font-semibold md:tracking-normal leading-snug md:text-4xl text-slate-900">
<h1 class="text-3xl font-semibold md:tracking-normal leading-snug md:text-4xl text-slate-900 dark:text-white">
<%= article.title %>
</h1>
<div class="flex flex-col items-start justify-between w-full md:flex-row md:items-center pt-2">
Expand All @@ -9,8 +9,8 @@
</div>
<% end %>
<div>
<h5 class="text-base font-medium text-slate-900 mb-2"><%= article.author.available_name %></h5>
<p class="text-sm font-normal text-slate-700">
<h5 class="text-base font-medium text-slate-900 dark:text-white mb-2"><%= article.author.available_name %></h5>
<p class="text-sm font-normal text-slate-700 dark:text-slate-100">
<%= I18n.t('public_portal.common.last_updated_on', last_updated_on: article.updated_at.strftime("%b %d, %Y")) %>
</div>
</div>
Expand Down
12 changes: 6 additions & 6 deletions app/views/public/api/v1/portals/articles/index.html.erb
@@ -1,25 +1,25 @@
<div class="bg-slate-50">
<div class="bg-slate-50 dark:bg-slate-800">
<div class="max-w-4xl px-6 py-16 mx-auto space-y-12 w-full">
<div class="space-y-4">
<div>
<a
class="text-slate-800 hover:underline leading-8"
href="/hc/<%= @portal.slug %>/<%= @category.present? ? @category.slug : '' %>"
href="/hc/<%= @portal.slug %>/<%= @category.present? ? @category.slug : '' %><%= @theme.present? ? '?theme='+@theme : '' %>"
>
<%= @portal.name %> <%= I18n.t('public_portal.common.home') %>
</a>
<span>/</span>
<span>/</span>
</div>
<% @articles.each do |article| %>
<h1 class="text-4xl font-semibold md:tracking-normal leading-snug md:text-5xl text-slate-900">
<h1 class="text-4xl font-semibold md:tracking-normal leading-snug md:text-5xl text-slate-900 dark:text-white">
<%= article.title %></h1>
<div class="flex flex-col items-start justify-between w-full md:flex-row md:items-center pt-2">
<div class="flex items-center space-x-2">
<img src="<%= article.author.avatar_url %>" alt="" class="w-12 h-812 border rounded-full">
<div>
<h5 class="text-base font-medium text-slate-900 mb-2"><%= article.author.name %></h5>
<p class="text-sm font-normal text-slate-700">
<h5 class="text-base font-medium text-slate-900 dark:text-white mb-2"><%= article.author.name %></h5>
<p class="text-sm font-normal text-slate-700 dark:text-slate-100">
<%= article.author.updated_at.strftime("%B %d %Y") %></p>
</div>
</div>
Expand All @@ -30,7 +30,7 @@
</div>
<div class="max-w-4xl flex-grow w-full px-8 py-16 mx-auto space-y-12">
<article class="space-y-8">
<div class="text-slate-800 font-sans leading-8 text-lg max-w-3xl blog-content">
<div class="text-slate-800 dark:text-slate-50 font-sans leading-8 text-lg max-w-3xl blog-content">
</div>
</article>
</div>
16 changes: 8 additions & 8 deletions app/views/public/api/v1/portals/articles/show.html.erb
Expand Up @@ -12,25 +12,25 @@
<% end %>
<% if !@is_plain_layout_enabled %>
<div class="bg-woot-50 py-8 shadow-inner" style="background: url(/assets/images/hc/grid.svg) color-mix(in srgb, <%= @portal.color %> 10%, white)">
<div class="bg-woot-50 dark:bg-woot-900 py-8 shadow-inner" style="<%= generate_portal_bg(@portal.color, @theme) %>">
<div class="max-w-6xl px-8 pt-8 pb-16 mx-auto space-y-4 w-full">
<div>
<a
class="text-slate-700 hover:underline leading-8 text-sm font-semibold"
href="/hc/<%= @portal.slug %>/<%= @article.category&.locale %>"
class="text-slate-700 dark:text-slate-100 hover:underline leading-8 text-sm font-semibold"
href="/hc/<%= @portal.slug %>/<%= @article.category&.locale %><%= @theme.present? ? '?theme='+@theme : '' %>"
>
Home
</a>
<span class="text-xs text-slate-600 px-1">/</span>
<span class="text-xs text-slate-600 dark:text-slate-200 px-1">/</span>
<% if @article.category %>
<a
class="text-slate-700 hover:underline leading-8 text-sm font-semibold"
href="/hc/<%= @portal.slug %>/<%= @article.category.locale %>/categories/<%= @article.category.slug %>"
class="text-slate-700 dark:text-slate-100 hover:underline leading-8 text-sm font-semibold"
href="/hc/<%= @portal.slug %>/<%= @article.category.locale %>/categories/<%= @article.category.slug %><%= @theme.present? ? '?theme='+@theme : '' %>"
>
<%= @article.category&.name %>
</a>
<% else %>
<span class="text-slate-700 leading-8 text-sm font-semibold" > Uncategorized </span>
<span class="text-slate-700 dark:text-slate-100 leading-8 text-sm font-semibold" > Uncategorized </span>
<% end %>
</div>
<%= render "public/api/v1/portals/articles/article_header", article: @article %>
Expand All @@ -43,7 +43,7 @@
<% end %>

<div class="flex max-w-6xl w-full px-8 mx-auto">
<article id="cw-article-content" class="flex-grow flex-2 mx-auto text-slate-800 text-lg max-w-3xl prose break-words w-full <%= @is_plain_layout_enabled ? 'py-4' : 'py-12' %>">
<article id="cw-article-content" class="flex-grow flex-2 mx-auto text-slate-800 dark:text-slate-50 text-lg max-w-3xl prose dark:prose-invert break-words w-full <%= @is_plain_layout_enabled ? 'py-4' : 'py-12' %>">
<%= @parsed_content %>
</article>
<div class="flex-1" id="cw-hc-toc"></div>
Expand Down

0 comments on commit b71a580

Please sign in to comment.