Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .claude/skills/new-prototype/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const CLUB = school(STUDENT.schoolId)!

Get this wrong and changing the cast produces a flow that fills in one club's
code and then rejects that club's usernames. See
`onboarding-yp/reference-school-code-join` for the pattern.
`import-yp/browse-projects-in-classroom` for the pattern.

See `#/debug` for everyone available.

Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ Either way the prototype is discovered automatically and appears on the landing
page in its lane — **no shared file needs to change**, which is what lets
several people build at once without conflicting.

Two worked examples to copy from, one per audience:
Worked examples to copy from, one per audience:

- `onboarding-mentor/reference-manage-club-route`
- `onboarding-yp/reference-school-code-join`
- `import-mentor/start-on-projects` — a mentor, signed out, browsing and
importing
- `import-yp/browse-projects-in-classroom` — a young person, signing in with a
school code

Both are real click-throughs. See [`src/prototypes/README.md`](src/prototypes/README.md).

Expand Down
2 changes: 1 addition & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ it is short, and the one rule in it matters.
Send them a link with `?full=1&autofill=0` on the end:

```
#/p/onboarding-yp/reference-school-code-join?full=1&autofill=0
#/p/import-yp/browse-projects-in-classroom?full=1&autofill=0
```

That hides everything belonging to the workbench and leaves the sign-in fields
Expand Down
2 changes: 1 addition & 1 deletion src/prototypes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ you need to send:
For a testing session, both:

```
#/p/onboarding-yp/reference-school-code-join?full=1&autofill=0
#/p/import-yp/browse-projects-in-classroom?full=1&autofill=0
```

That opens clean, with nothing pre-typed — so you can watch someone read a
Expand Down
2 changes: 1 addition & 1 deletion src/prototypes/_template/prototype.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Surface } from '../../surfaces'
// and belongs in notes.md.
//
// Derive everything else from the cast — do not hardcode a club. See
// onboarding-yp/reference-school-code-join for how.
// import-yp/browse-projects-in-classroom for how.
//
// See #/debug for everyone available.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, type CSSProperties } from 'react'
import { useState } from 'react'
import { Modal, TextInput } from '../../../kit'
import { PROJECT_TYPES, type ProjectTypeId } from './projectTypes'

Expand Down Expand Up @@ -143,107 +143,103 @@ export function AddProjectChoice({ isOpen, setIsOpen, className, onFind, onCreat
}

return (
// The custom property inherits down to the dialog element, which is how a
// narrower modal is possible without touching the shared stylesheet.
<div style={{ '--rpf-modal-max-inline-size': '30rem' } as CSSProperties}>
<Modal
isOpen={isOpen}
setIsOpen={(open) => (open ? setIsOpen(true) : close())}
heading={onCreateStep ? 'Create a new project' : 'Add a project'}
showCloseButton
primaryButtonText={onCreateStep ? 'Create project' : 'Continue'}
onClickPrimaryButton={onCreateStep ? create : forward}
// "Back" rather than "Cancel" on step 2: it came from a question, so
// returning to it is more use than dismissing. The header's X still
// cancels, which is how the live dialog's two buttons stay two.
secondaryButtonText={onCreateStep ? 'Back' : 'Cancel'}
onClickSecondaryButton={onCreateStep ? () => setOnCreateStep(false) : close}
>
{/* The modal's content box centres its children, so this has to claim
<Modal
isOpen={isOpen}
setIsOpen={(open) => (open ? setIsOpen(true) : close())}
heading={onCreateStep ? 'Create a new project' : 'Add a project'}
showCloseButton
primaryButtonText={onCreateStep ? 'Create project' : 'Continue'}
onClickPrimaryButton={onCreateStep ? create : forward}
// "Back" rather than "Cancel" on step 2: it came from a question, so
// returning to it is more use than dismissing. The header's X still
// cancels, which is how the live dialog's two buttons stay two.
secondaryButtonText={onCreateStep ? 'Back' : 'Cancel'}
onClickSecondaryButton={onCreateStep ? () => setOnCreateStep(false) : close}
>
{/* The modal's content box centres its children, so this has to claim
the full width or every row sits in the middle. */}
<div style={{ width: '100%', display: 'grid', gap: 'var(--space-2)' }}>
{onCreateStep ? (
<>
<TextInput
id="project-name"
name="project-name"
label="Project name"
hint="Your project name is visible to your students."
fullWidth
value={name}
error={nameError}
onChange={(event) => {
setTyped(event.target.value)
setNameError(undefined)
}}
/>

<div style={{ width: '100%', display: 'grid', gap: 'var(--space-2)' }}>
{onCreateStep ? (
<>
<TextInput
id="project-name"
name="project-name"
label="Project name"
hint="Your project name is visible to your students."
fullWidth
value={name}
error={nameError}
onChange={(event) => {
setTyped(event.target.value)
setNameError(undefined)
}}
/>

<p
style={{
margin: 0,
fontWeight: 'var(--fw-bold)',
fontSize: 'var(--fs-1)',
lineHeight: 'var(--lh-15)',
}}
>
What kind of project do you want to make for your students?
</p>

<div style={{ display: 'grid', gap: 'var(--space-1)' }}>
{PROJECT_TYPES.map((option) => (
<OptionRow
key={option.id}
tone={option.tone}
title={option.id}
blurb={option.blurb}
selected={type === option.id}
onSelect={() => setType(option.id)}
/>
))}
</div>
</>
) : (
<>
<p
style={{
margin: 0,
fontWeight: 'var(--fw-bold)',
fontSize: 'var(--fs-1)',
lineHeight: 'var(--lh-15)',
}}
>
What kind of project do you want to add to {className}?
</p>

{nudge && (
<p
style={{
margin: 0,
fontWeight: 'var(--fw-bold)',
fontSize: 'var(--fs-1)',
lineHeight: 'var(--lh-15)',
}}
role="alert"
className="body small"
style={{ margin: 0, color: 'var(--alert-error)' }}
>
What kind of project do you want to make for your students?
Pick one of these to carry on.
</p>

<div style={{ display: 'grid', gap: 'var(--space-1)' }}>
{PROJECT_TYPES.map((option) => (
<OptionRow
key={option.id}
tone={option.tone}
title={option.id}
blurb={option.blurb}
selected={type === option.id}
onSelect={() => setType(option.id)}
/>
))}
</div>
</>
) : (
<>
<p
style={{
margin: 0,
fontWeight: 'var(--fw-bold)',
fontSize: 'var(--fs-1)',
lineHeight: 'var(--lh-15)',
}}
>
What kind of project do you want to add to {className}?
</p>

{nudge && (
<p
role="alert"
className="body small"
style={{ margin: 0, color: 'var(--alert-error)' }}
>
Pick one of these to carry on.
</p>
)}

<div style={{ display: 'grid', gap: 'var(--space-1)' }}>
{ROUTES.map((option) => (
<OptionRow
key={option.id}
tone={option.tone}
title={option.title}
blurb={option.blurb}
selected={choice === option.id}
onSelect={() => {
setChoice(option.id)
setNudge(false)
}}
/>
))}
</div>
</>
)}
</div>
</Modal>
</div>
)}

<div style={{ display: 'grid', gap: 'var(--space-1)' }}>
{ROUTES.map((option) => (
<OptionRow
key={option.id}
tone={option.tone}
title={option.title}
blurb={option.blurb}
selected={choice === option.id}
onSelect={() => {
setChoice(option.id)
setNudge(false)
}}
/>
))}
</div>
</>
)}
</div>
</Modal>
)
}

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading