diff --git a/app/assets/images/icons/panel-left.svg b/app/assets/images/icons/panel-left.svg new file mode 100644 index 0000000000..c89675c6a8 --- /dev/null +++ b/app/assets/images/icons/panel-left.svg @@ -0,0 +1,4 @@ + diff --git a/app/assets/stylesheets/custom_styles/layout.css b/app/assets/stylesheets/custom_styles/layout.css index 9f32dfe445..9c1d5001e6 100644 --- a/app/assets/stylesheets/custom_styles/layout.css +++ b/app/assets/stylesheets/custom_styles/layout.css @@ -2,8 +2,40 @@ @apply max-w-7xl mx-auto py-10 px-4 sm:py-14 sm:px-6 lg:px-8; } +html:has([data-controller~="lessons--sidebar-toggle"]) { + scroll-padding-top: 3.5rem; +} + @utility highlight-white { @layer utilities { box-shadow: inset 0 1px 0 0 hsl(0deg 0% 100% / 5%); } } + +@utility scrollbar-thin { + scrollbar-width: thin; + scrollbar-color: var(--color-gray-300) transparent; + scrollbar-gutter: stable; + + &::-webkit-scrollbar { + width: 6px; + height: 6px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background-color: var(--color-gray-300); + border-radius: 9999px; + } + + .dark & { + scrollbar-color: var(--color-gray-700) transparent; + } + + .dark &::-webkit-scrollbar-thumb { + background-color: var(--color-gray-700); + } +} diff --git a/app/components/lessons/sidebar/completion_icon_component.html.erb b/app/components/lessons/sidebar/completion_icon_component.html.erb new file mode 100644 index 0000000000..092a4877ae --- /dev/null +++ b/app/components/lessons/sidebar/completion_icon_component.html.erb @@ -0,0 +1,7 @@ +<%= inline_svg_tag( + 'icons/checkmark-circle-solid.svg', + class: "sidebar-completion-icon-#{lesson.id} h-5 w-5 shrink-0 #{color_class}", + aria: true, + title: title, + data: { test_id: 'lesson-sidebar-completion' } + ) %> diff --git a/app/components/lessons/sidebar/completion_icon_component.rb b/app/components/lessons/sidebar/completion_icon_component.rb new file mode 100644 index 0000000000..d93f163226 --- /dev/null +++ b/app/components/lessons/sidebar/completion_icon_component.rb @@ -0,0 +1,21 @@ +module Lessons + module Sidebar + class CompletionIconComponent < ApplicationComponent + def initialize(lesson:) + @lesson = lesson + end + + private + + attr_reader :lesson + + def color_class + lesson.completed? ? 'text-teal-600' : 'text-gray-300 dark:text-gray-700' + end + + def title + lesson.completed? ? 'Lesson completed' : 'Lesson not completed' + end + end + end +end diff --git a/app/components/lessons/sidebar/lesson_component.html.erb b/app/components/lessons/sidebar/lesson_component.html.erb new file mode 100644 index 0000000000..c6f4482063 --- /dev/null +++ b/app/components/lessons/sidebar/lesson_component.html.erb @@ -0,0 +1,15 @@ +<%= link_to( + lesson_path(lesson), + class: 'flex items-center justify-between gap-2 px-2 py-1.5 rounded-md no-underline text-sm text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 hover:text-gray-900 dark:hover:text-gray-200 aria-[current=page]:bg-gray-100 dark:aria-[current=page]:bg-gray-800 aria-[current=page]:font-semibold aria-[current=page]:text-gray-900 dark:aria-[current=page]:text-gray-100', + aria: { current: ('page' if current?) }, + data: { test_id: 'lesson-sidebar-link', 'lessons--sidebar-toggle-target': 'item' } + ) do %> + + <%= inline_svg_tag "icons/#{icon_name}.svg", class: 'h-4 w-4 shrink-0 text-gray-400 dark:text-gray-500' %> + <%= lesson.display_title %> + + + <% if current_user %> + <%= render Lessons::Sidebar::CompletionIconComponent.new(lesson:) %> + <% end %> +<% end %> diff --git a/app/components/lessons/sidebar/lesson_component.rb b/app/components/lessons/sidebar/lesson_component.rb new file mode 100644 index 0000000000..4def10cc0e --- /dev/null +++ b/app/components/lessons/sidebar/lesson_component.rb @@ -0,0 +1,23 @@ +module Lessons + module Sidebar + class LessonComponent < ApplicationComponent + def initialize(lesson:, current_lesson:, current_user: nil) + @lesson = lesson + @current_lesson = current_lesson + @current_user = current_user + end + + private + + attr_reader :lesson, :current_lesson, :current_user + + def current? + lesson.id == current_lesson.id + end + + def icon_name + lesson.is_project? ? 'wrench-screwdriver' : 'book' + end + end + end +end diff --git a/app/components/lessons/sidebar/progress_bar_component.html.erb b/app/components/lessons/sidebar/progress_bar_component.html.erb new file mode 100644 index 0000000000..459143b9e2 --- /dev/null +++ b/app/components/lessons/sidebar/progress_bar_component.html.erb @@ -0,0 +1,16 @@ +
diff --git a/app/components/lessons/sidebar/progress_bar_component.rb b/app/components/lessons/sidebar/progress_bar_component.rb new file mode 100644 index 0000000000..dd8821f0fb --- /dev/null +++ b/app/components/lessons/sidebar/progress_bar_component.rb @@ -0,0 +1,13 @@ +module Lessons + module Sidebar + class ProgressBarComponent < ApplicationComponent + def initialize(percentage:) + @percentage = percentage + end + + private + + attr_reader :percentage + end + end +end diff --git a/app/components/lessons/sidebar/section_component.html.erb b/app/components/lessons/sidebar/section_component.html.erb new file mode 100644 index 0000000000..06f6c62e67 --- /dev/null +++ b/app/components/lessons/sidebar/section_component.html.erb @@ -0,0 +1,14 @@ +