Skip to main content

ripplearc_coreui 0.22.0 copy "ripplearc_coreui: ^0.22.0" to clipboard
ripplearc_coreui: ^0.22.0 copied to clipboard

A Flutter design system package with design tokens and basic components.

Changelog #

0.22.0 Stable test keys on calculator keys, strip chips and dependent-key pills #

✨ Features #

  • CoreKeyboard: every key carries a stable Key for Patrol and widget tests. Digits, operators, units and controls take calc_key_<enum name> (calc_key_seven, calc_key_add, calc_key_feet, calc_key_clearAll) from the new DigitTypeX.testKey, OperatorTypeX.testKey, UnitTypeX.testKey and ControlActionX.testKey; the result button carries CoreResultButton.testKey (calc_key_result). The key sits on the rendered button inside each Core*Button, so a button built on its own carries it too (CA-1044)
  • KeyType.testKey (optional) and KeyType.resolvedTestKey: a function-key tile carries testKey, or calc_key_<id> (calc_key_Length) — on the strip and in the "View all" sheet alike
  • SuggestionData.testKey (optional): a strip chip carries it, or the row's default — CoreSuggestionArea.chipTestKey(index) (calc_strip_chip_0) on the primary row and the toggle layout's single row, CoreSuggestionArea.conversionChipTestKey(index) (calc_strip_conversion_0) on the two-row layout's conversions row, so the rows never share a key. Element identity is unchanged: the label / value / unit / kind / index key that keeps a chip's tap highlight bound to its data now sits on a KeyedSubtree around the chip
  • CoreDependentKeyData.testKey (optional): a pill carries it, or CoreDisplayArea.dependentKeyTestKey(index) (calc_dep_pill_0)
  • Display area showcase: the Rate, Waste, O.C and Shown-as pills carry calc_dep_pill_rate / _waste / _oc / _shown_as

No behaviour or layout change: keys only.

🧪 Tests #

  • Keyboard: every digit, operator, control, unit (imperial and metric) and the result button is found by its key, a function key by resolvedTestKey with testKey winning over the id default, and a tap through the key fires the callback; a tile on its own and the "View all" sheet's tiles carry the same keys; the enum keys and resolvedTestKey are unit-tested
  • Suggestion area: chips take the index default per row, the two-row conversions row its own prefix and the toggle layout's conversions list the single-row prefix; testKey overrides; a tap through the key accepts the suggestion; duplicates still get distinct keys
  • Display area: pills take the index default; testKey overrides and a tap through it fires onPressed
  • Goldens unchanged

0.21.0 Calculator a11y: live regions and dependent-key pill hints #

✨ Features #

  • CoreSuggestionArea: the area is a live region. Its semantics node is labelled with the suggestions on screen — the active list in toggle, both rows in twoRows minus the conversions row while secondRowHidden — so a screen reader announces a new rung or a fresh set of conversions without moving focus; each chip keeps its own node inside the region. suggestionsSemanticsLabelBuilder(List<SuggestionData>) (optional) builds that text; CoreSuggestionArea.defaultSuggestionsSemanticsLabel joins each suggestion's semanticsLabel — or label, value and unit — with commas (Area: 220 ft², Cost: $84.25). The placeholder is a live region too, so an emptied strip is heard as well (CA-1043)
  • CoreDisplayArea: the value text is a live region — a computed result, a typed value or the errorTitle is announced when it changes. CoreDependentKeyData.semanticsHint is announced after a pill's label and says what a tap does (Edits the rate, Changes how the pitch is shown), the spoken counterpart of the trailing ✎ / ⇄ icon; no default, in line with the row holding no strings of its own
  • CoreButton: semanticsHint passes through to the button's semantics node
  • Display area showcase: the Rate, Waste, O.C and Shown-as pills carry hints

🧪 Tests #

  • Suggestion area a11y: the region carries the live-region flag and the joined chip text; the text follows a suggestion change, the toggle's active list and secondRowHidden; the builder overrides it; the placeholder is a live region; the existing guideline tests run against the new tree
  • Display area a11y: the value node is a live region whose label follows the value, and the error title, on the same node; pills announce their hint
  • Button: semanticsHint reaches the semantics node

0.20.0 CoreKeyboard group swipe and CoreFunctionKeyBottomSheet reorder callback #

✨ Features #

  • CoreKeyboard: a horizontal swipe on the function-key strip selects the previous (swipe right) or next (swipe left) group in allGroups through the existing onGroupSelected, wrapping at either end. One gesture selects exactly one group; a drag shorter than CoreKeyboard.groupSwipeThreshold (space16, 64 dp) is ignored, and a tap on a key never counts as a swipe — a swipe that starts on a key cancels that key's tap instead. The "View all" sheet stays the non-gesture equivalent (CA-1038)
  • CoreKeyboard: onGroupsReordered and reorderSemanticsLabelBuilder pass through to the built-in "View all" sheet. The keyboard keeps a rebuild hook rather than an order, so when the consumer applies a reorder — as a new allGroups list or in place — the sheet that is still open re-renders in the new order. Both indices reported by the callback are in range for allGroups
  • CoreFunctionKeyBottomSheet: onGroupsReordered(int oldIndex, int newIndex) reports a drag once the group is dropped; newIndex is already the final index, so groups.insert(newIndex, groups.removeAt(oldIndex)) applies it. The sheet no longer keeps a private copy of the order — it renders groups as given, so the stored preference is the single source of truth. Drag handles render only when the callback is set, so a read-only sheet offers no gesture it cannot honour
  • CoreFunctionKeyBottomSheet: reorderSemanticsLabelBuilder(groupLabel) replaces the hard-coded drag-handle label; defaultReorderSemanticsLabel keeps the previous English string when the builder is omitted
  • Showcases: the keyboard sheet applies reorders to its group list; the display-area and suggestion-area calculators now track the swiped group and apply reorders, so the strip follows the gesture

