feat: Updated the design of the article page (#8166)

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
Sivin Varghese
2023-11-09 07:35:13 +05:30
committed by GitHub
parent 950f085e80
commit f018b0013c
15 changed files with 115 additions and 58 deletions

View File

@@ -1,20 +1,29 @@
<template> <template>
<div class="hidden lg:block flex-1 scroll-mt-24 pl-4"> <div class="hidden lg:block flex-1 py-6 scroll-mt-24 pl-4">
<div v-if="rows.length > 0" class="sticky top-24 py-12 overflow-auto"> <div v-if="rows.length > 0" class="sticky top-24 py-2 overflow-auto">
<nav class="max-w-2xl"> <nav class="max-w-2xl">
<h2 <h2
id="on-this-page-title" id="on-this-page-title"
class="text-slate-800 dark:text-slate-50 font-semibold tracking-wide border-b mb-3 leading-7" class="text-slate-800 pl-6 dark:text-slate-50 font-semibold tracking-wide py-3 leading-7 border-l-2 border-solid border-slate-100 dark:border-slate-800"
:class="{
'!border-slate-400 dark:!border-slate-100': !currentSlug,
}"
> >
{{ tocHeader }} {{ tocHeader }}
</h2> </h2>
<ol role="list" class="mt-4 space-y-3 text-base"> <ol role="list" class="text-base">
<li v-for="element in rows" :key="element.slug" class="leading-6"> <li
v-for="element in rows"
:key="element.slug"
class="leading-6 py-2 pl-6 border-l-2 border-solid"
:class="elementBorderStyles(element)"
>
<p :class="getClassName(element)"> <p :class="getClassName(element)">
<a <a
:href="`#${element.slug}`" :href="`#${element.slug}`"
data-turbolinks="false" data-turbolinks="false"
class="text-base text-slate-800 dark:text-slate-50 cursor-pointer" class="text-base cursor-pointer"
:class="elementTextStyles(element)"
> >
{{ element.title }} {{ element.title }}
</a> </a>
@@ -33,6 +42,11 @@ export default {
default: () => [], default: () => [],
}, },
}, },
data() {
return {
currentSlug: window.location?.hash?.substring(1) || '',
};
},
computed: { computed: {
tocHeader() { tocHeader() {
return window.portalConfig.tocHeader; return window.portalConfig.tocHeader;
@@ -44,6 +58,12 @@ export default {
return this.rows.filter(el => el.tag === 'h2').length; return this.rows.filter(el => el.tag === 'h2').length;
}, },
}, },
mounted() {
window.addEventListener('hashchange', this.onURLHashChange);
},
beforeDestroy() {
window.removeEventListener('hashchange', this.onURLHashChange);
},
methods: { methods: {
getClassName(el) { getClassName(el) {
if (el.tag === 'h1') { if (el.tag === 'h1') {
@@ -65,6 +85,30 @@ export default {
return ''; return '';
}, },
onURLHashChange() {
this.currentSlug = window.location?.hash?.substring(1) || '';
},
isElementActive(el) {
return this.currentSlug === el.slug;
},
tocHeaderBorderStyles() {
if (this.currentSlug === '') {
return 'border-slate-400 dark:border-slate-100';
}
return 'border-slate-100 dark:border-slate-800';
},
elementBorderStyles(el) {
if (this.isElementActive(el)) {
return 'border-slate-400 dark:border-slate-50 transition-colors duration-200';
}
return 'border-slate-100 dark:border-slate-800';
},
elementTextStyles(el) {
if (this.isElementActive(el)) {
return 'font-semibold text-slate-900 dark:text-slate-25';
}
return 'text-slate-700 dark:text-slate-100';
},
}, },
}; };
</script> </script>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 160 KiB

View File

@@ -1,8 +1,11 @@
<footer class="pt-16 pb-8 flex flex-col items-center justify-center"> <footer class="pt-16 pb-8 flex flex-col items-center justify-center">
<div class="mx-auto max-w-2xl"> <div class="mx-auto max-w-2xl text-center py-2">
<p class="text-slate-700 dark:text-slate-100 py-2 text-center"> <div class="flex items-center gap-2">
<%= 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> 💙 <%= render partial: 'icons/chatwoot-logo' %>
</p> <p class="text-slate-700 dark:text-slate-300 text-sm font-medium 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>
</div> </div>
</footer> </footer>

View File

@@ -1,6 +1,6 @@
<header class="bg-white dark:bg-slate-900 w-full shadow-sm sticky top-0 z-50"> <header class="bg-white dark:bg-slate-900 w-full shadow-sm sticky top-0 z-50">
<nav class=" flex mx-auto max-w-5xl px-8" aria-label="Top"> <nav class=" flex mx-auto max-w-5xl px-4 md:px-8" aria-label="Top">
<div class="w-full py-5 flex items-center"> <div class="w-full py-5 flex items-center overflow-hidden">
<a href="/hc/<%= @portal.slug %>/<%= @portal.config['default_locale'] || params[:locale] %>/<%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>" class="h-10 text-lg flex items-center text-slate-900 dark:text-white font-semibold"> <a href="/hc/<%= @portal.slug %>/<%= @portal.config['default_locale'] || params[:locale] %>/<%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>" class="h-10 text-lg flex items-center text-slate-900 dark:text-white font-semibold">
<% if @portal.logo.present? %> <% if @portal.logo.present? %>
<img src="<%= url_for(@portal.logo) %>" class="h-10 w-auto mr-2" /> <img src="<%= url_for(@portal.logo) %>" class="h-10 w-auto mr-2" />
@@ -10,7 +10,7 @@
</div> </div>
<%# Go to homepage link section %> <%# Go to homepage link section %>
<div class="flex items-center justify-between gap-5"> <div class="flex items-center justify-between gap-2 sm:gap-5">
<% if @portal.homepage_link %> <% if @portal.homepage_link %>
<div class="ml-8 border-l-1 border-slate-50 dark:border-slate-800 hidden md:block cursor-pointer px-1 py-2"> <div class="ml-8 border-l-1 border-slate-50 dark:border-slate-800 hidden md:block cursor-pointer px-1 py-2">
<div class="flex-grow flex-shrink-0"> <div class="flex-grow flex-shrink-0">

View File

@@ -1,7 +1,7 @@
<% if !@is_plain_layout_enabled %> <% if !@is_plain_layout_enabled %>
<section id="portal-bg" class="w-full bg-woot-50 dark:bg-woot-900 shadow-inner" style="<%= generate_portal_bg(@portal.color, @theme) %>"> <section id="portal-bg" class="w-full bg-woot-50 dark:bg-woot-900 shadow-inner" style="<%= generate_portal_bg(@portal.color, @theme) %>">
<div id="portal-bg-gradient" class="pt-8 pb-8 md:pt-14 md:pb-6" style="<%= generate_gradient_to_bottom(@theme) %>"> <div id="portal-bg-gradient" class="pt-8 pb-8 md:pt-14 md:pb-6" style="<%= generate_gradient_to_bottom(@theme) %>">
<div class="mx-auto max-w-5xl px-8 flex flex-col items-center sm:items-start"> <div class="mx-auto max-w-5xl px-4 md:px-8 flex flex-col items-center sm:items-start">
<h1 class="text-2xl md:text-4xl text-slate-900 dark:text-white font-semibold leading-normal"> <h1 class="text-2xl md:text-4xl text-slate-900 dark:text-white font-semibold leading-normal">
<%= portal.header_text %> <%= portal.header_text %>
</h1> </h1>

View File

@@ -1,7 +1,7 @@
<section class="lg:container w-full py-6 px-4 flex flex-col h-full"> <section class="lg:container w-full flex flex-col h-full">
<div class="flex justify-between items-center w-full"> <div class="flex justify-between items-center w-full">
<h3 class="text-xl text-slate-900 dark:text-white font-semibold leading-relaxed hover:underline"> <h3 class="text-xl text-slate-900 dark:text-white font-semibold leading-relaxed hover:underline">
<%= category %> <%= I18n.t('public_portal.header.uncategorized') %>
</h3> </h3>
<span class="text-slate-500"> <span class="text-slate-500">
<%= render 'public/api/v1/portals/article_count', article_count: portal.articles.published.where(category_id: nil).size %> <%= render 'public/api/v1/portals/article_count', article_count: portal.articles.published.where(category_id: nil).size %>
@@ -31,5 +31,5 @@
</div> </div>
</a> </a>
<% end %> <% end %>
</div> </div>
</section> </section>

View File

@@ -1,17 +1,31 @@
<h1 class="text-3xl font-semibold md:tracking-normal leading-snug md:text-4xl text-slate-900 dark:text-white"> <div class="flex items-center flex-row mb-6 gap-px">
<a
class="text-slate-500 dark:text-slate-200 text-sm gap-1 hover:cursor-pointer <%= @is_plain_layout_enabled && 'hover:underline' %> leading-8 font-semibold"
href="/hc/<%= @portal.slug %>/<%= @article.category&.locale %><%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>"
>
<%= I18n.t('public_portal.common.home') %>
</a>
<span class="w-4 h-4 [&>svg]:w-3 [&>svg]:h-3 flex items-center justify-center text-xs text-slate-500 dark:text-slate-300"><%= render partial: 'icons/chevron-right' %></span>
<% if @article.category %>
<a class="text-slate-500 dark:text-slate-200 text-sm gap-1 whitespace-nowrap hover:cursor-pointer <%= @is_plain_layout_enabled && 'hover:underline' %> leading-8 font-semibold" href="/hc/<%= @portal.slug %>/<%= @article.category.locale %>/categories/<%= @article.category.slug %><%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>">
<%= @article.category&.name %>
</a>
<span class="w-4 h-4 [&>svg]:w-3 [&>svg]:h-3 flex items-center justify-center text-xs text-slate-500 dark:text-slate-300"><%= render partial: 'icons/chevron-right' %></span>
<span class="text-sm text-slate-800 dark:text-slate-100 font-semibold overflow-hidden text-ellipsis min-w-0 whitespace-nowrap"><%= @article.title %></span>
<% else %>
<span class="text-slate-700 dark:text-slate-100 leading-8 text-sm font-semibold" ><%= I18n.t('public_portal.header.uncategorized') %></span>
<% end %>
</div>
<h1 class="text-3xl font-semibold leading-normal md:tracking-normal md:text-4xl text-slate-900 dark:text-white">
<%= article.title %> <%= article.title %>
</h1> </h1>
<div class="flex flex-col items-start justify-between w-full md:flex-row md:items-center pt-2"> <div class="flex flex-col items-start justify-between w-full md:flex-row md:items-center pt-6">
<div class="flex items-center space-x-2"> <div class="flex items-start space-x-1">
<% if article.author&.avatar_url&.present? %> <% if article.author&.avatar_url&.present? %>
<div class="pr-1"> <div class="pr-px mt-0.5 min-w-[20px] min-h-[20px]">
<img src="<%= article.author.avatar_url %>" alt="<%= article.author.display_name %>" class="w-12 h-12 border rounded-full"> <img src="<%= article.author.avatar_url %>" alt="<%= article.author.display_name %>" class="w-5 h-5 border rounded-full">
</div> </div>
<% end %> <% end %>
<div> <span class="flex items-center text-base text-slate-600 dark:text-slate-400 font-medium">By <%= article.author.available_name %> • <%= I18n.t('public_portal.common.last_updated_on', last_updated_on: article.updated_at.strftime("%b %d, %Y")) %></span>
<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> </div>
</div> </div>

View File

@@ -4,7 +4,7 @@
<div> <div>
<a <a
class="text-slate-800 hover:underline leading-8" class="text-slate-800 hover:underline leading-8"
href="/hc/<%= @portal.slug %>/<%= @category.present? ? @category.slug : '' %><%= @theme.present? ? '?theme='+@theme : '' %>" href="/hc/<%= @portal.slug %>/<%= @category.present? ? @category.slug : '' %><%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>"
> >
<%= @portal.name %> <%= I18n.t('public_portal.common.home') %> <%= @portal.name %> <%= I18n.t('public_portal.common.home') %>
</a> </a>

View File

@@ -12,41 +12,27 @@
<% end %> <% end %>
<% if !@is_plain_layout_enabled %> <% if !@is_plain_layout_enabled %>
<div class="bg-woot-50 dark:bg-woot-900 shadow-inner" style="<%= generate_portal_bg(@portal.color, @theme) %>"> <div id="portal-bg" class="bg-woot-50 dark:bg-woot-900 shadow-inner" style="<%= generate_portal_bg(@portal.color, @theme) %>">
<div class="py-8" style="<%= generate_gradient_to_bottom(@theme) %>"> <div id="portal-bg-gradient" class="pt-8 pb-8 md:pt-14 md:pb-6" style="<%= generate_gradient_to_bottom(@theme) %>">
<div class="max-w-6xl px-8 pt-8 pb-16 mx-auto space-y-4 w-full"> <div class="max-w-5xl px-4 md:px-8 mx-auto flex flex-col">
<div>
<a
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 dark:text-slate-200 px-1">/</span>
<% if @article.category %>
<a
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 dark:text-slate-100 leading-8 text-sm font-semibold" > Uncategorized </span>
<% end %>
</div>
<%= render "public/api/v1/portals/articles/article_header", article: @article %> <%= render "public/api/v1/portals/articles/article_header", article: @article %>
</div> </div>
</div> </div>
</div> </div>
<% else %> <% else %>
<div class="max-w-6xl p-8 mx-auto space-y-4 w-full <%= @is_plain_layout_enabled ? 'px-8 py-4' : 'p-8' %>"> <div class="max-w-5xl mx-auto space-y-4 w-full px-4 md:px-8 <%= @is_plain_layout_enabled ? 'py-4' : 'py-8' %>">
<%= render "public/api/v1/portals/articles/article_header", article: @article %> <%= render "public/api/v1/portals/articles/article_header", article: @article %>
</div> </div>
<% end %> <% end %>
<div class="flex max-w-6xl w-full px-8 mx-auto"> <div class="flex max-w-5xl w-full px-4 md:px-8 mx-auto">
<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' %>"> <article id="cw-article-content" class="article-content flex-grow flex-2 mx-auto text-slate-800 dark:text-slate-50 text-lg max-w-3xl prose-h1:text-2xl prose-h2:text-xl prose-h2:mt-0 prose-h3:text-lg prose-code:[&>p]:p-1 prose-code:[&>p]:rounded-sm prose-code:[&>p]:bg-black-100 dark:prose-code:[&>p]:bg-black-600 prose-code:after:content-none prose-code:before:content-none prose dark:prose-invert break-words w-full <%= @is_plain_layout_enabled ? 'py-4' : 'pt-8 pb-12' %>">
<%= @parsed_content %> <%= @parsed_content %>
</article> </article>
<div class="flex-1" id="cw-hc-toc"></div> <div class="flex-1" id="cw-hc-toc"></div>
</div> </div>
<style>
.article-content li > p {
margin: 0;
}
</style>

View File

@@ -1,4 +1,4 @@
<div class="flex flex-col px-8 max-w-5xl w-full mx-auto gap-6 <%= @is_plain_layout_enabled && 'py-4' %>"> <div class="flex flex-col px-4 md:px-8 max-w-5xl w-full mx-auto gap-6 <%= @is_plain_layout_enabled && 'py-4' %>">
<div class="flex items-center flex-row"> <div class="flex items-center flex-row">
<a <a
class="text-slate-500 dark:text-slate-200 text-sm gap-1 <%= @is_plain_layout_enabled && 'hover:underline' %> hover:cursor-pointer leading-8 font-semibold" class="text-slate-500 dark:text-slate-200 text-sm gap-1 <%= @is_plain_layout_enabled && 'hover:underline' %> hover:cursor-pointer leading-8 font-semibold"

View File

@@ -1,6 +1,6 @@
<%= render "hero", portal: @portal %> <%= render "hero", portal: @portal %>
<div class="max-w-6xl w-full flex-grow mx-auto py-16"> <div class="max-w-5xl w-full flex-grow mx-auto py-16">
<div class="grid grid-cols-2 gap-x-32 gap-y-12"> <div class="grid grid-cols-2 gap-x-32 gap-y-12">
<% @categories.each do |category| %> <% @categories.each do |category| %>
<%= render "category-block", category: category, portal: @portal %> <%= render "category-block", category: category, portal: @portal %>

View File

@@ -14,7 +14,7 @@
<% else %> <% else %>
<%= render 'public/api/v1/portals/categories/category-hero', category: @category, portal: @portal %> <%= render 'public/api/v1/portals/categories/category-hero', category: @category, portal: @portal %>
<% end %> <% end %>
<section class="max-w-5xl w-full mx-auto px-8 py-6 flex flex-col items-center justify-center flex-grow"> <section class="max-w-5xl w-full mx-auto px-4 md:px-8 py-6 flex flex-col items-center justify-center flex-grow">
<div class="w-full flex flex-col gap-6 flex-grow"> <div class="w-full flex flex-col gap-6 flex-grow">
<% if @category.articles.published.size == 0 %> <% if @category.articles.published.size == 0 %>
<div class="h-full flex items-center justify-center bg-slate-50 dark:bg-slate-800 rounded-xl py-6"> <div class="h-full flex items-center justify-center bg-slate-50 dark:bg-slate-800 rounded-xl py-6">

View File

@@ -1,5 +1,5 @@
<%= render "public/api/v1/portals/hero", portal: @portal %> <%= render "public/api/v1/portals/hero", portal: @portal %>
<div class="max-w-5xl w-full flex flex-col flex-grow mx-auto py-8 px-8 gap-6"> <div class="max-w-5xl w-full flex flex-col flex-grow mx-auto py-8 px-4 md:px-8 gap-6">
<%# Featured Articles %> <%# Featured Articles %>
<% if !@is_plain_layout_enabled %> <% if !@is_plain_layout_enabled %>
<div><%= render "public/api/v1/portals/featured_articles", articles: @portal.articles, categories: @portal.categories.where(locale: @locale), portal: @portal %></div> <div><%= render "public/api/v1/portals/featured_articles", articles: @portal.articles, categories: @portal.categories.where(locale: @locale), portal: @portal %></div>

View File

@@ -225,6 +225,7 @@ en:
light: Light light: Light
dark: Dark dark: Dark
featured_articles: Featured Articles featured_articles: Featured Articles
uncategorized: Uncategorized
404: 404:
title: Page not found title: Page not found
description: We couldn't find the page you were looking for. description: We couldn't find the page you were looking for.

View File

@@ -119,7 +119,7 @@ describe PortalHelper do
end end
end end
end end
describe '#render_category_content' do describe '#render_category_content' do
let(:markdown_content) { 'This is a *test* markdown content' } let(:markdown_content) { 'This is a *test* markdown content' }
let(:plain_text_content) { 'This is a test markdown content' } let(:plain_text_content) { 'This is a test markdown content' }