Skip to content

Product updates

Screens that show where the product is heading: a versioned changelog and a public roadmap.

Installation & usage

npx @youj/cli add content-roadmap

Also installs app-page, async-button, avatar, badge, button, collapse, counter, dialog, empty, field, icon-arrow-up, icon-calendar, icon-circle-dashed, icon-engine, icon-filter, icon-hammer, icon-lightbulb, icon-message, icon-plus, icon-rocket, icon-trending-up, input, presence-list, reveal, select, sheet, tabs, textarea, timeline, toast, toggle, toggle-group, typography, use-announcer, use-controllable-state, youj-core, youj-presets, youj-ui-core.

The CLI copies the block to blocks/content/roadmap.tsx with every component it uses, so it’s yours to edit.

Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:

roadmap-view.tsx
'use client'

import { Roadmap, type RoadmapProps } from '@/blocks/content/roadmap'

export function RoadmapView({ requests, view, categories }: Pick<RoadmapProps, 'requests' | 'view' | 'categories'>) {
  return (
    <Roadmap
      requests={requests}
      view={view}
      categories={categories}
      copy={{ brandSection: 'Roadmap' }}
      onViewChange={(view) => {
        // your code
      }}
      onVote={(request, voted) => {
        // your code
      }}
      onSubmit={async (draft) => {
        // await your API here; the block shows progress until it settles
      }}
    />
  )
}

Reference

Props17 props, 3 types

Props

Roadmap props
PropType
themeThemeInput

A theme to force on the block. Default: none, so it inherits the app's (YoujProvider or a ThemeScope around it).

–
embeddedboolean

A page in your app's frame: the shared page header (AppPage) and the frame's gutter, with no top bar or eyebrow of its own (Submit a request moves to the header's actions).

default true

true
requestsreadonly RoadmapRequest[]

The requests to show. Pass [] for the empty board.

default Relay's board

Relay's board
viewView
'requests''roadmap'

The view, controlled: pair it with onViewChange.

–
defaultViewView
'requests''roadmap'

The view it opens on, when the page owns it.

default 'requests'

'requests'
onViewChange(view: View) => void–
categoriesRecord<string, string>

The areas, key to name; a request's category is a key.

default Relay's five

Relay's five
defaultVotedstring[]

The requests the reader has already voted for. Default: none.

–
onVote(request: RoadmapRequest, voted: boolean) => void

Saves a vote (true) or its removal (false).

–
onSubmit(draft: RoadmapDraft) => Promise<unknown> | unknown

Posts a new request; reject to keep the dialog open. Default: a short demo wait. Without it, a toast confirms the post.

–
onComment(request: RoadmapRequest, body: string) => Promise<unknown> | unknown

Posts a comment; reject to keep the draft.

default a short demo wait

a short demo wait
brand{ name: string; logo?: ReactNode }

The product in the top bar: { name, logo? }.

default Relay

Relay
changelogHrefstring | null

The changelog link in the top bar; null hides it.

default '#changelog'

'#changelog'
viewerstring

The signed-in reader's name, on what they post.

default 'You'

'You'
todaystring

Today, as YYYY-MM-DD: new posts' date, and which dates drop their year.

default the demo's day

the demo's day
localestring

A BCP 47 locale for dates and counts. Default: the app's (YoujProvider's locale), else en-US.

–
copyPartial<RoadmapCopy>

Any of the board's strings, to rewrite or translate.

–

RoadmapComment

RoadmapComment props
PropType
idRequiredstring–
authorRequiredstring–
teamboolean

A Relay team member: their comments carry a badge.

–
bodyRequiredstring–
dateRequiredstring–

RoadmapDraft

RoadmapDraft props
PropType
titleRequiredstring–
bodyRequiredstring–
categoryRequiredCategory–

RoadmapRequest

RoadmapRequest props
PropType
idRequiredstring–
titleRequiredstring–
bodyRequiredstring–
categoryRequiredCategory–
statusRequiredStatus
'review''planned''progress''shipped'
–
votesRequirednumber

Votes, not counting yours.

–
recentRequirednumber

Votes in the last seven days; ranks Trending.

–
authorRequiredstring–
historyRequired{ date: string; by: string; note?: string; }[]

One entry per status reached, in STATUS_ORDER: when, who moved it, and why.

–
commentsRequiredComment[]–
targetstring

Planned and in-progress work: the quarter it's aimed at. Shipped: the release.

–
Strings63 keys for copy

Strings

copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.

brandSectionchangelogeyebrowtitledescriptionstatssubmitviewrequestsTabroadmapTabstatusFilterareaFiltersortallStatusesallAreassortsstatusvotesupvoteupvotedunvotedemptyTitleemptyDescriptionnoMatchesTitlenoMatchesclearFilterspostedTitlepostedDescriptionnoDetailslistcommentsthisWeekboardEmptysubmittedmovedToteamreleasedaimingrequestedByfollowingfollowhistorycommentsTitlenoCommentscommentOnyourCommentcommentPlaceholderpostingAspostingpostedcommentdialogDescriptiontitleLabeltitlePlaceholdertitleTooShortsimilarFoundsimilarHeadingdetailsdetailsPlaceholderdetailsHintareacancelpostRequest
Built from21 components
Accessibilitylandmarks, dialogs, forms

Accessibility

Changelog is a main with one h1 and a status region for the subscribe result; the subscribe form opens in a popover. Roadmap is a main under a header with tabs that follow the kit’s Tabs keyboard pattern. Each vote button is labelled with the request it upvotes, the request sheet and the submit dialog trap focus and close with Escape, and a submitted request is announced in a status region. Links and buttons are real a and button elements with the kit’s focus ring.