New source found from dndbeyond.com

This commit is contained in:
David Kruger 2025-06-05 01:00:10 -07:00
parent 3954b12f5d
commit 451d940294
14 changed files with 88 additions and 35 deletions

View File

@ -67,7 +67,7 @@ export const CharacterNameLimitMsg = `The max length for a name is ${InputLimits
export const SourceCategoryDescription = {
official:
"The sources below add additional character options beyond the 2024 Core Rules. You will only see character options from the Core Rules and content you own and have enabled here.",
"You will only see character options from content you own and have enabled here in both the builder and your character sheet. Removing all sources will prevent you from being able to create a complete character.",
homebrew:
"Character options designed by other players and uploaded to D&D BEYOND. Talk to your DM before including Homebrew content.",
partnered:

View File

@ -5,22 +5,22 @@ import type {
AllHTMLAttributes,
ButtonHTMLAttributes,
FC,
PropsWithChildren,
ReactNode,
} from "react";
import styles from "./styles/Button.module.css";
import sizeStyles from "./styles/ButtonSizes.module.css";
import variantStyles from "./styles/ButtonVariants.module.css";
export interface ButtonProps
extends PropsWithChildren,
Omit<
extends Omit<
AllHTMLAttributes<HTMLAnchorElement | HTMLButtonElement | HTMLDivElement>,
"size" | "type"
>,
Pick<ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
children?: ReactNode;
className?: string;
color?: "primary" | "secondary" | "success" | "info" | "warning" | "error";
variant?: "solid" | "outline" | "text";
variant?: "solid" | "outline" | "text" | "tool";
size?: "x-small" | "small" | "medium" | "large" | "x-large";
isDiv?: boolean;
}

View File

@ -3,7 +3,7 @@ import type { ChangeEvent, FC, ReactNode } from "react";
import styles from "./Checkbox.module.css";
export interface CheckboxProps {
id?: string;
id: string;
label?: ReactNode;
defaultChecked?: boolean;
checked?: boolean;

View File

@ -15,6 +15,7 @@ export interface DialogProps extends HTMLAttributes<HTMLDialogElement> {
open: boolean;
onClose: (e?: MouseEvent) => void;
modal?: boolean;
onBackdropClick?: () => void;
}
export const Dialog: React.FC<DialogProps> = ({
@ -23,6 +24,7 @@ export const Dialog: React.FC<DialogProps> = ({
modal,
children,
className,
onBackdropClick,
...props
}) => {
const dialogRef = useRef<HTMLDialogElement>(null);
@ -46,7 +48,10 @@ export const Dialog: React.FC<DialogProps> = ({
rect.left <= e.clientX &&
e.clientX <= rect.left + rect.width;
if (!isClickInDialog) handleClose();
if (!isClickInDialog) {
onBackdropClick?.();
handleClose();
}
};
const handleEsc = (e: KeyboardEvent) => {

View File

@ -2,15 +2,23 @@ import type { MegaMenuCardProps } from "../MegaMenuCard";
const ddbImageBase = "https://media.dndbeyond.com/mega-menu";
export const characterBuilder: MegaMenuCardProps = {
label: "Character Builder",
imageUrl: `${ddbImageBase}/323a928e32eff87dee85dfbe0793ce12.jpg`,
link: "https://www.dndbeyond.com/characters/builder",
};
export const primaryItems: MegaMenuCardProps[] = [
export const groupOne: MegaMenuCardProps[] = [
{
label: "Maps",
label: "Character Builder",
imageUrl: `${ddbImageBase}/character_builder.png`,
link: "https://www.dndbeyond.com/characters/builder",
},
{
label: "Sigil 3D VTT",
imageUrl: `${ddbImageBase}/playtest_sigil.png`,
link: "https://www.dndbeyond.com/project-sigil",
flags: [{ label: "New", variant: "success" }],
},
];
export const groupTwo: MegaMenuCardProps[] = [
{
label: "Maps VTT",
imageUrl: `${ddbImageBase}/049ddb9085342521d25c5230451cfd45.jpg`,
link: "https://www.dndbeyond.com/games",
flags: [{ label: "Beta", variant: "info" }],
@ -23,7 +31,7 @@ export const primaryItems: MegaMenuCardProps[] = [
},
];
export const secondaryItems: MegaMenuCardProps[] = [
export const groupThree: MegaMenuCardProps[] = [
{
label: "Mobile App",
imageUrl: `${ddbImageBase}/3aa58aac2d02bb52d62204e158b48ce6.jpg`,

View File

@ -1,5 +1,6 @@
"use client";
import clsx from "clsx";
import type { FC } from "react";
import { Tooltip as ReactTooltip, type ITooltip } from "react-tooltip";
import styles from "./Tooltip.module.css";
@ -7,22 +8,24 @@ import styles from "./Tooltip.module.css";
export interface TooltipProps extends ITooltip {
id: string;
"data-testid"?: string;
disableStyleInjection?: "core" | undefined;
}
export const Tooltip: FC<TooltipProps> = ({
id,
"data-testid": testId,
children,
disableStyleInjection,
...props
}) => {
return (
<div
className={styles.container}
{...(testId && { "data-testid": testId })}
}) => (
<div className={styles.container} {...(testId && { "data-testid": testId })}>
<ReactTooltip
id={id}
{...props}
className={clsx([styles.tooltip, props.className])}
disableStyleInjection={disableStyleInjection}
>
<ReactTooltip id={id} className={styles.tooltip} {...props}>
{children}
</ReactTooltip>
</div>
);
};
{children}
</ReactTooltip>
</div>
);

View File

@ -37,6 +37,7 @@ export const Listing: FC<ListingProps> = ({
key={item.id + "group"}
disabledIds={disabledIds}
onQuickSelect={onQuickSelect}
data-testid="sourceHeader"
/>
) : (
<ListingItemButton
@ -44,6 +45,7 @@ export const Listing: FC<ListingProps> = ({
isDisabled={isDisabled}
key={item.id}
onQuickSelect={onQuickSelect}
data-testid="optionButton"
/>
);
})

View File

@ -287,7 +287,11 @@ export const ClassChoose: FC<ClassChooseProps> = ({
};
return (
<div className={clsx([styles.page, className])} {...props}>
<div
className={clsx([styles.page, className])}
{...props}
data-testid="chooseClassSection"
>
{showHeader && (
<>
<PortraitName />
@ -400,7 +404,10 @@ export const ClassChoose: FC<ClassChooseProps> = ({
);
})
) : (
<p className={styles.notFound}>No Results Found</p>
<p className={styles.notFound}>
No Class options available. Return to the <strong>Home</strong>{" "}
tab to enable more source categories.
</p>
)}
</>
)}

View File

@ -96,7 +96,11 @@ export const SpeciesChoose: FC<SpeciesChooseProps> = ({
};
return (
<div className={clsx([styles.speciesChoose, className])} {...props}>
<div
className={clsx([styles.speciesChoose, className])}
{...props}
data-testid="chooseSpeciesSection"
>
{showHeader && (
<>
<PortraitName />
@ -160,8 +164,13 @@ export const SpeciesChoose: FC<SpeciesChooseProps> = ({
</div>
<hr className={styles.divider} />
<div className={clsx([styles.text, styles.marketplace])}>
Looking for something not in the list below? Unlock all official options
in the <Link href="/marketplace">Marketplace</Link>.
Check your source settings on the <strong>Home</strong> tab if you can't
find Species you've purchased.
<br />
Expand your library in the <Link href="/marketplace">
Marketplace
</Link>{" "}
for more Species options.
</div>
{isLoading ? (
<Spinner />

View File

@ -1163,8 +1163,12 @@ class DescriptionManage extends React.PureComponent<Props, State> {
return (
<React.Fragment>
<div className="ct-character-tools__marketplace-callout">
Looking for something not in the list below? Unlock all official
options in the <Link href="/marketplace">Marketplace</Link>.
Check your source settings on the <strong>Home</strong> tab if you
can't find Backgrounds you've purchased.
<br />
Expand your library in the{" "}
<Link href="/marketplace">Marketplace</Link> for more Background
options.
</div>
<div className="description-manage-background-chooser-con">
<div className="description-manage-background-chooser-field">

View File

@ -20,6 +20,7 @@ import PageHeader from "../../../components/PageHeader";
import { builderEnvSelectors, builderSelectors } from "../../../selectors";
import { BuilderAppState } from "../../../typings";
import ConnectedBuilderPage from "../ConnectedBuilderPage";
import styles from "./styles.module.css";
interface Props extends DispatchProp {
characterId: number | null;
@ -243,6 +244,13 @@ class WhatsNext extends React.PureComponent<Props, State> {
<div className="whats-next-action">{this.renderPdfButton()}</div>
</div>
{this.renderPdfData()}
{!isCharacterSheetReady && (
<p className={styles.returnToHomeText}>
If you are unable to create a character due to missing options,
return to the <strong>Home</strong> tab and change your source
settings.
</p>
)}
<div className="whats-next-characters">
<Link href={characterListingUrl}>View all my characters</Link>
</div>

View File

@ -1,6 +1,7 @@
import clsx from "clsx";
import { orderBy } from "lodash";
import React from "react";
import { v4 as uuidv4 } from "uuid";
import { Checkbox } from "~/components/Checkbox";
import { HtmlContent } from "~/components/HtmlContent";
@ -81,6 +82,7 @@ export const FormCheckBoxesField: React.FC<Props> = ({
</div>
<div className={styles.checkbox}>
<Checkbox
id={uuidv4()}
checked={checkbox.initiallyEnabled}
aria-label={checkbox.label}
onClick={checkbox.onChange}
@ -121,6 +123,7 @@ export const FormCheckBoxesField: React.FC<Props> = ({
<div className={styles.group} key={idx}>
<div className={styles.checkbox}>
<Checkbox
id={uuidv4()}
checked={checkbox.initiallyEnabled}
aria-label={checkbox.label}
onClick={checkbox.onChange}
@ -174,6 +177,7 @@ export const FormCheckBoxesField: React.FC<Props> = ({
onCheckUncheckAll &&
variant === CheckboxVariant.DEFAULT && (
<Checkbox
id={uuidv4()}
checked={allChecksEnabled}
aria-label="Check/Uncheck all"
onClick={onCheckUncheckAll.onChange}
@ -215,6 +219,7 @@ export const FormCheckBoxesField: React.FC<Props> = ({
<div className={styles.summaryHeadingGroup}>
{checkUncheckAllEnabled && onCheckUncheckAll && (
<Checkbox
id={uuidv4()}
checked={allChecksEnabled}
aria-label="Check/Uncheck all"
onClick={onCheckUncheckAll.onChange}

View File

@ -0,0 +1,2 @@
// extracted by mini-css-extract-plugin
export default {"returnToHomeText":"styles_returnToHomeText__C7eSU"};

View File

@ -1,2 +1,2 @@
// extracted by mini-css-extract-plugin
export default {"primary":"ButtonVariants_primary__TMQ5y","secondary":"ButtonVariants_secondary__Z0czz","success":"ButtonVariants_success__OhFyN","info":"ButtonVariants_info__+w8ox","warning":"ButtonVariants_warning__qCfwB","error":"ButtonVariants_error__6SkiQ","outline":"ButtonVariants_outline__v36Mn","svg":"ButtonVariants_svg__Si33n","text":"ButtonVariants_text__vKMzd"};
export default {"primary":"ButtonVariants_primary__TMQ5y","secondary":"ButtonVariants_secondary__Z0czz","success":"ButtonVariants_success__OhFyN","info":"ButtonVariants_info__+w8ox","warning":"ButtonVariants_warning__qCfwB","error":"ButtonVariants_error__6SkiQ","outline":"ButtonVariants_outline__v36Mn","svg":"ButtonVariants_svg__Si33n","text":"ButtonVariants_text__vKMzd","tool":"ButtonVariants_tool__mrrWB"};