Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
ade42d9
add contextual help component
jchartrand Oct 24, 2025
ac75458
make help clickably toggled
jchartrand Oct 26, 2025
292fc56
add help icon to contextual help component
jchartrand Oct 26, 2025
5359626
add styling to info icon
jchartrand Oct 27, 2025
8fa6c90
replace @floating-ui/react with @base-ui-components/react
jchartrand Oct 27, 2025
f15b02c
enable tailwind
jchartrand Oct 27, 2025
b16569f
set ContextualHelp children in dialog body
jchartrand Oct 27, 2025
69e1baf
rework passing content into help dialog
jchartrand Oct 27, 2025
d903e59
add root div for base-ui
jchartrand Oct 30, 2025
6295467
add vc-help-react module definition
jchartrand Oct 30, 2025
98e5286
extract help content to @digitalcredentials/vc-help-react
jchartrand Oct 30, 2025
c1bc7a1
add expiration date contextual help
jchartrand Oct 30, 2025
3b11748
make modal wider
jchartrand Oct 31, 2025
d08489e
refactor contextual help
jchartrand Oct 31, 2025
3f3d085
rework help styling to use modules
jchartrand Oct 31, 2025
8501054
add help icons
jchartrand Oct 31, 2025
6c3841a
add common help css
jchartrand Oct 31, 2025
26265de
update expiration date help
jchartrand Oct 31, 2025
6bc1787
update issuer help
jchartrand Oct 31, 2025
e5f05f2
add issuance date help
jchartrand Nov 3, 2025
4190706
add holder help
jchartrand Nov 3, 2025
19e9b1b
add description field help
jchartrand Nov 3, 2025
549c7e0
add criteria help
jchartrand Nov 3, 2025
b1408fe
refactor registry help
jchartrand Nov 3, 2025
194b0b6
add verification indicator help
jchartrand Nov 3, 2025
4de8697
style the field choice section
jchartrand Nov 3, 2025
fdba977
fix warning and not verified criteria for verication help
jchartrand Nov 3, 2025
217b8b4
add credential title help
jchartrand Nov 4, 2025
a6d5b7c
add achievementType help
jchartrand Nov 4, 2025
d45ed4a
update title and criteria styling
jchartrand Nov 4, 2025
80693bb
add badge image help to title help
jchartrand Nov 4, 2025
1145cd7
add resultItem typescript types
jchartrand Nov 4, 2025
39cd64a
add credential format help
jchartrand Nov 4, 2025
3f53d3e
replace generic css with tailwind for consistency
jchartrand Nov 4, 2025
a3a8567
fix help icon placement and spacing in log section
jchartrand Nov 4, 2025
feafe54
add signature help
jchartrand Nov 4, 2025
06e0495
add known issuer help
jchartrand Nov 5, 2025
67c7293
add revocation help
jchartrand Nov 5, 2025
eb64f6d
add scrolling for help content
jchartrand Nov 5, 2025
2ed6884
fix viewport scrolling size
jchartrand Nov 5, 2025
34512b4
add expiration help to log
jchartrand Nov 5, 2025
5f81f52
fix note icon alignment in description help
jchartrand Nov 5, 2025
d089ce4
update expiration date help content
jchartrand Nov 5, 2025
fb13254
fix achievement styling
jchartrand Nov 5, 2025
9364cee
fix format help styling
jchartrand Nov 5, 2025
5281c51
update signature help styling
jchartrand Nov 5, 2025
fd79ee1
update verification help styling
jchartrand Nov 5, 2025
4e2d5f5
update styling for issuer help
jchartrand Nov 5, 2025
9ad189e
separate issuer help into details and known issuer
jchartrand Nov 6, 2025
ef86185
rework issuer help
jchartrand Nov 6, 2025
a158c5a
resize and align info icons
jchartrand Nov 6, 2025
d991c77
fix spacing on note sections
jchartrand Nov 6, 2025
d347365
rework known issuer help text
jchartrand Nov 6, 2025
e9a05e6
rework warning and error messages
jchartrand Nov 7, 2025
1f42a80
add registry list help
jchartrand Nov 7, 2025
9220421
add VPR help
jchartrand Nov 7, 2025
e4ca255
add paste help
jchartrand Nov 10, 2025
98fa6fd
reposition help icons on main page and fix paste content
jchartrand Nov 10, 2025
8886c6e
add drag and drop help
jchartrand Nov 10, 2025
cab0708
add QR scanning help
jchartrand Nov 10, 2025
94c9b00
add contextual help toggle
jchartrand Nov 11, 2025
752a33b
add chapi help
jchartrand Nov 11, 2025
7ccde8e
fix help toggle set from localStorage
jchartrand Nov 11, 2025
2de8733
add warning message help
jchartrand Nov 12, 2025
be62ba2
add help for not verified message
jchartrand Nov 12, 2025
9de13a3
fix expiration date help react hydration error
jchartrand Nov 12, 2025
95a3855
add help for not a vc error
jchartrand Nov 12, 2025
da3fc5d
update changelog and version
jchartrand Nov 13, 2025
31e683f
rework help toggle to fix parameterized credential page and fix test …
jchartrand Nov 13, 2025
818f690
make help icon bigger and indicate clickable on hover
jchartrand Nov 14, 2025
4e622e1
switch help icon to pixels for consistency
jchartrand Nov 17, 2025
4c43933
rework help modals to use collapsible sections and to use more space …
jchartrand Nov 17, 2025
d3b5a75
add summary section to contextual help
jchartrand Nov 17, 2025
9e26638
rework expiration vc examples
jchartrand Nov 18, 2025
57846ae
fix contextualHelp attribute error
jchartrand Nov 18, 2025
7396234
add VC display component
jchartrand Nov 18, 2025
52522c4
fix link sections of vc view
jchartrand Nov 19, 2025
d25b0ce
fix VC v1 example for expiration date
jchartrand Nov 19, 2025
eecd943
add option to expand specific nodes for example VCs
jchartrand Nov 19, 2025
55924c2
disable ssr for react-json-view
jchartrand Nov 19, 2025
6efec8e
add mobile media query max chars for VC field length
jchartrand Nov 19, 2025
251a430
add copy link to clipboard option
jchartrand Nov 20, 2025
14fb906
add copy to clipboard for example vc
jchartrand Nov 20, 2025
0a1490a
allow rectangular issuer icon
jchartrand Dec 3, 2025
8bb4221
rework validFrom and validUntil help
jchartrand Dec 3, 2025
4e121e2
rework help for validFrom/validUntil
jchartrand Dec 3, 2025
6565d3f
override inherited vertical-align on help icon
jchartrand Dec 4, 2025
78c4434
formatting;update help text
jchartrand Dec 4, 2025
60404db
rework paste area help
jchartrand Dec 5, 2025
63a3209
rework VPR help
jchartrand Dec 5, 2025
0043f89
rework drag and drop help
jchartrand Dec 5, 2025
a51ee3a
rework qr scan help
jchartrand Dec 5, 2025
0826ac4
rework chapi help
jchartrand Dec 5, 2025
a9119c5
rework help for vc error
jchartrand Dec 5, 2025
bad18a9
rework status help
jchartrand Dec 8, 2025
b27214f
rework title and image help
jchartrand Dec 8, 2025
6929dd2
add DCC legacy VC and rework
jchartrand Dec 8, 2025
39d40f0
rework achievementType help, including new VC example
jchartrand Dec 8, 2025
4632d9d
rework issuer help
jchartrand Dec 8, 2025
98dd107
rework holder help
jchartrand Dec 16, 2025
bd09666
add vc examples to holder help
jchartrand Dec 16, 2025
dbf8faf
rework credential description help
jchartrand Dec 17, 2025
21cc3ec
rework criteria help
jchartrand Dec 17, 2025
d0e9c38
update well-formed help
jchartrand Dec 17, 2025
896bf21
add alignment help
jchartrand Dec 17, 2025
1be29ef
rework signature help
jchartrand Dec 17, 2025
ffbd157
rework known issuer help
jchartrand Dec 17, 2025
638648d
rework revocation help
jchartrand Dec 17, 2025
cd91632
fix validUntil help
jchartrand Dec 19, 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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# verifier-plus Changelog

