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

Modify preview-card styles #88

Merged
merged 6 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
19 changes: 18 additions & 1 deletion src/components/Exercise.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import { Answer } from '../types';
import { IncludeRemoveQuestion } from './IncludeRemoveQuestion';
import styled from 'styled-components';
import { ExercisePreview } from './ExercisePreview';

const exerciseWithStepDataProps: ExerciseWithStepDataProps = {
exercise: {
Expand Down Expand Up @@ -103,7 +104,7 @@ const exerciseWithQuestionStatesProps = (): ExerciseWithQuestionStatesProps => {
is_answer_order_important: false,
answers: [{
id: '1',
correctness: undefined,
correctness: '1.0',
Copy link
Member

Choose a reason for hiding this comment

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

Does this break any of the other stories? Seems alright, I just can't remember why it was undefined originally

Copy link
Author

Choose a reason for hiding this comment

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

This marks a question as correct, I can keep it as undefined and create a new variable just for new stories

content_html: 'True',
}, {
id: '2',
Expand Down Expand Up @@ -948,10 +949,26 @@ export const OverlayCard = () => {
},
};

const [selectedQuestions, setSelectedQuestions] = useState<string[]>([]);

return (
<TextResizerProvider>
<h2>Exercise cards</h2>
<Exercise {...props1} className='preview-card' />
<Exercise {...props2} className='preview-card' />
<h2>Exercise Preview cards</h2>
<ExercisePreview
selectedQuestions={selectedQuestions}
setSelectedQuestions={setSelectedQuestions}
enableOverlay
exercise={props1.exercise}
/>
<ExercisePreview
selectedQuestions={selectedQuestions}
setSelectedQuestions={setSelectedQuestions}
enableOverlay
exercise={props2.exercise}
/>
</TextResizerProvider>
);
};
36 changes: 34 additions & 2 deletions src/components/Exercise/styles.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import { css } from "styled-components";

export const exerciseStyles = css`

&.included-card {
background-color: #daf3f8;

.step-card-footer-inner,
.step-card-body,
.step-card-header,
.answer-letter-wrapper::before {
background-color: #daf3f8 !important;
}
}

&.preview-card {
--spacing: 0.8rem;

.step-card-header,
.step-card-body {
background-color: #FFFFFF;
padding: var(--spacing);
font-size: 1.6rem;
line-height: 2rem;
Expand Down Expand Up @@ -44,6 +57,7 @@ export const exerciseStyles = css`
.openstax-question {
.openstax-answer {
padding: 0;
border: none;

.answer-label {
padding-top: var(--spacing);
Expand Down Expand Up @@ -74,13 +88,31 @@ export const exerciseStyles = css`
}
}

.step-card-footer {
.step-card-footer, .detailed-solution {
display: none;
}

.question-stem,
.question-feedback-content {
.question-feedback-content,
.question-info,
.exercise-context {
line-height: 2rem;
}

.question-info {
font-weight: bold;
font-size: 1.6rem;
Copy link
Member

Choose a reason for hiding this comment

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

Does this match Figma? I think Figma might be slightly smaller. Also I'm not sure when that other PR will get merged, so maybe we do include the fix you made last week for the broken separator :D

Copy link
Author

@jomcarvajal jomcarvajal Jan 29, 2025

Choose a reason for hiding this comment

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

You're right, it should be 1.2rem

}

.question-id {
font-weight: 400;
font-size: 1.6rem;
}

.question-stem {
color: #424242;
font-weight: bold;
font-size: 1.6rem;
}
}
`;
65 changes: 65 additions & 0 deletions src/components/ExercisePreview.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { ExercisePreview } from './ExercisePreview';
import renderer from 'react-test-renderer';
import { ExerciseData } from 'src/types';

describe('ExercisePreview', () => {
describe('using step data', () => {

let exercise: ExerciseData;

beforeEach(() => {
exercise = {
uid: '1@1',
Copy link
Member

Choose a reason for hiding this comment

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

I think these are indented 4 but we use 2 in this repo (and most of the repos)

uuid: 'e4e27897-4abc-40d3-8565-5def31795edc',
group_uuid: '20e82bf6-232e-40c8-ba68-2d22c6498f69',
number: 1,
version: 1,
published_at: '2022-09-06T20:32:21.981Z',
context: 'Context',
stimulus_html: '<b>Stimulus HTML</b>',
tags: [],
authors: [{ user_id: 1, name: 'OpenStax' }],
copyright_holders: [{ user_id: 1, name: 'OpenStax' }],
derived_from: [],
is_vocab: false,
solutions_are_public: false,
versions: [1],
questions: [{
id: '1234@5',
collaborator_solutions: [],
formats: ['true-false'],
stimulus_html: '',
stem_html: '',
is_answer_order_important: false,
answers: [{
id: '1',
correctness: undefined,
content_html: 'True',
}, {
id: '2',
correctness: undefined,
content_html: 'False',
}],
}],
};
});

it.each`
enableOverlay | description
${true} | ${'with overlay'}
${false} | ${'without overlay'}
`('matches snapshot %description', ({ enableOverlay }: { enableOverlay: boolean }) => {
const selectedQuestionsMock: string[] = [];
const setQuestionsmock = jest.fn();
const tree = renderer.create(
<ExercisePreview
exercise={exercise}
enableOverlay={enableOverlay}
selectedQuestions={selectedQuestionsMock}
setSelectedQuestions={setQuestionsmock}
/>
).toJSON();
expect(tree).toMatchSnapshot();
});
});
});
98 changes: 98 additions & 0 deletions src/components/ExercisePreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { useCallback } from "react";
import { ExerciseData, ExerciseQuestionData, StepBase } from "src/types";
import { IncludeRemoveQuestion } from "./IncludeRemoveQuestion";
import { Exercise } from "./Exercise";

export interface ExercisePreviewProps {
exercise: ExerciseData;
selectedQuestions: string[];
setSelectedQuestions?: React.Dispatch<React.SetStateAction<string[]>>;
enableOverlay?: boolean;
}

/**
* An Exercise version with less interaction with card and grants an Overlay with Include/Remove component
*/
export const ExercisePreview = (
Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer this to take selected and onSelectionChange props, that keeps it flexible on the consuming side

{
exercise,
selectedQuestions,
setSelectedQuestions,
enableOverlay = false,
}: ExercisePreviewProps) => {

const exercisePreviewProps = (exercise: ExerciseData) => {
const formatAnswerData = (questions: ExerciseQuestionData[]) => questions.map((q) => (
{ id: q.id, correct_answer_id: (q.answers.find((a) => a.correctness === '1.0')?.id || '') }));

const questionStateFields = {
available_points: '1.0',
is_completed: true,
answer_id: '1',
free_response: '',
feedback_html: '',
correct_answer_feedback_html: '',
attempts_remaining: 0,
attempt_number: 1,
incorrectAnswerId: 0
}

const questionStates = formatAnswerData(exercise.questions).reduce((acc, answer) => {
const { id, correct_answer_id } = answer;
return { ...acc, [id]: { ...questionStateFields, correct_answer_id } };
}, {});

const step: StepBase = {
id: 1,
uid: exercise.uid,
available_points: '1.0',
};

return {
canAnswer: true,
needsSaved: true,
hasMultipleAttempts: false,
onAnswerChange: () => undefined,
onAnswerSave: () => undefined,
onNextStep: () => undefined,
apiIsPending: false,
canUpdateCurrentStep: false,
step: step,
questionNumber: exercise.number as number,
numberOfQuestions: exercise.questions.length,
questionStates: questionStates,
show_all_feedback: false, // Hide all feedback
};
};

const includeQuestionHandler = React.useCallback(() => {
setSelectedQuestions?.(previous => previous.concat(exercise.uid));
}, [exercise, setSelectedQuestions]);

const removeQuestionHandler = useCallback(() => {
setSelectedQuestions?.(previous => previous.filter((id) => id !== exercise.uid));
}, [exercise, setSelectedQuestions]);

const includeRemoveQuestionComponent = React.useMemo(() =>
<IncludeRemoveQuestion
buttonVariant={selectedQuestions.includes(exercise.uid) ? 'remove' : 'include'}
onIncludeHandler={includeQuestionHandler}
onRemoveHandler={removeQuestionHandler}
/>
, [selectedQuestions, exercise, includeQuestionHandler, removeQuestionHandler]);

return (
<Exercise
exercise={exercise}
className={selectedQuestions.includes(exercise.uid) ? 'preview-card included-card' : 'preview-card'}
{
...(enableOverlay
? {
overlayChildren: includeRemoveQuestionComponent,
}
: {})
}
{...exercisePreviewProps(exercise)}
/>
);
};
24 changes: 12 additions & 12 deletions src/components/__snapshots__/Exercise.spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ exports[`Exercise using step data matches snapshot 1`] = `
data-task-step-id={1}
>
<div
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl RyOjk"
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl cJxUgl"
>
<div>
<div
Expand Down Expand Up @@ -69,7 +69,7 @@ exports[`Exercise using step data matches snapshot 1`] = `
data-test-id="student-exercise-question"
>
<div
className="sc-iBkjds bohpoA openstax-question step-card-body"
className="sc-iBkjds lXypw openstax-question step-card-body"
data-question-number={1}
data-test-id="question"
>
Expand Down Expand Up @@ -206,7 +206,7 @@ exports[`Exercise with overlay rendering matches snapshot 1`] = `
data-task-step-id={1}
>
<div
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl RyOjk"
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl cJxUgl"
>
<div
onBlur={[Function]}
Expand Down Expand Up @@ -271,7 +271,7 @@ exports[`Exercise with overlay rendering matches snapshot 1`] = `
data-test-id="student-exercise-question"
>
<div
className="sc-iBkjds bohpoA openstax-question step-card-body"
className="sc-iBkjds lXypw openstax-question step-card-body"
data-question-number={1}
data-test-id="question"
>
Expand Down Expand Up @@ -408,7 +408,7 @@ exports[`Exercise with question state data matches snapshot 1`] = `
data-task-step-id={1}
>
<div
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl RyOjk"
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl cJxUgl"
>
<div>
<div
Expand Down Expand Up @@ -462,7 +462,7 @@ exports[`Exercise with question state data matches snapshot 1`] = `
data-test-id="student-exercise-question"
>
<div
className="sc-iBkjds bohpoA openstax-question step-card-body"
className="sc-iBkjds lXypw openstax-question step-card-body"
data-question-number={1}
data-test-id="question"
>
Expand Down Expand Up @@ -653,7 +653,7 @@ exports[`Exercise with question state data renders header icons with multiple ch
data-task-step-id={1}
>
<div
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl RyOjk"
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl cJxUgl"
>
<div>
<div
Expand Down Expand Up @@ -793,7 +793,7 @@ exports[`Exercise with question state data renders header icons with multiple ch
data-test-id="student-exercise-question"
>
<div
className="sc-iBkjds bohpoA openstax-question step-card-body"
className="sc-iBkjds lXypw openstax-question step-card-body"
data-question-number={1}
data-test-id="question"
>
Expand Down Expand Up @@ -984,7 +984,7 @@ exports[`Exercise with question state data renders header icons with two-step ex
data-task-step-id={1}
>
<div
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl RyOjk"
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl cJxUgl"
>
<div>
<div
Expand Down Expand Up @@ -1164,7 +1164,7 @@ exports[`Exercise with question state data renders header icons with two-step ex
data-test-id="student-exercise-question"
>
<div
className="sc-iBkjds bohpoA openstax-question step-card-body"
className="sc-iBkjds lXypw openstax-question step-card-body"
data-question-number={1}
data-test-id="question"
>
Expand Down Expand Up @@ -1301,7 +1301,7 @@ exports[`Exercise with question state data shows a detailed solution 1`] = `
data-task-step-id={1}
>
<div
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl RyOjk"
className="sc-bczRLJ eAXREJ exercise-step sc-breuTD dSaRVj sc-hAZoDl cJxUgl"
>
<div>
<div
Expand Down Expand Up @@ -1355,7 +1355,7 @@ exports[`Exercise with question state data shows a detailed solution 1`] = `
data-test-id="student-exercise-question"
>
<div
className="sc-iBkjds bohpoA openstax-question step-card-body"
className="sc-iBkjds lXypw openstax-question step-card-body"
data-question-number={1}
data-test-id="question"
>
Expand Down
Loading