From 92040797cc9cfd38599baafd2bce5aff51dc0f9f Mon Sep 17 00:00:00 2001 From: Josiah Ivey Date: Wed, 18 Sep 2024 14:25:16 -0700 Subject: [PATCH 1/4] resize content text inside exercise and completion status --- src/components/Answer.tsx | 2 +- src/components/Card.tsx | 2 +- src/components/CompletionStatus.tsx | 27 ++++++---- src/components/Exercise.stories.tsx | 78 +++++++++++++++++++++-------- src/components/Exercise.tsx | 21 +++++--- src/components/Question.tsx | 6 +-- src/components/StepCardFooter.tsx | 5 +- src/theme.ts | 2 +- 8 files changed, 97 insertions(+), 46 deletions(-) diff --git a/src/components/Answer.tsx b/src/components/Answer.tsx index d90dadd6..912ede1f 100644 --- a/src/components/Answer.tsx +++ b/src/components/Answer.tsx @@ -10,7 +10,7 @@ import { colors } from '../theme'; const StyledAnswerIndicator = styled.div<{ state: boolean }>` color: ${props => props.state ? colors.answer.correct : colors.answer.incorrect}; text-transform: uppercase; - font-size: 1.1rem; + font-size: calc(1.1rem * var(--content-text-scale)); font-weight: bold; `; diff --git a/src/components/Card.tsx b/src/components/Card.tsx index 6143a0b4..5fff8517 100644 --- a/src/components/Card.tsx +++ b/src/components/Card.tsx @@ -145,7 +145,7 @@ StepCardHeader.displayName = 'StepCardHeader'; const StepCardQuestion = styled.div<{ unpadded?: boolean }>` .step-card-body { ${mixins.stepCardPadding()} - + overflow: auto; background: ${colors.card.body.background}; &.exercise-stimulus { diff --git a/src/components/CompletionStatus.tsx b/src/components/CompletionStatus.tsx index 774fe84e..2a3efd46 100644 --- a/src/components/CompletionStatus.tsx +++ b/src/components/CompletionStatus.tsx @@ -1,7 +1,13 @@ -import styled from "styled-components"; +import styled, { createGlobalStyle } from "styled-components"; import { InnerStepCard } from "./Card"; import Button from "./Button"; +const GlobalStyle = createGlobalStyle` + :root { + --content-text-scale: 1; + } +`; + export interface CompletionStatusProps { numberOfQuestions: number; numberCompleted: number; @@ -10,8 +16,8 @@ export interface CompletionStatusProps { const CompletionStatusCard = styled(InnerStepCard)` padding: 88px 72px; - font-size: 1.8rem; - line-height: 3rem; + font-size: calc(1.8rem * var(--content-text-scale)); + line-height: calc(3rem * var(--content-text-scale)); display: block; button { @@ -25,27 +31,28 @@ const CompletionStatusCard = styled(InnerStepCard)` `; const CompletionHeader = styled.h2` - font-size: 2.4rem; + font-size: calc(2.4rem * var(--content-text-scale)); margin: 0; `; -export const CompletionStatus = ({ +export const CompletionStatus = styled(({ numberOfQuestions, numberCompleted, handleClick }: CompletionStatusProps) => { - + const allCompleted = numberOfQuestions === numberCompleted; const someCompleted = numberCompleted > 0; const buttonText = allCompleted ? 'Next' : ( someCompleted ? 'Continue' : 'Start' ); - return ( + return <> + {allCompleted ? 'You are done.' : (someCompleted ? 'Quiz is partially complete.' : 'No questions have been answered.')}

{allCompleted ? 'Great job answering all the questions.' : (someCompleted ? `You've completed ${numberCompleted} of ${numberOfQuestions} questions.` : 'Begin working on the quiz.')}

-
- ) -}; + +})``; diff --git a/src/components/Exercise.stories.tsx b/src/components/Exercise.stories.tsx index 29be734f..d1aeb865 100644 --- a/src/components/Exercise.stories.tsx +++ b/src/components/Exercise.stories.tsx @@ -1,6 +1,7 @@ -import { useState } from 'react'; +import React, { useState } from 'react'; import { Exercise, ExerciseWithStepDataProps, ExerciseWithQuestionStatesProps } from './Exercise'; import { Answer } from '../types'; +import styled from 'styled-components'; const exerciseWithStepDataProps: ExerciseWithStepDataProps = { exercise: { @@ -131,6 +132,38 @@ const exerciseWithQuestionStatesProps = (): ExerciseWithQuestionStatesProps => { }, }}; +type TextResizerValue = -2 | -1 | 0 | 1 | 2 | 3; +const textResizerScales = [0.75, 0.9, 1, 1.25, 1.5, 2]; +const textResizerValues: TextResizerValue[] = [-2, -1, 0, 1, 2, 3]; +const textResizerValueMap = new Map(textResizerValues.map((v, i) => [v, textResizerScales[i]])); + +const ExerciseWrapper = styled.div<{ textSize: TextResizerValue }>` + ${(props: { textSize: TextResizerValue }) => ` + --content-text-scale: ${textResizerValueMap.get(props.textSize)}; + `} +`; + +const TextResizerProvider = ({ children }: { children: React.ReactNode }) => { + const [index, setIndex] = useState(2); + + const increase = () => setIndex(Math.min(index + 1, textResizerValues.length - 1)); + const decrease = () => setIndex(Math.max(index - 1, 0)); + + return ( + +
+

Text Size

+ + + {textResizerScales[index]} + + +
+ {children} +
+ ); +}; + export const Default = () => { const [selectedAnswerId, setSelectedAnswerId] = useState(0); const [apiIsPending, setApiIsPending] = useState(false) @@ -144,7 +177,8 @@ export const Default = () => { setSelectedAnswerId(a.id) }} onAnswerSave={() => setApiIsPending(true)} - />) + /> + ) }; export const DeprecatedStepData = () => ; @@ -173,7 +207,7 @@ export const CompleteWithFeedback = () => { } }; - return ; + return ; }; export const IncorrectWithFeedbackAndSolution = () => { @@ -197,7 +231,7 @@ export const IncorrectWithFeedbackAndSolution = () => { apiIsPending: false } }; - return ; + return ; }; export const IncorrectWithFeedbackAndSolutionWrappingText = () => { @@ -223,7 +257,7 @@ export const IncorrectWithFeedbackAndSolutionWrappingText = () => { }; props.exercise.questions[0].answers[0].content_html = 'A very long correct answer to observe line wrapping at mobile sizes'; props.exercise.questions[0].answers[1].content_html = 'A very long incorrect answer to observe line wrapping at mobile sizes'; - return ; + return ; }; export const MultiPartHalfComplete = () => { @@ -325,7 +359,7 @@ export const MultiPartHalfComplete = () => { } }; - return ; + return ; }; export const Icons = () => { @@ -341,20 +375,20 @@ export const Icons = () => { }; return ; }; @@ -506,7 +540,7 @@ bitterness. The discriminant could perhaps a }; return ( - <> + & { id: number, question_id: number }) => { setSelectedAnswerId(a.id) @@ -516,6 +550,6 @@ bitterness. The discriminant could perhaps a }} /> - + ); }; diff --git a/src/components/Exercise.tsx b/src/components/Exercise.tsx index 0c4030e5..2df03322 100644 --- a/src/components/Exercise.tsx +++ b/src/components/Exercise.tsx @@ -1,6 +1,6 @@ import React from 'react'; import scrollToElement from 'scroll-to-element'; -import styled, { css } from 'styled-components'; +import styled, { createGlobalStyle, css } from 'styled-components'; import { Answer, ExerciseData, ID, QuestionState, StepBase, StepWithData } from '../../src/types'; import { InnerStepCard, OuterStepCard, TaskStepCard, TaskStepCardProps } from './Card'; import { Content } from './Content'; @@ -12,8 +12,14 @@ import { ExerciseHeaderIcons } from './ExerciseHeaderIcons'; import { TypesetMathContext } from '../hooks/useTypesetMath'; const StyledTaskStepCard = styled(TaskStepCard)` - font-size: 1.8rem; - line-height: 2.8rem; + font-size: calc(1.8rem * var(--content-text-scale)); + line-height: calc(2.8rem * var(--content-text-scale)); +`; + +const GlobalStyle = createGlobalStyle` + :root { + --content-text-scale: 1; + } `; const ToolbarWrapper = styled.div<{ @@ -151,9 +157,9 @@ export interface ExerciseWithQuestionStatesProps extends ExerciseBaseProps { onAnswerChange: (answer: Omit & { id: number, question_id: number }) => void; } -export const Exercise = ({ +export const Exercise = styled(({ numberOfQuestions, questionNumber, step, exercise, show_all_feedback, scrollToQuestion, exerciseIcons, ...props -}: ExerciseWithStepDataProps | ExerciseWithQuestionStatesProps) => { +}: { className?: string } & (ExerciseWithStepDataProps | ExerciseWithQuestionStatesProps)) => { const legacyStepRender = 'feedback_html' in step; const questionsRef = React.useRef>([]); const container = React.useRef(null); @@ -175,6 +181,7 @@ export const Exercise = ({ const mobileToolbarEnabled = Object.values(exerciseIcons || {}).some(({ location }) => location?.toolbar?.mobile); return +
@@ -217,4 +225,5 @@ export const Exercise = ({
; -}; +})` +`; diff --git a/src/components/Question.tsx b/src/components/Question.tsx index 9042ea60..64109bff 100644 --- a/src/components/Question.tsx +++ b/src/components/Question.tsx @@ -13,7 +13,7 @@ const StyledQuestion = styled.div` &.openstax-question { border-top: 1px solid ${colors.palette.pale}; - font-size: 1.8rem; + font-size: calc(1.8rem * var(--content-text-scale)); .detailed-solution { margin-bottom: 1rem; @@ -42,8 +42,8 @@ const StyledQuestion = styled.div` .answers-table { margin-bottom: 20px; - font-size: 1.6rem; - line-height: 2rem; + font-size: calc(1.6rem * var(--content-text-scale)); + line-height: calc(2rem * var(--content-text-scale)); } .instructions { diff --git a/src/components/StepCardFooter.tsx b/src/components/StepCardFooter.tsx index a5a127d1..886eb942 100644 --- a/src/components/StepCardFooter.tsx +++ b/src/components/StepCardFooter.tsx @@ -6,9 +6,10 @@ export const StepCardFooter = styled.div` display: flex; flex-wrap: wrap; justify-content: space-between; - font-size: 1.4rem; - line-height: 2rem; + font-size: calc(1.4rem * var(--content-text-scale)); + line-height: calc(2rem * var(--content-text-scale)); background: ${colors.card.body.background}; + overflow: auto; > * { flex-grow: 1; diff --git a/src/theme.ts b/src/theme.ts index c3b38992..dd33048d 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -208,7 +208,7 @@ export const mixins = { margin: calc(${layouts.popover.arrow.height} - 14px) 0 ${layouts.answer.horizontalSpacing} 8px; box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.1); color: ${colors.palette.neutralThin}; - font-size: 1.4rem; + font-size: calc(1.4rem * var(--content-text-scale)); .arrow { position: absolute; From c5c1d4ae7e6bdb4645a10045574ec1aed9157a67 Mon Sep 17 00:00:00 2001 From: Josiah Ivey Date: Wed, 18 Sep 2024 15:15:24 -0700 Subject: [PATCH 2/4] accept a className so styles can be added --- src/components/CompletionStatus.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/CompletionStatus.tsx b/src/components/CompletionStatus.tsx index 2a3efd46..8e9cb50c 100644 --- a/src/components/CompletionStatus.tsx +++ b/src/components/CompletionStatus.tsx @@ -12,6 +12,7 @@ export interface CompletionStatusProps { numberOfQuestions: number; numberCompleted: number; handleClick: () => void; + className?: string; } const CompletionStatusCard = styled(InnerStepCard)` @@ -36,7 +37,7 @@ const CompletionHeader = styled.h2` `; export const CompletionStatus = styled(({ - numberOfQuestions, numberCompleted, handleClick + numberOfQuestions, numberCompleted, handleClick, className }: CompletionStatusProps) => { const allCompleted = numberOfQuestions === numberCompleted; @@ -47,7 +48,7 @@ export const CompletionStatus = styled(({ return <> - + {allCompleted ? 'You are done.' : (someCompleted ? 'Quiz is partially complete.' : 'No questions have been answered.')}

{allCompleted ? 'Great job answering all the questions.' : (someCompleted ? `You've completed ${numberCompleted} of ${numberOfQuestions} questions.` : 'Begin working on the quiz.')}