⚠️ Behaviour change #

  • CoreFunctionKeyBottomSheet without onGroupsReordered shows no drag handles and cannot be reordered. Previously the handles were always shown and dragging reordered a private copy that no consumer could read back — a reorder that was lost on the next rebuild. Wire the callback to keep the handles

🧪 Tests #

  • Keyboard: swipe left / right select the neighbouring group exactly once, wrap at both ends, a key tap never swipes, a swipe that starts on a key cancels the tap and the key's action, a sub-threshold drag is ignored, a single group ignores swipes; the "View all" sheet forwards the reorder and the handle label and re-renders in the consumer's new order while open
  • Sheet: the drop reports (oldIndex, finalIndex) and the rendered order stays the consumer's; a host that applies the callback renders the new order; no handles without the callback; the handle label defaults to the previous string and follows the builder
  • Goldens: the sheet golden wires the callback so the handles stay and the image is byte-identical; keyboard goldens unchanged

0.19.0 CoreDisplayArea dependent-key row #

✨ Features #

  • CoreDisplayArea: dependentKeys: List<CoreDependentKeyData> renders a row of pills under the value instead of the single dependentKeyLabel / dependentKeyValue pair, because an answer can depend on more than one assumption at once — a cost shows Rate and Waste together (CA-1037)
    • CoreDependentKeyData { label, value, kind, onPressed, semanticsLabel } with CoreDependentKeyKind { editable, toggle, offer }: editable opens an editor for an assumption and carries the ✎ icon; toggle respells the value on screen (Shown as: in/12in) and carries the new ⇄ CoreIcons.swapHorizontal icon; offer is a one-time rewrite (Re-input 38.30° as 38°30′) with no icon and a space instead of a colon, so it reads as a sentence
    • The row is end-aligned and scrolls horizontally with the trailing pill anchored in view when the pills outgrow the width; pills are separated by space2
    • Each pill is a CoreButton exposing button: true with its label (or the consumer's semanticsLabel), drawn with a 1 px lineMid hairline rather than the secondary button's 2 px outline, as in the Figma Dependent Key Chip spec (66225:151236); the row holds no default strings, in line with the 0.15.0 localization rule
    • resolvedDependentKeys (@visibleForTesting) exposes the list build renders, so tests assert the adapter without reaching into the widget tree
  • CoreIcons.swapHorizontal (Icons.swap_horiz) added for the toggle pill
  • CoreButton: optional borderColor and borderWidth override the variant's border in every state (null keeps the variant's own), plus CoreButton.hairlineBorderWidth (1 px) for chip-style edges such as the dependent-key pill
  • Display area showcase: a Cost key prices the current Area and shows Rate + Waste editable pills that recompute the cost on tap; the Pitch result carries a Shown as toggle that cycles in/12in → degrees → grade

🔧 Fixes #

  • CoreButton: a raised secondary button (variant: secondary with shadows) painted its card buttonInverse — white — in the dark theme too, so the dependent-key pill's textBody / textDark text was near-invisible on it (contrast 1.47:1). In dark mode the card now takes the same elevated backgroundGrayLight surface the social variant already uses; the light theme is untouched. Surfaced by the new pill contrast test; the old single pill had the same defect

🔧 Deprecations #

  • CoreDisplayArea: dependentKeyLabel, dependentKeyValue and onPressedDependentKey are deprecated. They still render — as one editable pill appended after dependentKeys — so existing callers get a deprecation warning only; the adapter is removed in the next minor release

🧪 Tests #

  • Widget tests: the row renders every pill with its label and value; kind-specific trailing icons (✎ / ⇄ / none) and offer punctuation; per-pill onPressed; button semantics with the default and the overridden label; a disabled pill without onPressed; the row anchors its trailing pill in view and scrolls the leading pills in; the adapter appends the legacy pill and resolvedDependentKeys reflects both sources; the value section shows for pills alone
  • A11y: pills meet label and contrast guidelines in light and dark; each kind is announced with its own label
  • Goldens: display_area_dependent_keys_{light,dark}.png (cost result with Rate + Waste, a Shown as toggle and an offer overflowing the width), viewport scoped to the collapsed display area. The existing dependent-key goldens (more_than_two_rows, expansion stages) migrated to dependentKeys and are byte-identical

0.18.0 CoreSuggestionArea two-row layout #

✨ Features #

  • CoreSuggestionArea: new layout parameter — CoreSuggestionLayout { toggle, twoRows }, default toggle so existing callers compile and render unchanged (CA-1035)
    • twoRows shows both lists at once: aiSuggestions on row 1 (the rung that fired), conversionSuggestions on row 2, no AI / conversion toggle. Each row keeps its own +N overflow chip and expands on its own; a single non-empty list renders as a single row rather than an empty shelf. This is the calculator's default (prototype strip: 'tworow'); the toggle layout survives behind the app's "Strip layout" preference
    • secondRowHidden (default false) folds the conversions row away so the display area's dependent-key band can take the space. The fold is an AnimatedSize over the new public CoreSuggestionArea.animationDuration (300 ms — the display area's stage timing, so the two surfaces move together); a hidden row is collapsed if it was expanded, and with only conversions present the placeholder shows. Ignored in toggle
    • onExpandedChanged reports true while either row is expanded and false once both are collapsed; a suggestion or layout change collapses both rows, as before
    • conversionsExpandToggleSemanticsLabelBuilder / conversionsCollapseToggleSemanticsLabel (optional) give the conversions row its own overflow semantics labels so a screen-reader user can tell the two rows' +N controls apart; they fall back to the shared labels
    • the conversions row is visibly secondary, as in the calculator prototype's two-row strip: a leading tag (CoreIcons.ruler + conversionsRowTagLabel, default 'as', decorative) says "conversion" once, and every chip on the row is a value-only CoreChipSize.mini — as 264in 7.33yd under Area: 410.67ft² Cost: $84.25. The row is a semantics container labelled conversionsRowSemanticsLabel (default 'Convert to other units'); both strings are overridable per locale. The toggle layout keeps full-size labelled conversion chips
  • CoreChip: gains CoreChipSize.mini — the large chip's page-background surface and lineMid outline at the medium chip's padding, no shadow, value and unit in bodyMediumSemiBold instead of the heavy unit. CoreChipTheme.onPageSurface(size) names the large/mini surface rule, and the chip's text styles now resolve through CoreChipTheme.labelStyle / valueStyle / unitStyle (unitFontWeight = w800) so a size can vary them
  • Suggestion area showcase gains a "Two rows" switch and a "Hide conversions row" switch above the strip; two rows is the showcase default. Chip showcase gains a mini chips row

