Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stage 2 experiment: Show Language Guide Before Solution #2574

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,61 +11,123 @@
{{/unless}}
</div>

{{#if this.solution}}
<BlurredOverlay
class="mb-3 group"
@isBlurred={{this.solutionIsBlurred}}
@overlayClass="inset-px rounded cursor-pointer group-hover:backdrop-blur-[3px] group-hover:bg-gray-50/20 dark:bg-gray-900/20 dark:group-hover:bg-gray-900/0"
>
<:content>
<div class="grid gap-3 mb-3">
{{#each this.solution.changedFiles as |changedFile|}}
{{! Extra if condition convinces typescript that solution isn't null }}
{{#if this.solution}}
<FileDiffCard
@filename={{changedFile.filename}}
@code={{changedFile.diff}}
@language={{this.solution.language.slug}}
data-test-file-diff-card
/>
{{/if}}
{{/each}}
</div>
{{#if this.canSeeLanguageGuideBeforeSolution}}
{{#if @languageGuide}}
<div
class="prose dark:prose-invert has-prism-highlighting mt-4"
{{highlight-code-blocks @languageGuide.markdownForBeginner}}
data-test-language-guide-card
>
{{markdown-to-html @languageGuide.markdownForBeginner}}
</div>
{{/if}}

{{#unless this.solutionIsBlurred}}
<TertiaryButton
class="w-full mb-6 flex justify-center items-center gap-2 dark:bg-transparent dark:text-gray-200 dark:border-white/5 dark:hover:border-gray-700/60 dark:bg-gray-800 dark:hover:bg-gray-700/50"
{{on "click" this.handleHideSolutionButtonClick}}
data-test-hide-solution-button
>
{{svg-jar "eye-off" class="size-4"}}
Hide Solution
</TertiaryButton>
{{#if this.solution}}
<BlurredOverlay
class="mb-3 group"
@isBlurred={{this.solutionIsBlurred}}
@overlayClass="inset-px rounded cursor-pointer group-hover:backdrop-blur-[3px] group-hover:bg-gray-50/20 dark:bg-gray-900/20 dark:group-hover:bg-gray-900/0"
>
<:content>
<div class="grid gap-3 mt-6 mb-3">

{{#each this.solution.changedFiles as |changedFile|}}
{{! Extra if condition convinces typescript that solution isn't null }}
{{#if this.solution}}
<FileDiffCard
@filename={{changedFile.filename}}
@code={{changedFile.diff}}
@language={{this.solution.language.slug}}
data-test-file-diff-card
/>
{{/if}}
{{/each}}
</div>

{{#if @languageGuide}}
<div
class="prose dark:prose-invert has-prism-highlighting"
{{highlight-code-blocks @languageGuide.markdownForBeginner}}
data-test-language-guide-card
{{#unless this.solutionIsBlurred}}
<TertiaryButton
class="w-full mb-6 flex justify-center items-center gap-2 dark:bg-transparent dark:text-gray-200 dark:border-white/5 dark:hover:border-gray-700/60 dark:bg-gray-800 dark:hover:bg-gray-700/50"
{{on "click" this.handleHideSolutionButtonClick}}
data-test-hide-solution-button
>
{{markdown-to-html @languageGuide.markdownForBeginner}}
</div>
{{/if}}
{{/unless}}
</:content>
{{svg-jar "eye-off" class="size-4"}}
Hide Solution
</TertiaryButton>
{{/unless}}
</:content>

<:overlay>
<SecondaryButton
class="self-center bg-white group-hover:bg-teal-50 dark:bg-gray-900 dark:group-hover:bg-gray-900/80 backdrop-blur-3xl group-hover:text-teal-600 dark:group-hover:text-teal-400 group-hover:border-teal-600 dark:group-hover:border-teal-400"
data-test-reveal-solution-button
>
<div class="flex items-center gap-2">
{{svg-jar "eye" class="size-6"}}
<span>Click to reveal solution</span>
<:overlay>
<SecondaryButton
class="self-center bg-white group-hover:bg-teal-50 dark:bg-gray-900 dark:group-hover:bg-gray-900/80 backdrop-blur-3xl group-hover:text-teal-600 dark:group-hover:text-teal-400 group-hover:border-teal-600 dark:group-hover:border-teal-400"
data-test-reveal-solution-button
>
<div class="flex items-center gap-2">
{{svg-jar "eye" class="size-6"}}
<span>Click to reveal solution</span>
</div>
</SecondaryButton>
<button class="absolute inset-0" type="button" {{on "click" this.handleRevealSolutionButtonClick}} data-test-solution-blurred-overlay>
</button>
Comment on lines +69 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve accessibility of the solution reveal button.

The button element lacks proper accessibility attributes:

  • Missing aria-label
  • Missing role attribute
  • Empty button content

Apply this diff to improve accessibility:

-<button class="absolute inset-0" type="button" {{on "click" this.handleRevealSolutionButtonClick}} data-test-solution-blurred-overlay>
+<button 
+  class="absolute inset-0" 
+  type="button" 
+  aria-label="Reveal solution"
+  role="button"
+  {{on "click" this.handleRevealSolutionButtonClick}} 
+  data-test-solution-blurred-overlay
+>
+  <span class="sr-only">Reveal solution</span>
</button>

Also applies to: 128-129

</:overlay>
</BlurredOverlay>
{{/if}}
{{else}}
{{#if this.solution}}
<BlurredOverlay
class="mb-3 group"
@isBlurred={{this.solutionIsBlurred}}
@overlayClass="inset-px rounded cursor-pointer group-hover:backdrop-blur-[3px] group-hover:bg-gray-50/20 dark:bg-gray-900/20 dark:group-hover:bg-gray-900/0"
>
<:content>
<div class="grid gap-3 mb-3">
{{#each this.solution.changedFiles as |changedFile|}}
{{! Extra if condition convinces typescript that solution isn't null }}
{{#if this.solution}}
<FileDiffCard
@filename={{changedFile.filename}}
@code={{changedFile.diff}}
@language={{this.solution.language.slug}}
data-test-file-diff-card
/>
{{/if}}
{{/each}}
</div>
</SecondaryButton>
<button class="absolute inset-0" type="button" {{on "click" this.handleRevealSolutionButtonClick}} data-test-solution-blurred-overlay>
</button>
</:overlay>
</BlurredOverlay>

{{#unless this.solutionIsBlurred}}
<TertiaryButton
class="w-full mb-6 flex justify-center items-center gap-2 dark:bg-transparent dark:text-gray-200 dark:border-white/5 dark:hover:border-gray-700/60 dark:bg-gray-800 dark:hover:bg-gray-700/50"
{{on "click" this.handleHideSolutionButtonClick}}
data-test-hide-solution-button
>
{{svg-jar "eye-off" class="size-4"}}
Hide Solution
</TertiaryButton>

{{#if @languageGuide}}
<div
class="prose dark:prose-invert has-prism-highlighting"
{{highlight-code-blocks @languageGuide.markdownForBeginner}}
data-test-language-guide-card
>
{{markdown-to-html @languageGuide.markdownForBeginner}}
</div>
{{/if}}
{{/unless}}
</:content>

<:overlay>
<SecondaryButton
class="self-center bg-white group-hover:bg-teal-50 dark:bg-gray-900 dark:group-hover:bg-gray-900/80 backdrop-blur-3xl group-hover:text-teal-600 dark:group-hover:text-teal-400 group-hover:border-teal-600 dark:group-hover:border-teal-400"
data-test-reveal-solution-button
>
<div class="flex items-center gap-2">
{{svg-jar "eye" class="size-6"}}
<span>Click to reveal solution</span>
</div>
</SecondaryButton>
<button class="absolute inset-0" type="button" {{on "click" this.handleRevealSolutionButtonClick}} data-test-solution-blurred-overlay>
</button>
</:overlay>
</BlurredOverlay>
{{/if}}
{{/if}}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import Component from '@glimmer/component';
import type RepositoryModel from 'codecrafters-frontend/models/repository';
import type CourseStageModel from 'codecrafters-frontend/models/course-stage';
import type CourseStageLanguageGuideModel from 'codecrafters-frontend/models/course-stage-language-guide';
import type FeatureFlagsService from 'codecrafters-frontend/services/feature-flags';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';

interface Signature {
Expand All @@ -17,8 +19,13 @@ interface Signature {
}

export default class ImplementSolutionStepComponent extends Component<Signature> {
@service declare featureFlags: FeatureFlagsService;
@tracked solutionIsBlurred = true;

get canSeeLanguageGuideBeforeSolution() {
return this.featureFlags.canSeeLanguageGuideBeforeSolutionForStage2;
}

get solution() {
return this.args.repository.secondStageSolution;
}
Expand Down
4 changes: 4 additions & 0 deletions app/services/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export default class FeatureFlagsService extends Service {
return Boolean(this.currentUser && (this.currentUser.isStaff || this.currentUser.isConceptAuthor));
}

get canSeeLanguageGuideBeforeSolutionForStage2(): boolean {
return Boolean(this.currentUser?.isStaff || this.getFeatureFlagValue('can-see-language-guide-before-solution-for-stage-2') === 'test');
}

get canSeeSplitUpGitCommandsForStage1(): boolean {
return Boolean(this.currentUser?.isStaff || this.getFeatureFlagValue('can-see-split-up-git-commands-for-stage-1') === 'test');
}
Expand Down