Skip to content

Commit

Permalink
Feature: Add progress pages component (#328)
Browse files Browse the repository at this point in the history
* add progress pages component

* put again the type argument for button component

* fix progress pages item not center if test is long

* make progress pages container take full width by default

* Fix progress item position (first & last one) to be aligned with the content

* fix progress item checked state to show the icon and the good background

* make the progress page component preview width bigger

---------

Co-authored-by: Bilel Kihal <[email protected]>
  • Loading branch information
syphax-bouazzouni and Bilelkihal authored Aug 22, 2023
1 parent fdf4fed commit 1bc089a
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 2 deletions.
4 changes: 4 additions & 0 deletions app/assets/images/icons/arrow-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions app/assets/images/icons/white-check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/stylesheets/bioportal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,9 @@ a.truncated_less, a.truncated_more {
.highlighted .search_ontology_acronym {
color: white;
}
.hide {
display: none !important;
}

.empty-state {
display: none;
Expand Down
3 changes: 2 additions & 1 deletion app/assets/stylesheets/components/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
@import "concept_details";
@import "card";
@import "header";
@import "image";
@import "image";
@import "progress_pages";
118 changes: 118 additions & 0 deletions app/assets/stylesheets/components/progress_pages.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
.progress-pages-container {
display: flex;
align-items: center;
margin-top: 20px;
margin-bottom: 50px;
width: 100%;
}

.progress-pages-container hr {
flex-grow: 1;
border: 1px solid #D9D9D9;
margin: 0;
}

.progress-pages-container hr.active {
border: 1px solid var(--primary-color);
}

.progress-pages-container .progress-item {
position: relative;
& > div {
position: absolute;
top: -13px;
left: -13px;
display: flex;
flex-direction: column;
align-items: center;
}
}

.progress-pages-container .progress-item:first-of-type {
& > div {
align-items: start;
left: 0;
}
}

.progress-pages-container .progress-item:last-of-type {
& > div {
align-items: end;
left: -23px;
}
}

.progress-pages-container .progress-item div .active:nth-child(2) {
color: var(--primary-color);
font-weight: 600;
}

.progress-pages-container .progress-item div span:nth-child(2) {
position: absolute;
font-size: 12px;
top: 33px;
white-space: nowrap;
color: #A9A9A9;
}

.progress-pages-container .progress-content .active:nth-child(2) {
color: var(--primary-color);
font-weight: 600;
}

.progress-pages-container .progress-content div:nth-child(2) {
position: absolute;
right: -38px;
top: 33px;

}



.outlined-checked-circle {
border: 2px solid var(--primary-color) !important;
background-color: var(--primary-color) !important;
display: flex;
align-items: center;
justify-content: center;
}

.outlined-active-circle {
border: 2px solid var(--primary-color) !important;
}

.outlined-circle {
border: 1px solid #D9D9D9;
border-radius: 13px;
height: 26px;
width: 26px;
background-color: white;

}

.outlined-checked-circle img {
display: block !important;
}

.outlined-active-circle img {
display: none;
}

.outlined-circle img {
display: none;
}



.progress-pages-actions {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}

.progress-pages-next-button {
margin-left: 25px;
}



10 changes: 10 additions & 0 deletions app/components/layout/progress_pages_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

class Layout::ProgressPagesComponent < ViewComponent::Base

renders_many :pages
def initialize(pages_title: [])
super
@pages_title = pages_title
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
%div.w-100{'data-controller': 'progress-pages'}
%div
.d-flex.justify-content-center.flex-column
.progress-pages-container
- @pages_title.each_with_index do |key, index|
.progress-item{'data-progress-pages-target': 'pageItem'}
%div
.outlined-circle{class: index.zero? ? 'outlined-active-circle' : ''}
= image_tag("icons/white-check.svg")
%span{class: index.zero? ? 'active' : ''}
= key.humanize
- if index < (@pages_title.size-1)
%hr.line
%div
- pages.each_with_index do |page, index|
%div.progress-content{{'data-progress-pages-target': 'pageContent'}, class: index.zero? ? '' : 'hide'}
= page


.progress-pages-actions
.progress-pages-back-button.hide{'data-action': "click->progress-pages#navigateBack", 'data-progress-pages-target': 'backBtn'}
= render Buttons::RegularButtonComponent.new(id: 'progress-pages-back-button', value: "Back", variant: "secondary", size: 'slim',state: 'regular') do |btn|
- btn.icon_left do
= inline_svg "icons/arrow-left.svg"
.progress-pages-next-button{'data-action': "click->progress-pages#navigateNext", 'data-progress-pages-target': 'nextBtn'}
= render Buttons::RegularButtonComponent.new(id: 'progress-pages-next-button', value: "Next", size: 'slim', state: 'regular') do |btn|
- btn.icon_right do
= inline_svg "arrow-right.svg"
.progress-pages-next-button.hide{ 'data-progress-pages-target': 'finishBtn'}
= render Buttons::RegularButtonComponent.new(id: 'progress-pages-finish-button', value: "Finish", size: 'slim', type: 'submit') do |btn|
- btn.icon_right do
= inline_svg "icons/white-check.svg"
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {Controller} from "@hotwired/stimulus";

export default class extends Controller {
static targets = ['pageItem','pageContent' ,'backBtn', 'nextBtn', 'finishBtn']
connect() {
this.pagesItems = this.pageItemTargets
this.buttons = [this.backBtnTarget, this.nextBtnTarget, this.finishBtnTarget]
this.currentForm = 1
}

navigateBack(){
this.navigateForm('back')
}
navigateNext(){
this.navigateForm('next')
}

navigateForm(direction) {
if (direction === "next" && this.currentForm < this.pagesItems.length) {
this.currentForm += 1
this.showForm()
} else if (direction === "back" && this.currentForm > 1){
this.currentForm -= 1
this.showForm()
}
}

showForm(){
const targetForm = this.currentForm
for (let index = 1; index <= this.pagesItems.length; index++) {

const targetFormDOM = this.pageContentTargets[index - 1];

const isCurrentForm = targetForm === index;

targetFormDOM.classList.toggle("hide", !isCurrentForm);

if (isCurrentForm) {
this.updateProgressBar(targetForm);
this.updateButtons(targetForm);
}

}

}
updateProgressBar(targetForm) {
const progressItemsDOM = document.querySelectorAll(".progress-item > div");
const line = document.querySelectorAll(".line");

progressItemsDOM.forEach((item, index) => {
const isPassedSection = index + 1 < targetForm;
const isCurrentSection = index + 1 === targetForm;

item.children[0].classList.toggle("outlined-checked-circle", isPassedSection);
item.children[0].classList.toggle("outlined-active-circle", isCurrentSection);


item.children[1].classList.toggle("active", isCurrentSection || isPassedSection);


line[index]?.classList.toggle("active", isPassedSection);
});
}

updateButtons(targetForm) {

switch (targetForm) {
case 1:
this.showBtn([this.buttons[1]]);
break;
case this.pagesItems.length:
this.showBtn([this.buttons[0], this.buttons[2]]);
break;
default:
this.showBtn([this.buttons[0], this.buttons[1]]);
}

}

showBtn(btnIds = []) {
this.buttons.forEach((btn) => {
const targetBtnDOM = btn;
const shouldShowBtn = btnIds.includes(btn);
targetBtnDOM.classList.toggle("hide", !shouldShowBtn);
});
}
}
4 changes: 3 additions & 1 deletion app/javascript/component_controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import Search_input_component_controller
import CircleProgressBarComponentController from "../../components/circle_progress_bar_component/circle_progress_bar_component_controller"
import Tabs_container_component_controller
from "../../components/tabs_container_component/tabs_container_component_controller";

import Progress_pages_component_controller
from "../../components/layout/progress_pages_component/progress_pages_component_controller";

application.register("turbo-modal", TurboModalController)
application.register("file-input", FileInputLoaderController)
Expand All @@ -25,3 +26,4 @@ application.register("subscribe-notes", Ontology_subscribe_button_component_cont
application.register("search-input", Search_input_component_controller)
application.register("tabs-container", Tabs_container_component_controller)
application.register("circle-progress-bar", CircleProgressBarComponentController)
application.register("progress-pages", Progress_pages_component_controller)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class Layout::ProgressPagesComponentPreview < ViewComponent::Preview

# @param pages_count number
def default(pages_count: 5)
render Layout::ProgressPagesComponent.new(pages_title: (pages_count || 0).times.map { |x| "page #{x}" }) do |c|
5.times.each { |i| c.page { content_tag(:div, "page #{i}", class: "p-5 mx-5 text-center", style: 'width: 500px') } }
end
end
end

0 comments on commit 1bc089a

Please sign in to comment.