🧪 Tests #

  • Widget tests: default layout is toggle; two rows render both lists with no toggle and the conversions row below the primary row; single-list two-row renders one row; secondRowHidden folds the row away and back, animates over the shared duration rather than snapping, shows the placeholder when only conversions exist, and is ignored in toggle; independent per-row overflow with onExpandedChanged aggregation; a suggestion change or a runtime layout change collapses both rows; hiding the conversions row while it is expanded reports collapsed and brings it back collapsed, and reports nothing while the primary row is still open; the conversions row falls back to the shared overflow labels
  • Widget tests: the conversions row renders one tag then value-only mini chips below the full-size row, conversionsRowTagLabel is configurable, and the toggle layout keeps full-size labelled conversion chips
  • A11y: both rows meet tap-target, label and contrast guidelines in light and dark; no toggle is announced in two-row mode; each row announces its own overflow controls; the conversions row announces its group label (configurable) and not the decorative tag, and a value-only chip still announces its value and unit
  • CoreChip: mini renders at the medium height; theme tests for the mini padding, surface, outline, focus fill and semibold value/unit against the heavy unit of the other sizes, in light and dark
  • Goldens: suggestion_area_two_rows_{light,dark}.png (deterministic + predictive over an as tag and three mini conversions), viewport scoped to the two rows; core_chip_outline_{light,dark}.png gains a solid mini chip; every other suggestion-area golden verified byte-identical

0.17.0 CoreSuggestionArea suggestion kinds, bind styling, localisable toggle label #

⚠️ Breaking changes #

  • CoreSuggestionArea: toggleSemanticsLabel is now a required parameter. The AI / conversion toggle's screen-reader label ('Toggle suggestion mode') was the last hard-coded semantics string in suggestion_area/; like the sibling expandToggleSemanticsLabelBuilder and collapseToggleSemanticsLabel it has no English default, so a user-facing string cannot reach the screen without passing through the consuming app's localization layer (CA-1036)
    • Migration: toggleSemanticsLabel: AppLocalizations.of(context).toggleSuggestionMode

✨ Features #

  • SuggestionData: gains kind — SuggestionKind { deterministic, predictive, bind, conversion, memory }, default predictive — so the app can attach the right accept behaviour without re-deriving it from label text, and an optional semanticsLabel that overrides the chip's announced text ('12.57yd²' → "Convert to 12.57 square yards"). A suggestion update that only swaps a kind or semanticsLabel now also collapses an expanded area (CA-1036)
  • CoreSuggestionArea: a SuggestionKind.bind offer renders with the dashed offer outline and a trailing bindSuffix (default '?', overridable per locale) appended to its last text segment — Height: 8ft ? — because accepting a bind relabels an existing chip instead of adding a result, and the look says so. The looks follow the Figma Suggestion Strip Chip spec (66225:151222): a deterministic rung renders with the 2 px lineHighlight outline, a memory recall with a leading CoreIcons.history icon (an empty label shows the value alone), and the bind chip keeps the strip's plain fill
  • CoreChip: gains outline (CoreChipOutline { solid, dashed, highlight }, default solid) and semanticsLabel. The dashed outline reuses CoreDashedBorderDecoration (0.16.0) as the chip's foregroundDecoration over the chip's usual fill, with the solid border painted transparent so the chip measures the same and the stroke following the focus border width; CoreChipTheme.dashedOutline(outline:, isFocused:, colors:) resolves it. The highlight outline is a solid lineHighlight border at the focus width (CoreChipTheme.borderWidthFor(outline:)), with the padding giving the extra width back so the chip measures the same
  • Suggestion area showcase: digits typed with no function key start an unnamed entry, and the strip offers bind chips for the dimensions still missing (prototype off-script rule); Area suggestions are tagged deterministic, conversions conversion with spoken semantics labels

🧪 Tests #

  • Suggestion area widget tests: default kind, bind outline + suffix (value and unit placement, custom suffix), solid kinds unchanged, bind accept callback, semanticsLabel override, custom toggle label, and kind-only change collapsing an expanded area; a11y tests for the bind chip's tap target, label, contrast and announced text in both themes
  • CoreChip widget tests: default solid outline, dashed and highlight chip text, semanticsLabel override, and theme resolution for the dashed chip's unchanged fill and transparent border, the highlight border colour, width and state priority, and the focus stroke width in light and dark
  • Suggestion area widget tests: deterministic renders the highlight outline; memory renders the history icon and hides an empty label
  • Goldens: suggestion_area_bind_{light,dark}.png (bind offer beside a deterministic chip) and core_chip_outline_{light,dark}.png (highlight, solid and dashed at large, dashed at medium), viewport scoped to one chip row; existing suggestion area and chip goldens are byte-identical

0.16.0 CoreCalculatorChip result, dashed and error variants + long-press #

