Repository navigation
feat: redesign knobs — fonts (buttons/inputs), transparent layout, Statistic valueAs/countUp, Tier price detail + modern appearance, ReqoreTierGroup (3D stack on phones), Panel media, FeatureCard actions, Timeline states, SegmentedControl item props — 0.78.0 - #696
Merged
Merged
Conversation
…layout — 0.77.6 Buttons, inputs and textareas were left to the browser's user-agent stylesheet, which draws form controls in the platform's control face (`-webkit-small-control`: system-ui on macOS, the system sans on Linux), and ReqoreTag and the ReqoreKeyboardShortcut keys named `system-ui`. On a page set in its own typeface every button, field, tag and badge was in a different font from the text around it. They now declare `font-family: inherit`: the page's font, or the theme's. `theme.fontFamily` (the `'mono'` / `'system'` shorthands or any CSS font stack) is the font every Reqore surface renders in: the layout wrapper and the portal popovers, modals and drawers render into both set it, and everything inherits it. Unset (the default) Reqore names no font of its own. `effect.fontFamily` still picks a font for one element. ReqoreLayoutWrapper takes `transparent`: no surface, so a page that paints its own background behind the app shows through without a rectangle of another colour and a seam where it ends. ReqoreUIProvider passes props to the wrapper through `layoutWrapperProps` (`transparent`, `className`, `style`, `aria-*`, `data-*`); `options.withSidebar` still decides the direction. `TReqoreDataAttributes` lets a props bag written as an object carry `data-*` attributes. The font change is the only change without a new prop: every snapshot with a button, an input, a textarea, a tag or a shortcut key re-renders its text in the page's font (in the story suite, the Helvetica / Arial stack of .storybook/preview-body.html) instead of the control font. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
valueAs: the prefix, the value and the suffix are each a heading by
default (h1 – h4 from `size`), so a row of KPI tiles puts one to three
headings per tile into the page outline and a screen reader lists the
figures as section titles. `valueAs` ('h1'–'h6' | 'p' | 'div' | 'span')
writes the whole value as ONE element of that kind instead, drawn as
before: the same size from `size`, bold where the element is not a
heading, no margins. Without it nothing renders differently.
countUp (`boolean | { duration, from, threshold, format }`): the value
counts up once `threshold` (0.35) of it is on screen, from `from` (0)
over `duration` ms (1000), easing out, keeping its own format — decimals,
thousands separator and the text around the number ('$1.2M', '99.8%',
'1,234', '1.234,5') — or writing each frame with `format`. The last frame
is the value as given. A value that is not one number ('2–4', '24/7') and
every value under prefers-reduced-motion show at once. While it counts,
the moving number is aria-hidden and the value itself is read from a
visually hidden copy. The hook lives in hooks/useCountUp with its parser
and formatter.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The line under the price ("/ month") was fixed at small, uppercase and
the muted intent — about 1.6:1 on the default dark theme, and forced into
capitals. `priceDetailEffect` is spread over its effect defaults
(`{ uppercase: false }` keeps the text as written; a colour or opacity
makes it readable) and `priceDetailProps` over its paragraph's (another
intent or size, aria-*, data-*), the props' own effect merged under
priceDetailEffect. The paragraph carries `.reqore-tier-price-detail`.
Without them nothing renders differently.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`media` (an image URL, or any node: an img, a picture, a video, an
illustration) is drawn edge to edge across the panel, outside its
padding, in a frame whose outer corners take the panel's inner curve —
its radius, less the 1px border when it draws one — so the cover is
clipped to the panel's shape even with a sticky header, which makes the
panel overflow visible. `mediaPosition` puts it above the title bar (the
default; the sticky-header sentinel moves under it) or under the bottom
actions; `mediaAlt` is a URL's image text (default '': decorative);
`mediaAspectRatio` fixes the frame and makes the media cover it;
`mediaProps` reach the frame. Hidden while the panel is collapsed. A
panel with only `media` and `padded={false}` is a photo card. Without
`media` nothing renders differently.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`actions` (ReqoreButton props plus `label`) and `footer` (any node; text at the description's size) make a last row, pinned to the card's bottom edge, so in a row of stretched cards the buttons share one line whatever each description's length. The footer content comes first, in a ReqoreControlGroupItem so the row hands it none of its props, then the actions. Actions take the card's size, intent and customTheme unless they set their own, are disabled with the card and fluid only when they say so, and a click on one never reaches the card's own onClick (the rule ReqoreEntityRow and ReqoreSeverityRow follow). `footerProps` restyle the row. Without actions or a footer nothing renders differently. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`highlighted` marks the step that matters now: a halo round its marker in the item's colour (its intent, the timeline's, or the neutral line colour), a bolder title and aria-current="step". `pending` marks a running step: a spinning LoaderLine in the item's colour replaces its icon or dot, standing still under prefers-reduced-motion, and the item is aria-busy. Both work in either direction. Without them nothing renders differently. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An item's `props` reach its ReqoreButton: data-* (a data-track-click for analytics), aria-* (an aria-label for an icon-only segment), id, style, className (merged). They go under the control's own, so the segments stay the radio group the control runs — the selection handler, role, aria-checked, tabIndex, disabled and the selected look are the control's, and the item's own icon, rightIcon, badge, tooltip and effect win where set. A segment folded into the More menu passes them to its menu item. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ReqoreButton, ReqoreInput, ReqoreTextarea and ReqoreTag (and the shortcut keys) are in the page's font or theme.fontFamily; a new ReqoreUIProvider row covers theme.fontFamily and layoutWrapperProps, and ReqoreLayoutWrapper `transparent`. ReqoreStatistic valueAs / countUp, ReqoreTier priceDetailEffect / priceDetailProps, ReqorePanel media, ReqoreFeatureCard actions / footer, ReqoreTimeline highlighted / pending and ReqoreSegmentedControl per-item props are described where each component is. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
📦 Prerelease published for this PR: Install it in a consumer (updates yarn add @qoretechnologies/reqore@0.78.0-pr.696.g0578ab9Published under the |
qlip visual regression🔍 0 changed, 13 new of 1125 snapshots. |
A <textarea> gets `font-family: monospace` from the browser's own stylesheet, so ReqoreTextarea was monospace until it started following the page's font. For prose (a description, a message) the page's font is right; for data it is not. ReqoreExportModal's CSV / JSON / YAML export and ReqoreTree's raw value editor now ask for the generic `monospace` (`BROWSER_MONOSPACE_FONT`), the face they always had, so their rendering does not change. The font test now reproduces the browser's textarea rule too, and checks both data textareas. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Per the review of #696, the font fix stays for buttons and inputs only. ReqoreTag (and so every badge) and the ReqoreKeyboardShortcut keys name system-ui again, and ReqoreTextarea is left to the browser's own stylesheet again, which draws it in monospace: the IDE relies on that for the code and data it edits in textareas. All of them render exactly as on develop. theme.fontFamily stays. The layout wrapper and the portal set it, and the text, the buttons and the inputs inherit it. Tags, shortcut keys and textareas are excluded from it, as they are from the page's font, and the theme.ts and COMPONENTS.md docs say so. effect.fontFamily still picks a font for any one of them. With textareas monospace by default, ReqoreExportModal's export and ReqoreTree's raw value editor no longer need to ask for it, so they go back to develop's code and BROWSER_MONOSPACE_FONT is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nobs Brings in #697 (styling props no longer reach the DOM), released as 0.77.7 while this PR was open. The only conflict was the version: this PR moves from 0.77.6 to 0.77.8, the next one above develop's 0.77.7. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
develop released 0.77.7 (#697) while this PR was open, so these knobs and the button / input font fix ship in 0.77.8, not 0.77.6. The "new in" and "changed in" notes say so. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Since buttons and inputs take the font around them (0.77.8), the "+ Add item" / "+ Add property" buttons inside a value cell inherited ValueCell's MONO_FONT and rendered in monospace, and so did the type picker, the delete button and the edit and rename inputs of every nested level (Qlip #332: Collections/DataView · Editable Array Ops and · Editable Open Api Schema). Per the review of #696, buttons keep the normal font. ValueCell keeps its monospace, so its own text and line boxes, and with them the data, render exactly as before. The buttons and inputs in it get the theme's font when theme.fontFamily is set, and otherwise the browser's own control font (`font-family: revert`), which is what they rendered in on develop. The page's font cannot be named from inside a cell that has replaced it, and moving the monospace off the cell onto the value text would change the line boxes of every nested level. Checked locally against develop. With the page font set to Arial, the headless browser's control font and the face CI resolves the stories' font to, all 25 DataView stories are byte-identical to develop's. With the stories' Helvetica Neue only the root "+ Add property" differs, as it already does on this branch: that is the button font change itself. Unit tests cover a theme font and no theme font; Editable Array Ops asserts the two fonts in its play. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 7, 2026
…ners measured before paint The tier group needs what ButtonRail and useCountUp each kept to themselves: a test for "this key belongs to a text field" and a read of prefers-reduced-motion. Both are shared now (isTextEntry in helpers/utils, prefersReducedMotion / usePrefersReducedMotion in hooks/usePrefersReducedMotion, which also follows the preference while mounted), so the group does not grow a third copy of either. useNarrowContainer answered only from the ResizeObserver's first callback, which arrives after React has committed: a narrow container was painted once in its wide layout and then jumped. It now measures in a layout effect before the first paint and lets the observer keep the answer current. EntityRow and SeverityRow captures are byte-identical with and without the change (42 of 42); the group's stack relies on it to avoid a one-frame layout shift on phones. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…one line with its neighbours'
Filip, 7 Oct: "We need to improve the look and feel of the ReqoreTier,
I don't like them that much." The classic tier centres everything,
forces the name, the period and the button label into upper case,
draws the period as a faint 12px line under the price, scales and
animates the highlighted tier, and leaves each button wherever its
description ended, so a row of tiers has its buttons at different
heights.
appearance="modern" is opt-in; the default ('classic') renders exactly
as before (the four existing Tier snapshots are byte-identical). Modern,
after the pricing pages of Linear, Vercel, Supabase and Clerk:
left-aligned on the panel's flat surface with a hairline border; the
name a heading (h3, `labelSize` sets the level) with its badge beside
it as a soft pill; a large price (40px at normal) that is never a
heading, the period on its baseline, as written, in a muted colour kept
at 4.5:1; the description, muted, 4.5:1; the features as a list with
each icon on its feature's first line; and the button pinned to the
bottom edge, so stretched tiers share one button line. A highlighted
tier gets a border, a faint wash and a soft shadow in its intent, and a
filled button — no scaling, no animation. A sale strikes the original
price through (<del>). `labelEffect` / `descriptionEffect` style the
name and the description; `priceDetailEffect` / `priceDetailProps`
still apply. Every tier now carries `.reqore-tier`.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… on a narrow screen Filip, 7 Oct: "On mobile I would also like to improve the presentation, like 3D stacked cards, one is always at the top, and others are behind it on each side and you switch between them with swiping." ReqoreTierGroup lays out ReqoreTiers. Wide: a grid of equal-height columns. Narrow (the group's own width, 480px by default): either the same row wrapped (mobileLayout="columns", the default) or a stack (mobileLayout="stack"): one tier in front — the highlighted one at first — and its neighbours behind it on either side, scaled, turned a little and dimmed by brightness (opacity made dark cards vanish into a dark page). Swipes (touch or mouse drag; past 18% of the width or a quick flick), the arrow keys, Home and End, the previous / next buttons and a dot per tier change the tier in front; the switch is a CSS transition on a slightly overshooting curve, so captures with animations disabled show its end state. Under prefers-reduced-motion it switches at once, flat. Clamped at the ends by default (the order of plans means something); `loop` wraps. The stack is a labelled carousel region (focusable, focus ring), each tier a slide; tiers behind the front one are inert; a polite live line names the new front tier; focus that would be lost moves to the carousel; the stack clips at its sides and never widens the page. The group hands `appearance` and `size` to tiers without their own and cascades its customTheme. Index and gesture arithmetic are pure, exported and unit tested. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s 0.78.0 A new component makes this PR a minor release: 0.77.8 → 0.78.0 (0.77.8 was never published; develop is at 0.77.7 and the other open PRs at 0.77.9 / 0.77.10). The knobs this PR documented as "new in 0.77.8" now say 0.78.0. COMPONENTS.md gains the modern Tier appearance and a ReqoreTierGroup entry, and records that the classic tier's price is a heading too — a ReqoreH1 its control group sizes into an <h3>. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ons say near-white Narrow Columns asked for a 360×1900 viewport. That is taller than the 1080px browser window, so the test runner scaled the frame down and Qlip captured it at 205×1080 (denied on build #336). It now uses 360×1080, the third plan running on below the screen, and its description says so. Modern Light and Stack Light described the cards as white. They are the panel's own near-white surface. The reduced-motion story's sentence now reads clearly. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
davidnich
added a commit
that referenced
this pull request
Oct 7, 2026
…s a focus list again — 0.78.1 Foxhoundn's review of #708: the check for a field focused as it mounts ran on every re-run of the listener effect, and the effect re-runs whenever the list opens or closes (it depends on `open`, which depends on `isOpen`). Closing the list with the cursor still in the field - Escape, or a click on it with closeOnTargetClick - re-ran it, found the field focused, and reopened the list at once. The check is made once per trigger, remembered in a ref, as the listener is first attached. Test: a list closed with Escape stays closed while the field keeps the focus (fails without the change). 0.78.1: #696 goes in first as 0.78.0.
davidnich
added a commit
that referenced
this pull request
Oct 7, 2026
…used # Conflicts: # package.json
davidnich
added a commit
that referenced
this pull request
Oct 7, 2026
…description takes block content #696 added the panel's media props (media, mediaAlt, mediaPosition, mediaAspectRatio, mediaProps) and the modern Tier appearance. The panel's compiler-checked style list caught the props: they are now in it, so they do not reach a component the panel is rendered as. The modern tier drew its description in a ReqoreP <p>; it is a div like the classic tier's, with its effect memoized for the memoized paragraph.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Nine knobs the qorus.cloud redesign needs, in one PR (the redesign spec's R1–R9). The landing page uses an interim for each today (marked
TODO(reqore)there); these replace them. Filip's rule for the site: "If a look needs a knob Reqore lacks, add the knob upstream instead of a local component."Every knob is opt-in and renders nothing differently without its prop, except R1, which is a font bug fix: buttons and inputs inherit the page font; tags and textareas are unchanged (see "Snapshots" below).
Changes after review (7 Oct)
Per Filip's review ("OK without the tag change please"), R1 no longer touches tags or textareas:
ReqoreTag(and every badge) and theReqoreKeyboardShortcutkeys keep their hard-codedsystem-ui, exactly as on develop.ReqoreTextareastays monospace by default, as on develop (the IDE relies on it). The "no longer monospace" behaviour change and its note are gone.ReqoreExportModalandReqoreTreeare back to develop's code, since the default already gives them monospace, andBROWSER_MONOSPACE_FONTis removed.theme.fontFamily, which the layout wrapper and the portal set. Tags, shortcut keys and textareas are excluded from it, andtheme.ts/COMPONENTS.mdsay so.Develop released 0.77.7 (#697) while this PR was open. It is merged in. With the tier work below (a new component), this PR ships as 0.78.0.
Tiers: a modern appearance, and a 3D stack on phones (7 Oct)
Filip: "We need to improve the look and feel of the ReqoreTier, I don't like them that much. On mobile I would also like to improve the presentation, like 3D stacked cards, one is always at the top, and others are behind it on each side and you switch between them with swiping."
Both are opt-in. A tier without
appearancerenders exactly as before: the four existing Tier snapshots are byte-identical (md5) to their captures before this change, and the classic code path is untouched apart from areqore-tierclass on its root.What was weak in the classic tier
ReqoreH1its control group sizes into an<h3>), one per plan.ReqoreTierappearance="modern"Modelled on the pricing pages of Linear, Vercel, Supabase and Clerk:
radiusSizebig, padding fromsize(24px at normal).<h3>;labelSizesets the level) with its badge beside it as a soft pill. The price is 40px (32 / 48 at small / big) and never a heading. The period sits on its baseline, as written, in a muted colour kept at 4.5:1, and wraps under the price when there is no room. A sale strikes the original price through (<del>).<ul>), each icon held on its feature's first line.ReqoreTierGroup, or in any grid that stretches its items, such asReqoreColumns.infoby default), and a filled button. It is not scaled and not animated. The other buttons are neutral; an active tier's is a read-only success button with a check.labelEffect/descriptionEffectstyle the name and the description;priceDetailEffect/priceDetailProps,contentEffectandactionButtonPropsstill apply over the defaults.ReqoreTierGroup(new component)minColumnWidth240px,maxColumnWidth1fr,gapSizebig).mobileBreakpoint, 480px): the same row wrapped to one column (mobileLayout="columns", the default), or a 3D stack (mobileLayout="stack"). The stack shows one tier in front (the highlighted one at first) and its neighbours behind it on either side, scaled to 0.9, turned 12° and dimmed by brightness, peeking 20px past its edges. Dimming uses brightness rather than opacity because faded dark cards vanish into a dark page.prefers-reduced-motion: the tiers switch at once, do not follow the finger and are not turned.loopwraps round.overflow-x: clip) and handles only horizontal swipes (touch-action: pan-y). The stories assert no overflow at 360px.stackLabel, "Plans"), focusable with a focus ring. Each tier is a slide named "Pro, 2 of 3" (stackItemLabel), and the tiers behind the front areinert. A polite live line names the new front tier. Focus that would be lost moves to the carousel. Each dot is named after its tier and the front one hasaria-current.appearanceandsizeto tiers that do not set their own, and cascades itscustomTheme.intentcolours the front dot, the focus ring and the buttons.ReqoreTierappearance'classic' | 'modern''classic'ReqoreTierGroupappearanceTReqoreTierAppearancemobileLayout'columns' | 'stack''columns'mobileBreakpointnumber(px, the group's own width)480activeIndex/defaultActiveIndexnumber0onActiveIndexChange(index: number) => voidloopbooleanfalseminColumnWidth/maxColumnWidth/gapSizestring/string/TSizes'240px'/'1fr'/'big'stackLabel/previousLabel/nextLabelstring'Plans'/'Previous plan'/'Next plan'stackItemLabel(name, index, count) => string'Pro, 2 of 3'size,intent,customTheme,inheritCustomTheme,tooltip,ref,divattributesThe arithmetic is pure and exported:
normalizeTierIndex,getTierStackOffset,getInitialTierIndex,getTierSwipeStep,getTierStackItemStyle, andgetTierColorsfor the modern tier.Supporting changes
useNarrowContainernow measures before the first paint (a layout effect), so a narrow container is never painted once in its wide layout first. EntityRow and SeverityRow captures are byte-identical with and without the change (42 of 42).isTextEntry(from ButtonRail) andprefersReducedMotion/usePrefersReducedMotion(from useCountUp, and now kept current) are shared helpers rather than private copies.Stories (all new; each has a description and a play test)
ReqoreColumns: equal heights, one button line, the period on the baseline, a highlighted Pro<h2>name with a detail and an orange badge, an excluded feature and a right iconloop: Enterprise behind Starter on the leftcustomTheme,intentandsizereaching its tiers and controlsmobileLayout: one columnThe play tests assert: equal heights and one button line (±1px); the period on the price's line or wrapped to the next; no tier scaled; the name a heading and no
<h1>; muted lines at 4.5:1 or better; the front tier and the dots after swipes, keys, buttons and dots; clamping and wrapping; inert tiers; no transitions under reduced motion; no horizontal overflow at 360px.Tests
tier.test.tsx(4 → 18: the modern structure, heading level, period, sale, currency, features, active, highlight, effects, and contrast on dark and light themes);tierGroup.test.tsx(new, 23: index arithmetic, swipe decisions, stack geometry, row / stack, the breakpoint, keyboard, loop, buttons and dots, a controlled index, translated labels, reduced motion,customTheme, tiers arriving late, the first-paint measurement);hooks/usePrefersReducedMotion.test.tsx(new, 3).yarn precheck: 1358 tests, green.Snapshots (tiers)
Qlip build #337 (head
0578ab9): 0 changed, 13 new, 1112 unchanged. The four classic Tier stories (Default, Group, Price Detail Effect and its Light variant) are byte-identical to their baselines: the same sha256 blob, 0 diff pixels. The 13 new stories are the ones in the table above and are left for Filip; nothing was accepted. On #336, Narrow Columns was captured at 205×1080 (a 1900px-tall viewport, scaled down to the window) and denied. #337 captures it at 360×1080. Stack Keyboard varies by 2 anti-aliased pixels on its focus ring's corner between runs.Adopting it on the landing page (once published)
The prerelease
0.78.0-pr.696.g0578ab9is on npm for trying this locally (never committed to a consumer).This drops the interims: the period goes back to
priceDetailinstead of the description fragment, and thecontentEffect={{ gradient: undefined }},labelEffectandminimal: falseoverrides are no longer needed.The knobs
ReqoreButton,ReqoreInputfont-family: inherit. Buttons and inputs were left to the browser, which draws form controls in its control face (-webkit-small-control: system-ui on macOS, the system sans on Linux). They now use the page's font, andeffect.fontFamilystill picks one. Tags and textareas are unchanged:ReqoreTag(badges included) and theReqoreKeyboardShortcutkeys keepsystem-ui, andReqoreTextareakeeps the browser'smonospace.ReqoreUIProvidertheme.fontFamily'mono' | 'system' | stringsystem-ui/monospace). Unset (default): the wrapper and the portal name no font.ReqoreStatisticvalueAs'h1' … 'h6' | 'p' | 'div' | 'span'size, bold, no margins).ReqoreUIProviderlayoutWrapperPropsOmit<IReqoreLayoutWrapperProps, 'children' | 'withSidebar'> & TReqoreDataAttributes.reqore-layout-wrapper:transparent,className(merged),style,aria-*,data-*.ReqoreLayoutWrappertransparentbooleanReqoreTierpriceDetailEffectIReqoreEffect{ uppercase: false }keeps the case; colour / opacity make it readable).ReqoreTierpriceDetailPropsPartial<IReqoreParagraphProps> & TReqoreDataAttributesintent: 'muted',size: 'small'; itseffectmerges underpriceDetailEffect.ReqorePanelmediastring | ReactNode<img>. Hidden while collapsed.ReqorePanelmediaPosition'top' | 'bottom'(default'top')ReqorePanelmediaAltstring(default'')ReqorePanelmediaAspectRatiostring | numberaspect-ratio); the media covers it.ReqorePanelmediaPropsHTMLAttributes<HTMLDivElement> & TReqoreDataAttributesReqoreFeatureCardactionsIReqoreFeatureCardAction[](Omit<IReqoreButtonProps, 'children'> & { label?: string })onClick.ReqoreFeatureCardfooterReactNodeReqoreFeatureCardfooterPropsPartial<IReqoreControlGroupProps> & TReqoreDataAttributeshorizontalAlign,vertical,gapSize, …).ReqoreTimelineitemhighlightedbooleanaria-current="step".ReqoreTimelineitempendingbooleanLoaderLinein place of the icon or dot (still under reduced motion),aria-busy.ReqoreStatisticcountUpboolean | { duration?: number; from?: number; threshold?: number; format?: (n: number) => string }threshold(0.35) of the value is in view, overduration(1000 ms), keeping the value's own format; ends on the value as given. Not-one-number values and reduced motion: shown at once. The moving number isaria-hidden; the value is read instead.ReqoreSegmentedControlitempropsTReqoreSegmentedControlItemProps(ReqoreButtonprops minusonClick/role/tabIndex/aria-checked/label/children, plusdata-*)data-*,aria-*,id,style,classNamefor one segment's button; the control keeps the radio-group props. Folded segments pass them to their menu item.New shared type:
TReqoreDataAttributes(types/global), an index signature fordata-*keys, so a props bag written as an object can carrydata-*attributes. New hook:hooks/useCountUp(useCountUp,parseCountUpValue,formatCountUpValue), internal.Snapshots (R1)
The font fix is the only change without a new prop, so it is the only one that can touch existing snapshots. Button and input text is now in the page's font, which in the story suite is the Helvetica Neue / Helvetica / Arial stack from
.storybook/preview-body.html. In CI's Chromium on Linux the browser's control font resolves to the same face, so button and input labels barely move there. Tag, badge, shortcut-key and textarea snapshots are unchanged against develop. The other eight knobs add stories only.Qlip build #332 (head
65842e7): 0 changed, 20 new, 1092 unchanged.ReqoreModals to be managed via newaddModal | removeModal | updateModalcontext method #328 and the 1 on Fix message / notification transparency #327 were reset after the review. They had become this branch's baselines; with the reset, those stories compare against develop again.One real change Qlip did not surface. Its perceptual-hash shortcut auto-passed it, so I compared every image with develop's own capture to find it. In ReqoreDataView, the "+ Add item" / "+ Add property" buttons inside a value cell now inherit the cell's
MONO_FONTand render in monospace (before, the browser's control font overrode it). It shows in Collections/Dataview · Editable Array Ops and · Editable Open Api Schema, and there are comments on both snapshots. This needs a decision: keep it (buttons follow the surrounding font), or scope DataView's monospace to the value text. Everything else that differed was flaky (image loads, a per-run stack trace) or sub-threshold anti-aliasing.Stories (all new; each has a description and a play test)
system-ui, and the textarea staysmonospacetheme.fontFamily: 'mono'. The theme font reaches the text, input and buttons, not the tags, the key or the textarealayoutWrapperProps.transparent, dark and light pagesp,div,h3(1 heading)$48,200,99.9+%,1.2Mcounting up;2–4shown at once0until scrolled to, then12,345data-track-*on billing-cycle segments;aria-labelon icon-only segmentsTests
New tests:
fontFamily.test.tsxreproduces the browser's control-font and textarea-monospace rules, so it fails without the fix. It checks both sides: buttons and inputs follow the page font, the body font andtheme.fontFamily, while tags and shortcut keys staysystem-uiand textareas staymonospaceunder all three.statisticValue.test.tsx,hooks/useCountUp.test.ts,tier.test.tsx,panelMedia.test.tsx.Additions to
layout,FeatureCard,TimelineandsegmentedControl.tag.test.tsxis back to develop's version, which assertssystem-ui.yarn precheckis green after merging develop: 1316 tests. The UI Provider, Tag, TextArea and KeyboardShortcut story files run locally and pass (46 stories).Not changed (noted for later)
ReqoreTierstill renders the price as a heading: aReqoreH1that its control group sizes into an<h3>(this note said<h1>before; the tests now show which), one per plan. The same class of issue as R2.appearance="modern"(below) fixes it for tiers that opt in: the name is the heading and the price is a paragraph. The classic look is unchanged.ReqoreProviderreportsisMobile: falseunderNODE_ENV=test, so no story can show a viewport-width branch (e.g. the Timeline's horizontal → vertical fallback); the Timeline phone story shows both directions explicitly instead.Version
0.77.7 → 0.78.0. This is a minor release because of a new component,
ReqoreTierGroup; the rest are new props on existing components and a bug fix. The branch was at 0.77.8, and before that 0.77.6, and neither was ever published. The other open PRs are at 0.77.9 (#708) and 0.77.10 (#709). The notes inCOMPONENTS.mdthat said "new in 0.77.8" now say 0.78.0.🤖 Generated with Claude Code