Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e854fc3
Remove all Phy-specific references from item
sjd210 Nov 3, 2025
da8f774
Make Ada-specific references into generic ones
sjd210 Nov 3, 2025
f0626bb
Add correct icon structuring to Ada ALVIs
sjd210 Nov 3, 2025
d92fda6
Display Ada question titles consistently
sjd210 Nov 3, 2025
5828815
Re-style status and difficulty
sjd210 Nov 3, 2025
a584e09
Re-adjust vertical spacing for alt width questions
sjd210 Nov 3, 2025
f478f82
Restructure Ada list-group css file
sjd210 Nov 3, 2025
3217d73
Apply ALVI changes to progress page
sjd210 Nov 3, 2025
c41e0f7
Add ALVIs with carets to Ada Search
sjd210 Nov 3, 2025
e3d6076
Add new ListViewItem for topics
sjd210 Nov 3, 2025
bec442b
Add shorthand for CS icon path
sjd210 Nov 3, 2025
07aa701
Add breadcrumbs to external Ada ALVIs with caret
sjd210 Nov 3, 2025
c9ad9ce
Set ALL_INCORRECT completion icon to IN_PROGRESS
sjd210 Nov 3, 2025
404baba
Stop displaying top-level "Computer Science" tag
sjd210 Nov 3, 2025
1f240fb
Add question icon label to other question icons
sjd210 Nov 3, 2025
7cc68df
Update VRT baselines
actions-user Nov 3, 2025
d6fd5ce
Merge pull request #1815 from isaacphysics/vrt/improvement/remove-CSLGIs
sjd210 Nov 3, 2025
d13da00
Update breadcrumb code with CompSci-exclusion func
sjd210 Nov 4, 2025
a020e8c
Replace GameboardViewer with ListView for boards
sjd210 Nov 4, 2025
b6dacc5
Apply card-header styling for empty cards globally
sjd210 Nov 4, 2025
7772c2f
Make empty card header rule more specific
sjd210 Nov 4, 2025
70651ac
Show question deck preview as ListView on schedule
sjd210 Nov 4, 2025
f5e3454
Move gameboard preview into shared component
sjd210 Nov 4, 2025
a374417
Remove now-unused GameboardViewer
sjd210 Nov 4, 2025
f0d5a1c
Enable property tags on Ada
sjd210 Nov 4, 2025
40ba899
Fix ESLint errors
sjd210 Nov 4, 2025
2cbc216
Correct html selector to new Ada format in test
sjd210 Nov 4, 2025
37655e5
Hide icon labels on the QF and <=xs screens
sjd210 Nov 6, 2025
3bb2091
Correct topic summary links
sjd210 Nov 6, 2025
5d7355d
Replace "hex" type with "icon" type in TitleIcon
sjd210 Nov 6, 2025
04d882c
Replace PhyHexIcon with more generic HexIcon
sjd210 Nov 6, 2025
95ece5d
Add icon status classes to Ada
sjd210 Nov 6, 2025
db5bcac
Add question status -> icon mappings
sjd210 Nov 6, 2025
b06a2ee
Add default size back to HexIcon
sjd210 Nov 6, 2025
3bac11e
Replace question list ternary with const mapping
sjd210 Nov 6, 2025
18096d5
Replace Ada ListView "img" icons with "icon" ones
sjd210 Nov 6, 2025
b5c0de6
Remove unused function
sjd210 Nov 6, 2025
782577b
Move icon changes to another branch
sjd210 Nov 6, 2025
7d929ca
Re-add missing iconPath from reversion
sjd210 Nov 7, 2025
533c47b
Update icons used in search to 32px
sjd210 Nov 7, 2025
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
4 changes: 2 additions & 2 deletions src/app/components/elements/ContentPropertyTags.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { isStaff, isTeacherOrAbove } from "../../services";
import { isPhy, isStaff, isTeacherOrAbove } from "../../services";
import { selectors, useAppSelector } from "../../state";
import classNames from "classnames";
import {v4 as uuid_v4} from "uuid";
Expand All @@ -16,7 +16,7 @@ export const QuestionPropertyTags = ({ supersededBy, tags, ...rest }: QuestionPr
const accessibilitySettings = useAccessibilitySettings();

return <div {...rest} className={classNames("d-flex gap-2 align-items-center", rest.className)}>
{accessibilitySettings?.SHOW_INACCESSIBLE_WARNING && getAccessibilityTags(tags)?.map(tag => {
{isPhy && accessibilitySettings?.SHOW_INACCESSIBLE_WARNING && getAccessibilityTags(tags)?.map(tag => {
const id = `access-warn-${uuid_v4()}`; // must be globally unique. making refs in a loop was too painful.
return <React.Fragment key={tag}>
<i className={`icon icon-md ${ACCESSIBILITY_WARNINGS[tag].icon} icon-access-visual icon-color-black z-2`} id={id} />
Expand Down
3 changes: 1 addition & 2 deletions src/app/components/elements/GameboardBuilderRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@ const GameboardBuilderRow = (
</button>
<Spacer />
</div>
{isPhy && <QuestionPropertyTags className="my-1" supersededBy={question.supersededBy} tags={question.tags} />}

<QuestionPropertyTags className="my-1" supersededBy={question.supersededBy} tags={question.tags} />
{question.subtitle && <>
<span className="small text-muted d-none d-sm-block">{question.subtitle}</span>
</>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from "react";
import { isAda } from "../../services";

export function LLMFreeTextQuestionIndicator({small, symbol, className}: {small?: boolean, symbol?: boolean, className?: string}) {
return <div className={classNames(className, "llm-indicator text-nowrap my-1", { small })}>
return <div className={classNames(className, "llm-indicator text-nowrap", {small, "my-1": !small})}>
<span className={classNames("icon icon-ai", {"me-2": !symbol}, {"icon-md": isAda})}/>
{!symbol && `LLM marked question`}
</div>;
Expand Down
4 changes: 3 additions & 1 deletion src/app/components/elements/PageTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export interface TitleIconProps extends PhyHexIconProps {
type: "img" | "hex" | "placeholder";
height?: string;
width?: string;
alt?: string;
label?: string;
}

export interface PageTitleProps {
Expand Down Expand Up @@ -97,7 +99,7 @@ export const PageTitle = ({currentPageTitle, displayTitleOverride, subTitle, dis
return <h1 id="main-heading" tabIndex={-1} ref={headerRef} className={classNames("h-title h-secondary d-sm-flex", {"align-items-center py-2 mb-0": isPhy}, className)}>
<div className="d-flex w-100" data-testid={"main-heading"}>
{isPhy && icon && (
icon.type === "img" ? <img src={icon.icon} alt="" height={icon.height} width={icon.width} className="me-3"/>
icon.type === "img" ? <img src={icon.icon} alt={icon.alt ?? ""} height={icon.height} width={icon.width} className="me-3"/>
: icon.type === "hex" ? <PhyHexIcon icon={icon.icon} subject={icon.subject} style={{"height": icon.height, "width": icon.width}}/>
: icon.type === "placeholder" ? <div style={{width: icon.width, height: icon.height}}/>
: undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const StageAndDifficultySummaryIcons = (props: StageAndDifficultySummaryI
</span>
)}
</div>,
<div className={classNames(className, "d-sm-flex flex-wrap mt-1 align-items-baseline", {"justify-content-end": !stack})}>
<div className={classNames(className, "d-sm-flex flex-wrap align-items-baseline", {"justify-content-end": !stack})}>
<div key={`${difficulties[0]}`} className={classNames("align-self-center d-flex align-items-center")}>
{difficulties.length > 0 && <>
<div className="hierarchy-tags text-center me-2">
Expand Down
12 changes: 9 additions & 3 deletions src/app/components/elements/layout/SidebarLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { EventsPageQueryParams } from "../../pages/Events";
import { StyledDropdown } from "../inputs/DropdownInput";
import { CollapsibleList } from "../CollapsibleList";
import { extendUrl } from "../../pages/subjectLandingPageComponents";
import { getProgressIcon } from "../../pages/Gameboard";
import { tags as tagsService } from "../../../services";
import { Markup } from "../markup";
import { History } from "history";
Expand Down Expand Up @@ -69,11 +68,18 @@ const QuestionLink = (props: React.HTMLAttributes<HTMLLIElement> & QuestionLinkP
const audienceFields = filterAudienceViewsByProperties(determineAudienceViews(question.audience), AUDIENCE_DISPLAY_FIELDS);
const link = isDefined(gameboardId) ? `/questions/${question.id}?board=${gameboardId}` : `/questions/${question.id}`;

const progressIcon = question.state && (question.state === CompletionState.ALL_CORRECT
? "icon icon-raw icon-correct"
: [CompletionState.ALL_INCORRECT, CompletionState.ALL_ATTEMPTED].includes(question.state)
? "icon icon-raw icon-attempted"
: question.state === CompletionState.IN_PROGRESS
? "icon icon-raw icon-in-progress"
: "icon icon-raw icon-not-started");

return <li key={question.id} {...rest} data-bs-theme={getThemeFromContextAndTags(subject, question.tags ?? [])}>
<Link to={link} className="py-2">
{(isDefined(gameboardId) || question.state !== CompletionState.NOT_ATTEMPTED)
? <i className={classNames(getProgressIcon(question.state).icon, {"ms-2": isDefined(gameboardId)})} style={{minWidth: "16px"}}/>

? <i className={classNames(progressIcon, {"ms-2": isDefined(gameboardId)})} style={{minWidth: "16px"}}/>
: <i className="icon icon-question-thick"/>
}
<div className="d-flex flex-column w-100">
Expand Down
33 changes: 19 additions & 14 deletions src/app/components/elements/list-groups/AbstractListViewItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ViewingContext} from "../../../../IsaacAppTypes";
import classNames from "classnames";
import { Badge, Button, Col, ListGroupItem } from "reactstrap";
import { CompletionState, GameboardDTO } from "../../../../IsaacApiTypes";
import { below, isDefined, isPhy, isTeacherOrAbove, siteSpecific, Subject, useDeviceSize } from "../../../services";
import { above, below, isAda, isDefined, isPhy, isTeacherOrAbove, siteSpecific, Subject, useDeviceSize } from "../../../services";
import { PhyHexIcon } from "../svg/PhyHexIcon";
import { TitleIconProps } from "../PageTitle";
import { Markup } from "../markup";
Expand Down Expand Up @@ -161,9 +161,10 @@ export type AbstractListViewItemProps = {
url?: string;
state?: AbstractListViewItemState;
className?: string;
hasCaret?: boolean;
} & ALVIType & ALVILayout;

export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb, tags, fullWidth, url, state, className, ...typedProps}: AbstractListViewItemProps) => {
export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb, tags, fullWidth, url, state, className, hasCaret, ...typedProps}: AbstractListViewItemProps) => {
const deviceSize = useDeviceSize();
const user = useAppSelector(selectors.user.orNull);

Expand All @@ -176,19 +177,20 @@ export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb
fullWidth = fullWidth || below["sm"](deviceSize) || (isItem && !(typedProps.status || typedProps.audienceViews));
const cardBody = <div className="w-100 d-flex flex-row">
<Col className={classNames("d-flex flex-grow-1", {"mt-3": isCard, "mb-3": isCard && !typedProps.linkTags?.length})}>
<div className="position-relative">
{icon && (
icon.type === "img" ? <img src={icon.icon} alt="" width={icon.width} height={icon.height} className={classNames(icon.className, "me-3")} />
<div className={classNames("position-relative", {"question-progress-icon": isAda})}>
{icon && <div className="inner-progress-icon">
{icon.type === "img" ? <img src={icon.icon} alt={icon.alt ?? ""} width={icon.width} height={icon.height} className={classNames(icon.className, {"me-3": isPhy})} />
: icon.type === "hex" ? <PhyHexIcon icon={icon.icon} subject={icon.subject} size={icon.size} className={icon.className} />
: icon.type === "placeholder" ? <div style={{width: icon.width, height: icon.height}} />
: undefined
)}
{isItem && typedProps.status && typedProps.status === CompletionState.ALL_CORRECT && <div className="list-view-status-indicator">
: undefined}
{icon.label && above['sm'](deviceSize) && <div className="icon-title mt-1">{icon.label}</div>}
</div>}
{isPhy && isItem && typedProps.status && typedProps.status === CompletionState.ALL_CORRECT && <div className="list-view-status-indicator">
<StatusDisplay status={typedProps.status} showText={false} />
</div>}
{isGameboard && typedProps.board?.contents && <ItemCount count={typedProps.board.contents.length} />}
</div>
<div className="align-content-center text-overflow-ellipsis pe-2">
<div className={classNames("align-content-center text-overflow-ellipsis", siteSpecific("pe-2", "py-3"))}>
<div className="d-flex text-wrap mt-n1">
{url && !isDisabled
? (url.startsWith("http")
Expand All @@ -205,7 +207,7 @@ export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb
}
{isItem && <>
{typedProps.quizTag && <span className="quiz-level-1-tag ms-sm-2">{typedProps.quizTag}</span>}
{isPhy && <QuestionPropertyTags className="ms-2 justify-self-end" supersededBy={typedProps.supersededBy} tags={tags} />}
<QuestionPropertyTags className="ms-2 justify-self-end" supersededBy={typedProps.supersededBy} tags={tags} />
</>}
</div>
{subtitle && <div className="small text-muted text-wrap">
Expand All @@ -217,10 +219,10 @@ export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb
{isItem && fullWidth && typedProps.audienceViews && <div className="d-flex mt-1">
<StageAndDifficultySummaryIcons audienceViews={typedProps.audienceViews} stack/>
</div>}
{tags?.includes("llm_question_page") && <div className="mt-2">
{tags?.includes("llm_question_page") && <div className={classNames("mt-1", {"mt-2": isPhy || !fullWidth})}>
<LLMFreeTextQuestionIndicator small />
</div>}
{isItem && fullWidth && typedProps.status && typedProps.status !== CompletionState.ALL_CORRECT &&
{isPhy && isItem && fullWidth && typedProps.status && typedProps.status !== CompletionState.ALL_CORRECT &&
<StatusDisplay status={typedProps.status} showText className="py-1" />
}
{isGameboard && fullWidth && isTeacherOrAbove(user) && <div className="d-flex pt-3">
Expand All @@ -236,9 +238,9 @@ export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb
</Col>
{!fullWidth &&
<>
{isItem && typedProps.status && typedProps.status !== CompletionState.ALL_CORRECT && <StatusDisplay status={typedProps.status} showText className="ms-2 me-3" />}
{isPhy && isItem && typedProps.status && typedProps.status !== CompletionState.ALL_CORRECT && <StatusDisplay status={typedProps.status} showText className="ms-2 me-3" />}
{isItem && typedProps.audienceViews && <div className={classNames("d-none d-md-flex justify-content-end wf-13", {"list-view-border": typedProps.audienceViews.length > 0})}>
<StageAndDifficultySummaryIcons audienceViews={typedProps.audienceViews} stack className="w-100"/>
<StageAndDifficultySummaryIcons audienceViews={typedProps.audienceViews} stack className={siteSpecific("w-100", "py-3 pe-3")}/>
</div>}
{isGameboard && isTeacherOrAbove(user) && <Col md={6} className="d-none d-md-flex align-items-center justify-content-end">
<GameboardAssign board={typedProps.board} />
Expand All @@ -248,6 +250,9 @@ export const AbstractListViewItem = ({title, icon, subject, subtitle, breadcrumb
</Col>}
</>
}
{hasCaret && <div className="list-caret align-content-center" aria-hidden="true">
<i className="icon icon-chevron-right" aria-hidden="true"/>
</div>}
</div>;

return <ListGroupItem
Expand Down
Loading