✨ Features #

  • CoreCalculatorChip: three new CoreCalculatorChipType variants for the calculator tape, so the app no longer has to borrow disabled for an answer or hand-build a chip for an error (CA-1034)
    • result — filled chip for an answer the app computed (prototype: outlined = typed, filled = computed). Shares the muted grey pair of disabled by design (prototype .t-result) but stays interactive so a long-press can open provenance
    • dashed — dashed outlineFocus outline over backgroundBlueLight for a bind offer ("Height: 8ft ?") or a chip being edited in place; text and factor keep the editable teal
    • error — alertRed fill inside a new alertRedOutline stroke (red200 light / red700 dark, the Figma spec's error border) with a regular-weight textDark value for the dimension-error chip that backspace repairs
    • editable, dashed and error carry CoreShadows.small as in the Figma Calculator Chip spec (58781:24269); the filled disabled, active and result chips stay flat
    • onLongPress fires for every variant except disabled; longPressSemanticLabel is exposed as the semantics long-press hint only while the callback is set, so screen readers never announce an action that is not there
    • CoreCalculatorChipTheme.dashedOutline(type:, colors:) resolves the dashed decoration (null for every other type); the solid border is painted transparent at the same width so all six variants measure the same
  • CoreDashedBorderDecoration: new shared Decoration for dashed rounded outlines, applied as a container's foregroundDecoration so the solid BoxDecoration border stays untouched
  • AppColorsExtension: new alertRedOutline token (red200 light / red700 dark) for the stroke around an alertRed surface
  • Calculator chip showcase regrouped by tape meaning (typed / computed / tentative / error) with a long-press provenance demo

🧪 Tests #

  • Widget tests: tap and long-press gating per variant, long-press semantics action + hint (present with the callback, withheld without it and when disabled), dashed outline resolved only for dashed, and token resolution for the three new variants in light and dark; text contrast checked for the new variants in both themes
  • Decoration unit tests for equality, step interpolation and painting
  • Goldens: the single light golden is replaced by light + dark goldens covering all six variants

0.15.0 Localization ownership moves to the consumer #

⚠️ Breaking changes #

  • KeyType / GroupNameType: both gain a required id — a stable, locale-independent identifier separate from the displayed label. GroupNameType equality and hashCode now key on id alone, so a group stays the same group (and the same Map key) when the app switches locale and re-renders its label. KeyType.groupName is documented as holding the group's id (CA-898)
    • onKeyTapped is unchanged: it already hands over the whole KeyType, so consumers read key.id for domain logic and key.label only for display
    • Migration: pass id at every KeyType / GroupNameType call site. Using the existing English label as the id keeps current domain matching working with no other change
    • GroupNameType.id must be non-empty and unique among sibling groups — equality depends on nothing else, so a shared id collapses two groups into one Map key. The constructor asserts against the empty string, the shape a missed migration takes
  • CoreDisplayArea: closeSemanticLabel and historyPlaceholder are now required. The English defaults ('Close', 'Here will show what you type') and the defaultCloseSemanticLabel / defaultHistoryPlaceholder constants that exposed them are gone, so a user-facing string can no longer reach the screen without passing through the consuming app's localization layer (CA-654)
    • Migration: pass localized strings at every call site, e.g. closeSemanticLabel: AppLocalizations.of(context).closeButton. Callers that relied on the constants for test assertions should assert against their own localized value instead

🧪 Tests #

  • Display-area widget, golden, and a11y call sites updated to pass both strings explicitly; goldens are byte-identical since the default text is unchanged
  • GroupNameType identity tests: equal across differing labels, unequal across differing ids, still resolving as a Map key when the label is localized, and an empty id rejected at construction
  • KeyType identity test: id is independent of the displayed label

0.14.1 Dark-theme colour audit: switch contrast, tooltip theming, AppColorsExtension dedup #

🔧 Fixes #

  • CoreSwitch: the normal (non-error) inactive thumb fill moves from lineDarkOutline to iconGrayMid so it clears WCAG 1.4.11 (3:1 non-text contrast) against the track in both CoreTheme.light() and CoreTheme.dark(); the error-state thumb is unchanged (F10 in the dark-theme colour audit)
    • _getInactiveThumbColor now delegates to _getBorderColor instead of duplicating its body
  • CoreTooltip: theme-dependent colours and typography are captured in _showTooltip() from the widget's declaring context and threaded into the overlay, instead of being re-resolved against the root navigator's overlay context. A tooltip inside a locally themed subtree (e.g. a Theme(data: CoreTheme.dark()) wrapper under a light MaterialApp) now renders with its local theme. This matches Flutter's own Tooltip, which also resolves theme values at show time (F7 in the dark-theme colour audit)

🔧 Internal #

  • AppColorsExtension: create() / createDark() now delegate to CoreTheme.lightAppColors() / CoreTheme.darkAppColors() instead of holding a second copy of the token map. Output is unchanged (F11 in the dark-theme colour audit)

🧪 Tests #

  • test/theme/theme_extensions_test.dart pins AppColorsExtension.create() / createDark() field-for-field against CoreTheme.lightAppColors() / darkAppColors(), and asserts the dark factory returns the dark palette rather than the light one
  • Switch goldens: a dark golden is added (switch_component_dark.png) and the light golden is refreshed for the new inactive-thumb colour
  • CoreTooltip gains a regression test for the locally-themed-subtree case

0.14.0 CoreDivider hairline rule #

✨ Features #

  • CoreDivider: new 1px hairline rule that replaces the hand-tokened Material Divider call sites in the consuming app (the search-results end-of-results footer and the auth pages' "or" separators), which each re-applied thickness: 1 + lineLight with private constants (CA-1016)
    • Exactly CoreDivider.thickness (1px) tall with no built-in whitespace — unlike Material's Divider and its default 16px height, vertical rhythm stays at the call site as CoreSpacing tokens; in a Row via Expanded the rule adds no vertical extent, so the label-separator row is sized by the text alone
    • Color defaults to the theme extension's lineLight, so the rule tracks CoreTheme.light() and CoreTheme.dark(); color overrides it for surfaces that need a different line token
    • Every Material Divider parameter is pinned — including radius: BorderRadius.zero — so a consuming app's ambient DividerThemeData cannot restyle the rule
    • indent / endIndent inset the rule from either edge; pass CoreSpacing tokens
    • resolvedColor(context) (@visibleForTesting) exposes the color build paints, so tests assert color resolution without reaching into the widget tree
    • Purely decorative: exposes no semantic node, matching Material's Divider
    • Defaults are derived from the two consumer call-site families, not measured from Figma directly; CA-1016 names the pagination-footer frame (65869:151824) as the design source for review cross-checking
  • Divider showcase screen added to the example catalogue (full-bleed, inset, custom color, label separator, end-of-list footer)

🧪 Tests #

  • Widget tests pin the 1px-tall/full-width geometry, the text-only row height and centering in the label-separator Row, and color resolution across both themes plus the explicit override
  • A11y test pins the purely-decorative contract — no announceable semantics node — in light and dark
  • Goldens for the three rule variants (full-bleed, inset, lineMid override), light + dark

0.13.1 CoreSearchBox exposes test keys on the inner text field and clear button #

Version note: 0.13.1 is a deliberate patch even though the change is a Feature — it is additive-only, and 0.14.0 is already claimed by the open CA-898 (#158) and CA-654 (#157) branches. Whichever of #157/#158/#159 merges last reconciles the version headers.

✨ Features #

  • CoreSearchBox: exposes CoreSearchBox.textFieldKey (core_search_box_text_field) on the inner text field and promotes the existing clear-button key to CoreSearchBox.clearButtonKey (core_search_box_clear_button, string unchanged), so app widget tests can target both with find.byKey instead of fragile find.byType(TextFormField) descendant finders. Both keys are shared statics, matching CoreInputChip.removeButtonKey — scope with find.descendant when a screen renders more than one search box (CA-952)

🧪 Tests #

  • Widget tests pin both key strings, assert the keyed widget is the single rendered text field, and pin the shared-static behavior across two instances; the suite migrated to the shared buildTestApp harness with CoreTheme.light() and every finder now goes through the key constants

0.13.0 CoreDateFilterChip active pill reuses the CoreInputChip primitive #

✨ Features #

  • CoreInputChip: adds removeOnChipTap (default false) — when true, tapping anywhere on the chip invokes onRemove and the whole chip is exposed as a single semantic button labeled with removeSemanticLabel; the close (×) icon stays visible as the removal affordance but is no longer a separate tap target (CA-830)

🔧 Changes #

  • CoreDateFilterChip: the active pill is now a CoreInputChip with whole-chip tap-to-remove instead of a hand-built container, so it adopts the chip family's visual treatment (pill radius, chipGrey background, semibold label, size-20 close icon). Consumers with goldens of the active pill will see pixel drift and should regenerate (CA-830)

🧪 Tests #

  • Unit + semantics tests for the whole-chip tap-to-remove mode (tap anywhere removes, single button node, icon stays, no-op without onRemove); default-mode chip goldens are byte-identical
  • CoreDateFilterChip active-pill goldens regenerated (light + dark)

0.12.0 CoreAppBar #

✨ Features #

  • CoreAppBar: new top app bar that implements PreferredSizeWidget, so it drops straight into Scaffold.appBar (CA-823)
    • Separating shadow comes from CoreShadows.medium via BoxDecoration, with Material elevation held at zero, so the shadow is drawn exactly once instead of doubling
    • CoreAppBarElevation { none, shadow, material } covers the un-shadowed bar, the CoreShadows bar, and surfaces that must match a Material-elevated sibling
    • padding is additive to preferredSize (preferredSize.height == height + padding.vertical), so padding never shrinks the content box. This is the failure mode behind the 48x40 tap target in CA-822; the constructor also asserts height >= CoreSpacing.space12 (48) so leading and action tap targets can always meet the 48x48 guideline
    • height defaults to CoreSpacing.space14 (56) — measured from the consuming app, where 56 is the preferred size of 9 of the 12 existing bars (HeaderRow uses 64; the two estimation bars use an off-grid kToolbarHeight + 5). The class doc carries a caveat that Figma's reusable "Action Bar" component instead measures 64 total with t8/b8/l4/r16 baked-in padding, so CA-823 migration sites should pass height/padding explicitly rather than treating the code-derived default as spec-confirmed
    • decorationShadow (@visibleForTesting) exposes the shadow the bar's decoration paints, resolved from elevation and consumed by build itself, so tests assert elevation behavior without reaching into the widget tree
    • scrolledUnderElevation is held at zero in every mode, so the bar does not darken or re-tint when content scrolls under it
    • Accepts an arbitrary title widget (custom rows, icon clusters) or a titleText convenience styled titleMediumSemiBold in textHeadline; supplying both asserts
    • Colors resolve from the theme extension (pageBackground, textHeadline, iconDark), so the bar tracks CoreTheme.light() and CoreTheme.dark()
    • implyLeading defaults to false, so the bar never sprouts a Material back button just because the route is poppable — the app bar design has no back button. leading is rendered independently of the flag, so an explicit close/back icon is never silently dropped
    • Holds no user-visible strings — leading and actions pass their own semanticLabel through, keeping localization in the consuming app

🧪 Tests #

  • Widget tests: preferred-size arithmetic, both asserts, elevation modes, theming fallback and override, action rendering and callbacks, and leading behaviour over a real pushed route (no implied back button by default, opt-in via implyLeading, explicit leading rendered regardless)
  • Golden tests: five bar shapes (flat/no-shadow, custom title row, back button with project title, Material elevation, plain title) in both light and dark, with the viewport scoped to each bar's own preferredSize so every golden contains exactly the bar and no empty body space
  • A11y tests: tap-target and label guidelines in both themes, including at the minimum permitted height
  • Title contrast is asserted from the resolved tokens rather than sampled pixels; the pixel-sampling guideline reads the AppBar title's antialiased glyph edges and reports a blend of text and background rather than the token colors

0.11.2 Keep CoreMultiSelectSheet visible above the keyboard #

🔧 Fixes #

  • CoreMultiSelectSheet: the sheet now pads itself by the keyboard's view inset and lets the item list shrink, so the search field, list, and action buttons stay visible above the keyboard while the user types (CA-842)

🧪 Tests #

  • Widget test: presents the sheet through CoreQuickSheet.show (the real presentation path), simulates the keyboard opening, and asserts the search field, list items, and Apply button all sit above the keyboard
  • Golden tests: keyboard-open sheet in both light and dark themes

0.11.1 CoreBottomNavBar action button semantic label #

🔧 Fixes #

  • CoreBottomNavBar: adds actionButtonSemanticLabel parameter — when provided, the trailing circular action button is wrapped in a Semantics node so screen readers can announce it; when null (default) behavior is unchanged (backward compatible, no golden change)

🧪 Tests #

  • Semantics test: verifies label and isButton flag appear on the trailing button's semantics node
  • A11y test: confirms the labeled trailing button meets tap-target and label guidelines in both light and dark themes

0.11.0 Parameterize CoreBottomNavBar for 2–4 tabs #

✨ Features #

  • CoreBottomNavBar: now accepts 2–4 tabs (previously required exactly 4)
    • Assert updated to tabs.length >= 2 && tabs.length <= 4
    • Layout computation derives tab-row and nav-bar base widths dynamically from tabs.length, so pill, active-tab, and inactive-tab proportions are correct for any supported tab count
    • 2-tab design verified against Figma spec (CA-874)
    • Inactive tab icons corrected from iconGrayMid to iconWhite for contrast on dark track
    • Active tab label uses textLink token (semantic fix; same hex value in all themes)
    • Existing 4-tab layout unchanged; goldens regenerated for icon color fix

🧪 Tests #

  • Boundary assert tests: rejects < 2 tabs and > 4 tabs
  • 2-tab rendering tests: active label only visible, correct icon count
  • 2-tab interaction test: tap second tab fires onTabSelected(1)
  • New golden: core_bottom_nav_bar_2tab_default.png

0.10.2 Accessibility #

✨ Features #

  • CoreInputChip: add optional removeSemanticLabel for a localizable remove-button announcement; when null, keeps the default 'Remove <label>' English label

0.10.1 Dark-mode contrast fixes #

🔧 Fixes #

  • Accessibility / Dark mode
    • CoreButton (social variant): background changed from buttonInverse (gray25 — near-white) to backgroundSecondaryDark in dark mode, preventing invisible content when text and icon tokens also resolve to near-white
    • DimensionCard: same background-swap fix applied; card surface is now backgroundSecondaryDark in dark mode instead of buttonInverse
    • SizeCard: same background-swap fix applied; card surface is now backgroundSecondaryDark in dark mode instead of buttonInverse
    • All three fixes mirror the existing CoreSelectButton dark-mode guard pattern; contrast ratios now meet WCAG AA (≥ 4.5:1 for text, ≥ 3:1 for UI components)

🧪 Tests #

  • Social button: WCAG contrast a11y test + light & dark golden tests
  • DimensionCard / SizeCard: WCAG contrast a11y tests added to core_geometry_area_a11y_test.dart
  • Dark-mode golden tests added for CoreGeometryArea (collapsed and expanded)

0.10.0 Search & Filter Components #

✨ Features #

  • UI Components
    • CoreDateFilterChip: Filter chip for a date-range filter. With no selection it renders a plain CoreFilterChip that opens a CoreDateRangeSheet on tap; with a selection it renders an active pill showing the formatted range with a clear ×. Surface-agnostic: each caller supplies its own label, accessibility labels, and widget keys.
    • CoreDateRangeSheet: Modal bottom sheet for picking an inclusive, whole-calendar-day DateRange. Offers predefined ranges (Today, Last 7 days, Last 30 days, This month) plus a Custom range option that opens CoreDatePicker twice — once for the start date, once for the end date. Resolves with the chosen DateRange, or null on cancel/dismiss.
    • CoreMultiSelectSheet: Modal bottom sheet body for selecting multiple values from a searchable list of {id, label} items. The caller supplies the (already filtered) list and reacts to search and apply callbacks; present it with CoreQuickSheet.show.
    • DateRange: Value type representing an inclusive calendar-day range, shared by the date filter components.
    • All three components ship with showcase screens, widget tests, accessibility tests, and light + dark golden tests.

0.9.1 Dart 3.8 compatibility patch #

🔧 Fixes #

  • Dependency constraints loosened for Dart 3.8 compatibility
    • flutter_svg: ^2.3.0 → ^2.2.3 — 2.3.0 requires Dart ≥3.9.0; 2.2.3 is the last release compatible with Dart 3.8. No coreui APIs from 2.3.0 are used.
    • lottie: ^3.4.0 → ^3.3.1 — same reason; only Lottie.asset() with stable params is used.
    • ripplearc_linter moved from dependencies to dev_dependencies — the linter has no runtime role and should never have been a transitive dependency for consumers; this was causing analyzer ^8.4.0 to cascade to every app using coreui, breaking build tooling on Dart 3.8.

0.9.0 Dark theme #

✨ Features #

  • Dark Color Tokens
    • 9 dark token classes mirroring each light class (DarkBackgroundColors, DarkTextColors, DarkIconColors, DarkBorderColors, DarkTabColors, DarkButtonColors, DarkInputColors, DarkSelectColors, DarkStateColors) — all colors sourced from the Figma dark-mode palette
    • CoreTheme.dark() now returns a fully populated ThemeData with brightness: Brightness.dark and scaffoldBackgroundColor mapped to gray50; both AppColorsExtension and AppTypographyExtension are switched to their dark variants automatically
    • AppTypographyExtension.createDark() — all 19 text styles substituted with CoreDarkTextColors.* (gray25 for headlines, gray100 for titles, gray300 for body); components using typography.someStyle without .copyWith now render correctly in dark mode

🔧 Fixes #

  • Accessibility
    • SingleItemSelector modal title: uses .copyWith(color: colors.textHeadline) so text stays visible on the dark scaffold (was gray900 on gray900 — 1:1 contrast)
    • SingleItemSelector item text: uses .copyWith(color: colors.textBody) to ensure list items remain legible in dark mode
    • CoreSelectButton selected tab: text color switches to textInverse (gray900) when tab background is tabsHighlight (orient300), resolving the 1.6:1 contrast failure in dark mode
  • CoreLetterAvatar: replaced Image.asset with a BoxDecoration-based Container wrapped in AspectRatio(aspectRatio: 1.0); fixes Semantics label propagation that was blocked by Image.asset and correctly derives height from the available width constraint without a RenderBox infinite-constraint error

Tests #

  • CoreDatePicker Visual Regression - Dark golden added — verifies header background (blue900), selected day fill (orient200), and month row text under CoreTheme.dark()
  • Dark-mode goldens added for color tokens, letter avatar, and check row item; all light goldens refreshed against current Flutter SDK

0.8.0 CoreInputChip #

✨ Features #

  • UI Components
    • CoreInputChip: New non-toggleable input chip for displaying committed tokens (e.g. email addresses or tags) with a remove button.
      • Displays a text label in bodyMediumSemiBold with TextOverflow.ellipsis — safe inside Wrap rows and on narrow screens
      • Trailing close (×) button meets the 48 dp minimum tap-target requirement; tapping calls onRemove
      • onRemove is optional — omitting it hides the remove button entirely, enabling a read-only/locked-token display mode
      • Full accessibility support: chip container exposes a Semantics(container: true) node with the label text; remove button exposes a Semantics(button: true) node labelled "Remove <label>"; label Text is wrapped in ExcludeSemantics to prevent double-announcement
      • CoreInputChip.removeButtonKey static key for locating the tap target in tests
      • Widget tests, accessibility tests (both themes), and golden tests (light + dark, short label + email label)

0.7.2 CoreCheckRowItem & CoreDatePicker #

Upgraded #

  • Flutter SDK bumped from 3.32.0 to 3.44.4; Dart SDK constraint raised to >=3.12.0 <4.0.0.
  • Gradle wrapper 8.13 → 8.14.
  • Android Gradle Plugin (AGP) 8.7.0 → 8.11.1.
  • Kotlin Gradle Plugin 2.1.0 → 2.2.20.
  • flutter_lints ^5.0.0 → ^6.0.0.
  • flutter_svg ^2.2.2 → ^2.3.0, lottie ^3.3.1 → ^3.4.0, ripplearc_linter ^0.4.0 → ^0.4.1.
  • Minimum supported iOS deployment target raised from 12.0 to 13.0 (example app).

Fixed #

  • Fixed a drag-reorder regression in CoreFunctionKeyBottomSheet where migrating to Flutter's new onReorderItem callback (which now performs index correction internally) had left the widget's own manual index-correction logic in place, causing dropped items to land one position off from where the user released them.

Changed #

  • Migrated ReorderableListView/ReorderableListView.builder usages (_SizesTable, CoreFunctionKeyBottomSheet) from the deprecated onReorder callback to onReorderItem, ahead of Flutter's planned removal of onReorder.
  • Migrated widget tests off the deprecated SemanticsNode.hasFlag/SemanticsData.flags API to the new flagsCollection API, including the isSelected/isEnabled flags moving from bool to the new Tristate enum.
  • SingleItemSelector's bottom sheet item now wraps its ListTile in a Material widget with Clip.antiAlias, fixing the tap ripple/ink effect rendering outside the intended bounds.
  • CoreKeyboard's reveal/collapse SizeTransition migrated from axisAlignment: -1.0 to alignment: AlignmentDirectional.topStart.

Tests #

  • Existing SingleItemSelector widget tests now pass without framework exceptions after the Material(clipBehavior: Clip.antiAlias) wrapper fix.

0.7.0 CoreCheckRowItem & CoreDatePicker #

✨ Features #

  • UI Components
    • CoreCheckRowItem: New selectable list row — leading widget, title (+ optional subtitle), and a trailing checkbox.
      • Whole row is tappable; tapping toggles selected via onChanged
      • Defaults the leading widget to a 24×24 circle showing the first initial of title (derived from the first whitespace-delimited token, uppercased, e.g. "John Doe" → "J"; blank title renders an empty circle, no crash); avatarBackgroundColor/avatarTextColor/avatarTextStyle theme it (ignored when a custom leading is supplied); avatarTextColor is applied last and remains the single source of truth for the glyph colour
      • Trailing checkbox swaps between CoreIcons.check and CoreIcons.checkBlank based on selected
      • Optional subtitle for a second line (e.g. an email address)
      • Localizable semanticLabel param (defaults to title); exposed as a Semantics(button: true, checked: selected) node
    • CoreDatePicker: New modal calendar widget for picking a single date (CA-220).
      • Header with a localizable label and a large spelled-out selected date ("Mon, Aug 17"-style by default, fully overridable via dateLabelBuilder)
      • Month selector row with previous/next navigation; arrows disable themselves once an adjacent month would be entirely out of the optional firstDate/lastDate range
      • Day grid with selected (filled), "today" (outlined), and disabled (out-of-range) states
      • CoreDatePicker.show static helper presents the picker in a themed dialog and resolves with the confirmed DateTime, or null on cancel/dismiss
      • monthLabelBuilder and weekdayLabels allow full localization of all date text without subclassing
      • Each day cell exposes a Semantics(button: true, selected: ...) node with a full date label via MaterialLocalizations.formatFullDate

0.5.0 Search components #

✨ Features #

  • UI Components
    • CoreSearchBox: New borderless search input field.
      • Built-in leading search icon and auto-appearing clear button (shown only when the field has text)
      • Flat appearance with no visible border — designed for global or in-page search bars
      • Accepts an optional TextEditingController and FocusNode; manages its own when none are supplied
      • onChanged, onSearch (keyboard submit), and onClear callbacks
      • enabled flag renders the field non-interactive with a backgroundGrayMid fill
      • clearSemanticLabel localizable constructor param (defaults to 'Clear search')
      • hintText localizable constructor param for placeholder text
    • CoreSearchRowItem: New single-row item for search screens.
      • Two named constructors: CoreSearchRowItem.recentSearch (history icon) and CoreSearchRowItem.suggestion (search icon with bold-prefix query highlighting)
      • Trailing ↗ icon with independent onTrailingTap callback (e.g. fill the search field without triggering a search)
      • showTrailingIcon flag to hide the trailing icon
      • semanticLabel and trailingSemanticLabel localizable params for full screen-reader support
      • Custom variant via the default constructor: caller supplies any leadingIcon and a pre-built label widget

0.4.1 CoreIconSize token #

✨ Features #

  • Design Tokens
    • CoreIconSize: New icon size token with four canonical sizes — size16 (16dp), size20 (20dp), size24 (24dp), size32 (32dp).
      • Value-based naming reflects how icon sizes are referenced in design tooling and specs
      • Exported from the public barrel alongside other theme tokens
      • Golden test verifying each size using CoreIconWidget

0.4.0 CoreFilterChip component #

✨ Features #

  • UI Components
    • CoreFilterChip: New dropdown-style filter chip for filter rows.
      • Filled pill design using backgroundGrayMid (#F2F4F7) background token
      • Trailing dropdown arrow icon in iconDark (#015B7C) color
      • label (required) and onTap (optional) public API — chip is non-interactive when onTap is null
      • Full accessibility support: outer Semantics node exposes label and button role (only when enabled); Text and arrow icon wrapped in ExcludeSemantics to prevent double-announcement
      • Widget tests, accessibility tests, and golden tests (enabled, long label, disabled states)

0.3.9 CoreToast title support #

✨ Features #

  • UI Components
    • CoreToast: Added optional title parameter to showSuccess, showError, and showWarning methods.

🔧 Fixes #

  • Code Quality
    • Improved null safety in CoreToast descriptions to avoid displaying "null" strings.
    • Cleaned up redundant documentation and implementation comments.

0.3.8 CoreQuickSheet component #

✨ Features #

  • UI Components
    • CoreQuickSheet: New standardized bottom sheet component for consistent sheet presentation across the app
      • Automatic content-based height (up to 90% of screen)
      • Custom drag handle with consistent styling
      • Theme-aware background color (defaults to pageBackground)
      • Configurable dismiss behavior (isDismissible, enableDrag)
      • Optional safe area handling (useSafeArea)
      • Optional custom background color override
      • Rounded top corners (28px) per design spec
      • Returns values when dismissed for result handling

🔧 Fixes #

  • Code Quality
    • Fixed tooltip component forced unwrapping issue with overlay entry
    • Improved null safety in tooltip overlay insertion

0.3.7 Add splash screen icons #

✨ Features #

  • Icons
    • Added splash screen animation icons (splashFirstState, splashSecondState, splashThirdState)
    • New SVG icons available via CoreIcons for splash screen animations

0.3.6 Accessibility improvements #

✨ Features #

  • Accessibility
    • Added accessibility tests for all interactive components (CoreAvatar, CoreLetterAvatar, CoreKeyboard, CoreButton, CoreBottomNavBar, CoreLoadingIndicator)
    • Tests verify tap target size, semantic labels, and text contrast guidelines

🔧 Fixes #

  • Design Tokens

    • Updated text link color from orient600 to orient800 to match UI design specification
  • Accessibility

    • Fixed CoreButton text overflow with ellipsis and FittedBox scaling for long labels
    • Fixed accessibility-related contrast and layout issues across components

0.3.5 Code quality improvements #

✨ Features #

  • UI Components

    • CoreLoadingIndicator: Added Lottie-based loading indicator component with customizable size and fit options
  • Dependencies

    • Added lottie (^3.2.0) for animation support
  • Assets

    • Added loading animation asset (assets/animations/loading.json)

0.3.4 Code quality improvements #

🔧 Fixes #

  • Code Quality
    • Fixed avoid_static_colors linter violations
    • Integrated shadow colors into theme system for consistent design token usage

0.3.3 Theme extension naming consistency #

⚠️ Breaking Changes #

  • TypographyExtension has been renamed to AppTypographyExtension for consistency with other theme extensions
  • Update your code: Theme.of(context).extension<TypographyExtension>() → Theme.of(context).extension<AppTypographyExtension>()

0.3.2 Code quality improvements #

🔧 Fixes #

  • Code Quality
    • Fixed avoid_static_typography linter violations
    • Fixed forbid_forced_unwrapping linter violations
    • Fixed specific_exceptions_types linter violations

0.3.1 Add transparent utility color #

✨ Features #

  • Design Tokens
    • Added transparent utility color to the core color palette and AppColorsExtension for consistent use across apps.

0.1.0 Initial Release #

✨ Features #

  • UI Components

    • CoreBottomNavBar: A customizable bottom navigation bar component with responsive sizing and smooth animations.
    • SuccessModal: A bottom sheet that is displayed to the user when an operation is successful.
    • Toast: Provides a static interface to display toast messages, e.g., Toast.showSuccess, Toast.showError, Toast.showWarning.
    • CoreButton: Customizable button with support for primary, secondary, and social variants, multiple sizes, icons, and disabled state.
    • CoreTextField: Flexible text input with label, helper text, error handling, phone number input, prefix/suffix widgets, and country code selector.
    • SingleItemSelector: Single-select dropdown with bottom sheet support.
    • CoreIconWidget: Unified icon widget supporting both Material and SVG icons.
  • Design Tokens

    • Color tokens (brand, gray, blue, red, etc.)
    • Typography tokens (font sizes, weights, styles)
    • Spacing tokens (consistent spacing system)
    • Shadow tokens (multiple shadow levels)
    • Icon tokens (Material and custom SVG icons)
  • Theming

    • Light and dark theme support
    • Easily extendable theme data for custom branding
  • Assets

    • Extensive icon set (SVG and Material icons)
    • IBM Plex Sans Hebrew font family included
3
likes
160
points
773
downloads

Documentation

API reference

Publisher

verified publisherripplearc.com

Weekly Downloads

A Flutter design system package with design tokens and basic components.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, flutter_svg, lottie

More

Packages that depend on ripplearc_coreui