## 2.0.2
### Added
- Contextual Help
### Fixed
- browser title

## 2.0.1
### Added
- Add Alignments to Open Badges 3.0 Display
Expand Down
5 changes: 4 additions & 1 deletion app/components/Alignment/Alignment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import type { Alignment as AlignmentType } from '@/types/credential.d'
import { isValidHttpUrl } from '@/lib/url'
import type { AlignmentProps } from './Alignment.d'
import { TestId } from '@/lib/testIds'
import { alignmentHelpDescription, alignmentHelpSections } from '../Help'
import { ContextualHelp } from '../ContextualHelp/ContextualHelp'

export const Alignment = ({ alignment, headerClassName }: AlignmentProps) => {
const alignmentsArray: AlignmentType[] = Array.isArray(alignment) ? alignment : (alignment ? [alignment] : [])
Expand All @@ -18,7 +20,7 @@ export const Alignment = ({ alignment, headerClassName }: AlignmentProps) => {

return (
<section className={styles.container} data-testid={TestId.Alignment}>
<h3 className={headerClassName ?? styles.header}>Alignments</h3>
<h3 className={headerClassName ?? styles.header}>Alignments <ContextualHelp title='Alignments' sections={alignmentHelpSections} description={alignmentHelpDescription}/></h3>
<ul className={styles.list}>
{items.map((a, idx) => (
<li key={`${a.targetUrl || a.targetName}-${idx}`} className={styles.item}>
Expand All @@ -38,6 +40,7 @@ export const Alignment = ({ alignment, headerClassName }: AlignmentProps) => {
</li>
))}
</ul>

</section>
)
}
Expand Down
1 change: 1 addition & 0 deletions app/components/Button/Button.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export type ButtonProps = {
icon?: ReactElement | null;
onClick?: (e: React.SyntheticEvent) => void;
className?: string;
children?: ReactElement;
}
4 changes: 2 additions & 2 deletions app/components/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { ButtonProps } from './Button.d';
import styles from './Button.module.css';
export const Button = ({secondary = false, onClick = () => {}, text, icon = null, className = ''}: ButtonProps) => {
export const Button = ({secondary = false, onClick = () => {}, text, icon = null, className = '', children}: ButtonProps) => {
return (
<button className={`${styles.button} ${secondary ? styles.secondaryButton : ''} ${className}`} onClick={onClick}>
{icon} {text}
{icon} {text} {children}
</button>
)
}
16 changes: 16 additions & 0 deletions app/components/ContextualHelp/ContextualHelp.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React, { ReactElement, ReactNode } from "react"

export type ContextualHelpProps = {
title?: string;
description?: ReactNode;
children?: ReactNode;
iconSize?: string;
iconColor?: string;
style?: string;
sections?: CollapsibleSectionProps[]
}

export type CollapsibleSectionProps = {
sectionTitle: string;
content: ReactNode;
}
20 changes: 20 additions & 0 deletions app/components/ContextualHelp/ContextualHelp.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.icon {
margin-left: .5em;
font-size: .9em;
vertical-align: top;
}


.help-icon-container {
/* Ensures the cursor changes to a hand icon on hover */
cursor: pointer;
/* Optional: Add a smooth transition for visual effects */
transition: color 0.3s ease;
}

.help-icon-container:hover {
/* Optional: Change the color on hover */
color: #007bff;
/* Optional: Add a slight scale effect */
transform: scale(1.1);
}
80 changes: 80 additions & 0 deletions app/components/ContextualHelp/ContextualHelp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import * as React from 'react';
import type { CollapsibleSectionProps, ContextualHelpProps } from './ContextualHelp.d';
import HelpIcon from '@mui/icons-material/HelpOutlined';
import { Dialog } from '@base-ui-components/react/dialog';
import { ScrollArea } from '@base-ui-components/react/scroll-area';
import { Collapsible } from '@base-ui-components/react/collapsible';
import { useHelpContext } from '@/lib/HelpContext';

function ChevronIcon(props: React.ComponentProps<'svg'>) {
return (
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" {...props}>
<path d="M3.5 9L7.5 5L3.5 1" stroke="currentcolor" />
</svg>
);
}

const CollapsibleSection = ({ sectionTitle, content }: CollapsibleSectionProps) => {
return (
<Collapsible.Root className="flex flex-col justify-center text-gray-900">
<Collapsible.Trigger className="group flex items-center gap-2 rounded-sm bg-gray-100 px-2 py-1 text-sm font-medium hover:bg-gray-200 focus-visible:outline focus-visible:outline-blue-800 active:bg-gray-200">
<ChevronIcon className="size-3 transition-all ease-out group-data-[panel-open]:rotate-90" />
{sectionTitle}
</Collapsible.Trigger>
<Collapsible.Panel className="flex h-[var(--collapsible-panel-height)] flex-col justify-end overflow-hidden text-sm transition-all ease-out data-[ending-style]:h-0 data-[starting-style]:h-0">
<div className="mt-1 flex cursor-text flex-col gap-2 rounded-sm bg-gray-100 py-2 pl-7">
{content}
</div>
</Collapsible.Panel>
</Collapsible.Root>)
}

export const ContextualHelp = ({ title, description, iconSize = '12px', children, sections, iconColor = 'info', style = "align-top mx-1 inline m-h-1" }: ContextualHelpProps) => {
let {isHelpEnabled} = useHelpContext();
if (isHelpEnabled) {
return (

<Dialog.Root>
<Dialog.Trigger onClick={(e) => e.stopPropagation()} nativeButton={false} render={<span className={`${style} hover:cursor-pointer`}><HelpIcon sx={{ fontSize: iconSize, verticalAlign: 'top' }} htmlColor={iconColor} /></span>}>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Backdrop className="fixed inset-0 min-h-dvh bg-black opacity-20 transition-all duration-150 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0 dark:opacity-70 supports-[-webkit-touch-callout:none]:absolute" />
<Dialog.Popup className="fixed top-1/2 left-1/2 -mt-8 w-200 max-w-[calc(100vw)] md:max-w-[calc(100vw-3rem)] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-gray-50 p-2 md:p-6 text-gray-900 outline outline-gray-200 transition-all duration-150 data-[ending-style]:scale-90 data-[ending-style]:opacity-0 data-[starting-style]:scale-90 data-[starting-style]:opacity-0 dark:outline-gray-300">
<Dialog.Title className="-mt-1.5 mb-1 text-lg text-center md:text-left font-medium">{title}</Dialog.Title>

<ScrollArea.Root className="w-full">
<ScrollArea.Viewport className="max-h-[75dvh] overscroll-contain rounded-md outline -outline-offset-1 outline-gray-200 focus-visible:outline focus-visible:outline-blue-800">
<div className="flex flex-col gap-4 py-5 pr-1 pl-1 md:pr-5 md:pl-5 text-sm leading-[1.375rem] text-gray-900">
{description}
{children}
{
sections && sections.map((section : CollapsibleSectionProps) => (
<CollapsibleSection key={crypto.randomUUID()} content={section.content} sectionTitle={section.sectionTitle} />
))
}
</div>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar className="m-2 flex w-1 justify-center rounded bg-gray-200 opacity-0 transition-opacity delay-300 pointer-events-none data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[hovering]:duration-75 data-[hovering]:pointer-events-auto data-[scrolling]:opacity-100 data-[scrolling]:delay-0 data-[scrolling]:duration-75 data-[scrolling]:pointer-events-auto">
<ScrollArea.Thumb className="w-full rounded bg-gray-500" />
</ScrollArea.Scrollbar>
</ScrollArea.Root>

<div className="flex justify-end gap-4 mt-5">
<Dialog.Close className="flex h-10 items-center justify-center rounded-md border border-gray-200 bg-gray-50 px-3.5 text-base font-medium text-gray-900 select-none hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-blue-800 active:bg-gray-100">
Close
</Dialog.Close>
</div>
</Dialog.Popup>
</Dialog.Portal>
</Dialog.Root>
);
} else {
return null
}
}






9 changes: 9 additions & 0 deletions app/components/CopyToClipboard/CopyToClipboard.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type CopyToClipboardProps = {
text: string;
buttonText: string;
}

export type CopyButtonProps = {
buttonText: string;
handleClick: function;
}
35 changes: 35 additions & 0 deletions app/components/CopyToClipboard/CopyToClipboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { CopyButtonProps, CopyToClipboardProps } from './CopyToClipboard.d';


import { IconButton, Button, Snackbar } from '@mui/material'
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import { useState } from 'react'

const CopyButton = ({buttonText, handleClick} : CopyButtonProps) => {
return buttonText?
<Button onClick={handleClick} style={{fontSize:'.7em', fontWeight:'bold'}} color="inherit" size="small" variant="outlined" endIcon={<ContentCopyIcon />} > {buttonText} </Button>
:
<IconButton onClick={handleClick}><ContentCopyIcon/></IconButton>
}

export const CopyToClipboard = ({text, buttonText}: CopyToClipboardProps) => {
const [open, setOpen] = useState(false)

const handleClick = () => {
setOpen(true)
navigator.clipboard.writeText(text)
}

return (
<>
<CopyButton buttonText={buttonText} handleClick={handleClick}/>
<Snackbar
open={open}
onClose={() => setOpen(false)}
autoHideDuration={2500}
message="Copied to clipboard!"
/>
</>
)
}

40 changes: 32 additions & 8 deletions app/components/CredentialCard/CredentialCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { extractNameFromOBV3Identifier } from '@/lib/extractNameFromOBV3Identifi
import { TestId } from '@/lib/testIds';
import { Alignment } from '@/components/Alignment/Alignment';

import { ContextualHelp } from '@/components/ContextualHelp/ContextualHelp'
import { holderHelpDescription, holderHelpSections, titleHelpDescription, titleHelpSections, achievementTypeHelpDescription, achievementTypeHelpSections, validUntilHelpSections, validUntilHelpDescription, validFromHelpDescription, validFromHelpSections, descriptionHelpDescription, descriptionHelpSections, criteriaHelpDescription, criteriaHelpSections } from '@/components/Help';



export const CredentialCard = ({ credential, wasMulti = false }: CredentialCardProps) => {
// TODO: add back IssuerInfoModal
Expand Down Expand Up @@ -64,8 +68,8 @@ export const CredentialCard = ({ credential, wasMulti = false }: CredentialCardP
<div className={styles.achivementInfo}>
{displayValues.achievementImage ? <img className={styles.achievementImage} src={displayValues.achievementImage} alt="achievement image" data-testid={TestId.AchievementImage}/> : null}
<div>
<h1 id='title' className={styles.credentialName} data-testid={TestId.CredentialName}>{displayValues.credentialName}</h1>
{displayValues.achievementType ? <p className={styles.achievementType} data-testid={TestId.AchievementType}>Achievement Type : {displayValues.achievementType}</p> : null}
<h1 id='title' className={styles.credentialName} data-testid={TestId.CredentialName}>{displayValues.credentialName}<ContextualHelp description={titleHelpDescription} sections={titleHelpSections} title="Credential Name and Image"/></h1>
{displayValues.achievementType ? <p className={styles.achievementType} data-testid={TestId.AchievementType}>Achievement Type : {displayValues.achievementType} <ContextualHelp title="Achievement Type" sections={achievementTypeHelpSections} description={achievementTypeHelpDescription}/></p> : null}
</div>
</div>
</div>
Expand All @@ -75,11 +79,20 @@ export const CredentialCard = ({ credential, wasMulti = false }: CredentialCardP
<Issuer issuer={issuer} infoButtonPushed={infoButtonPushed} header='Issuer' />
<div className={styles.headerRow}>
{displayValues.issuanceDate && (
<InfoBlock header="Issuance Date" contents={DateTime.fromISO(displayValues.issuanceDate).toLocaleString(DateTime.DATE_MED)} testId={TestId.IssuanceDate} />
<InfoBlock
header="Valid From"
helpDescription={validFromHelpDescription}
helpSections={validFromHelpSections}
helpTitle="ValidFrom"
contents={DateTime.fromISO(displayValues.issuanceDate).toLocaleString(DateTime.DATE_MED)}
testId={TestId.IssuanceDate} />
)}

<InfoBlock
header="Expiration Date"
header="Valid Until"
helpDescription={validUntilHelpDescription}
helpSections={validUntilHelpSections}
helpTitle="Valid Until"
contents={
displayValues.expirationDate
? DateTime.fromISO(displayValues.expirationDate).toLocaleString(DateTime.DATE_MED)
Expand All @@ -99,19 +112,30 @@ export const CredentialCard = ({ credential, wasMulti = false }: CredentialCardP

<div className={styles.primaryColumn}>
{displayValues.issuedTo ?
<InfoBlock header="Issued To" contents={displayValues.issuedTo} testId={TestId.IssuedTo}/>
<InfoBlock
header="Issued To"
helpDescription={holderHelpDescription}
helpSections={holderHelpSections}
helpTitle="Issued To"
contents={displayValues.issuedTo}
testId={TestId.IssuedTo}/>
:
null
}
{displayValues.credentialDescription ?
<InfoBlock header="Description" contents={displayValues.credentialDescription} testId={TestId.CredentialDescription}/>
<InfoBlock
header="Description"
helpDescription={descriptionHelpDescription}
helpSections={descriptionHelpSections}
helpTitle="Credential Description"
contents={displayValues.credentialDescription}
testId={TestId.CredentialDescription}/>
:
null
}
{displayValues.criteria && (
<div>
<h3 className={styles.smallHeader}>Criteria</h3>
{/* <div className={styles.credentialCriteria}>{displayValues.criteria}</div> */}
<h3 className={styles.smallHeader}>Criteria<ContextualHelp title="Criteria" description={criteriaHelpDescription} sections={criteriaHelpSections}/></h3>
<div className={styles.markdownContainer} data-testid={TestId.CredentialCriteria}>
<ReactMarkdown >{displayValues.criteria}</ReactMarkdown>
</div>
Expand Down
58 changes: 58 additions & 0 deletions app/components/Help/AchievementTypeHelp/AchievementTypeHelp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import styles from '../Help.module.css';
import { VcDisplay } from '@/components/VcDisplay/VcDisplay';

const ExampleV2Section = () => {
return <VcDisplay link='https://digitalcredentials.github.io/vc-test-fixtures/verifiableCredentials/v2/dataIntegrityProof/didKey/legacyRegistry-noStatus-noExpiry-achievementTypeExample.json' nodesToExpand={['credentialSubject', 'credentialSubject.achievement', 'credentialSubject.achievement.achievementType']}/>
}

const DeterminationSection = () => {
return (
<div>
<div className={styles.preference}>achievementType is a property of an Open Badges version 3 Verifiable Credential:</div>
<ul className={styles.list}>
<li>credential.credentialSubject.achievement.achievementType</li>
</ul>
<div className={styles.preference}>See the example section for a working example.</div>
</div>)
}

const DetailsSection = () => {
return (
<ul className={styles.list}>
<li>Examples include 'Award', 'Certification', 'DoctoralDegree'.</li>
<li>A full list of pre-defined Open Badge achievement types is defined in the <a target="_blank" className={styles.externalLink} href="https://www.imsglobal.org/spec/ob/v3p0#context">Open Badges Specification</a>. </li>
<li>New OBv3 achievement types can be added by extending the OBv3 context.</li>
<li>If no achievementType is available, nothing is shown, nor the label.</li>
</ul>
)
}

const NotesSection = () => {
return (
<>
<div className={styles.note}><img className={styles.infoIcon} src="./icons/info_24_lime.svg"></img>The goal of the achievementType field is interoperability.
If different credential issuers use the same achievementType for similar credentials then hopefully consumers of the
credential can treat the credentials as equivalent to some degree. It might of course be less useful to treat
two credentials with a very general achievementType like 'Award' as equivalent, but hopefully moreso for two credential of type 'DoctoralDegree'. Over time
we expect that issuers will converge on common definitions.
</div>
</>
)
}

const DescriptionSection = () => {
return (
<div className={styles.note}>The type of Open Badge v3 achievement.</div>
)
}

export const achievementTypeHelpDescription = DescriptionSection()

export const achievementTypeHelpSections = [
{ sectionTitle: 'Details', content: DetailsSection() },
{ sectionTitle: 'How We Determine the AchievementType', content: DeterminationSection() },
{ sectionTitle: 'Example - Open Badge version 3', content: ExampleV2Section() },
{ sectionTitle: 'Notes', content: NotesSection( )}
]


Loading