feat: sync cloud-portal changes (datum-ui 0.7 minor)#78
Open
yahyafakhroji wants to merge 10 commits intomainfrom
Open
feat: sync cloud-portal changes (datum-ui 0.7 minor)#78yahyafakhroji wants to merge 10 commits intomainfrom
yahyafakhroji wants to merge 10 commits intomainfrom
Conversation
d2c3170 to
be23785
Compare
Syncs behavior and primitives that landed in cloud-portal's vendored app/modules/datum-ui/ fork between 2026-03-01 and 2026-04-14. ## Added - useBreakpoint hook (mobile/tablet/desktop tier, SSR-safe, matchMedia-backed) - MobileSheet base primitive (bottom-sheet wrapper around Sheet) - ResponsiveDropdown base primitive (DropdownMenu on desktop/tablet, MobileSheet on mobile) - RichTextEditor feature component (compound API: .Toolbar, .Bold, .Italic, .Underline, .Strike, .Link, .Content, .CharacterCount) with TipTap 3.x as optional peer deps - RichTextContent read-only renderer with DOMPurify sanitization - Optional Canela font export at @datum-cloud/datum-ui/styles/canela (opt-in; default stack is system sans) - Mobile long-press tooltip support via TouchTooltipBubble (500ms press, 1500ms auto-dismiss) ## Changed - PageTitle: font-title text-3xl, description max-w-2xl, data-e2e hook - TagsInput: new optional props delimiters, normalizer, validator (Zod); auto-confirm pending input on blur - Form.Dialog: new optional showHeaderClose prop (default true) - Form.Field: items-start alignment (visual change), showErrors prop, responsive help tooltip - TimeRangePicker: mobile sheet layout on mobile viewports - Tooltip: TooltipContent gains max-w-[calc(100vw-2rem)] ## Dependencies - New optional peer deps: @tiptap/react, @tiptap/starter-kit, @tiptap/extension-link, @tiptap/extension-underline, @tiptap/extension-character-count, @tiptap/extension-placeholder (>=3) - New runtime dep: isomorphic-dompurify (sanitizer for RichTextContent)
- Introduced a NavSkeleton component to display a loading state in the AppNavigation component. - Added a loading prop to conditionally render the skeleton or the actual navigation items. - Enhanced the sidebar structure with new Sidebar components for better organization and visual separation.
1ce3c86 to
f3d7a0d
Compare
Stories for the new components and enhanced props landing in this sync: Added - base/mobile-sheet.stories.tsx (Default, WithDescription, NoFooter) - base/responsive-dropdown.stories.tsx (Default menu, WithCustomContent). Children use plain buttons/rows — Radix DropdownMenuItem requires a DropdownMenu context that only exists on the desktop branch. - features/rich-text-editor.stories.tsx (Editor, ReadOnly) - features/form-dialog.stories.tsx (showHeaderClose toggle) Enhanced - features/tag-input.stories.tsx — WithCustomDelimiters, WithNormalizer, WithZodValidator, AutoConfirmOnBlur variants - features/page-title.stories.tsx — LongDescription variant showing the new max-w-2xl constraint - base/tooltip.stories.tsx — doc note describing mobile long-press - stories/storybook.css — opt into canela.css so font-title renders Canela (previously fell back to system sans)
f3d7a0d to
8049fdf
Compare
…to MobileSheet/ResponsiveDropdown - InSheetContext (co-located with MobileSheet) + useInSheet hook — lets responsive primitives detect when they're already inside a MobileSheet and suppress their own sheet branch to avoid sheet-in-sheet stacking. - MobileSheet provides InSheetContext=true on its scrollable body. - ResponsivePopover primitive: Popover on desktop/tablet, MobileSheet on mobile. Same decision logic as ResponsiveDropdown: responsive && mobile && !inSheet. Exposes align, side, sideOffset, alignOffset, avoidCollisions, contentClassName, modal, onOpenAutoFocus, onCloseAutoFocus, onInteractOutside, onEscapeKeyDown. - ResponsiveDropdown back-filled with responsive?: boolean prop and InSheetContext read for nested-case suppression. Backward compatible — defaults preserve existing behavior.
…mers All existing popover/dropdown consumers now render as a MobileSheet on <768px viewports by default. Each gains optional responsive?: boolean (default true) and sheetTitle?: string props. Desktop behavior unchanged. Popover-based (→ ResponsivePopover): - Combobox (sheetTitle fallback: placeholder ?? 'Select option') - Autocomplete (fallback: placeholder ?? 'Search') - Autosearch (fallback: placeholder ?? 'Search') - CalendarDatePicker (fallback: placeholder ?? 'Pick a date') - DateTimePicker (fallback: placeholder ?? 'Pick date & time') - RichTextEditor link-toolbar (fallback: 'Insert link') - TimeRangePicker AbsoluteRangePanel (context-suppressed — stays popover inside parent sheet) - DataTable checkbox-filter + select-filter (fallback: title ?? 'Filter') DropdownMenu-based (→ ResponsiveDropdown): - MoreActions (fallback: 'Actions'). Actions refactored from Radix DropdownMenuItem to plain buttons so they render in both the desktop DropdownMenu and the mobile MobileSheet. - DataTable row-actions (fallback: 'Actions'). Same refactor. Each affected component now has a mobile-sheet test case verifying the viewport branch.
Ports the MultiSelect component from cloud-portal. Uses ResponsivePopover internally — no manual useBreakpoint + MobileSheet branching needed. Exposes options, value, onValueChange, placeholder, variant, animation, maxCount, modalPopover, asChild, className plus the standard responsive? and sheetTitle? props (fallback: placeholder ?? 'Select options'). Fixed a latent bug from the cloud-portal source: defaultValue = [] as a destructure default created a new array every render, causing an infinite useEffect loop in React 19. Extracted to a module-level EMPTY_ARRAY constant.
- New story: base/responsive-popover (Default, ResponsiveFalse) - New story: features/multi-select (Default, WithPresetSelection) - Changeset bullets added to sync-cloud-portal-0.7.md and storybook-sync-coverage.md documenting the new primitives, MultiSelect feature, and the responsive-by-default sweep across existing popover/dropdown consumers.
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.
Summary
Syncs
@datum-cloud/datum-uiwith behavior and primitives that landed in cloud-portal's vendoredapp/modules/datum-ui/fork between 2026-03-01 and 2026-04-14. Version bump is handled by the changeset (minor); CI will compute the alpha build hash.Added
useBreakpointhook (mobile | tablet | desktoptier, SSR-safe, matchMedia-backed)MobileSheetbase primitive (bottom-sheet wrapper aroundSheet)ResponsiveDropdownbase primitive (DropdownMenu on desktop/tablet, MobileSheet on mobile)RichTextEditorfeature component (TipTap 3.x, compound API:.Toolbar,.Bold,.Italic,.Underline,.Strike,.Link,.Content,.CharacterCount)RichTextContentread-only renderer with DOMPurify sanitization@datum-cloud/datum-ui/styles/canela(opt-in; default is system sans)TouchTooltipBubble(500ms press → show, 1500ms auto-dismiss)Changed
PageTitle—font-title text-3xl, descriptionmax-w-2xl,data-e2e="page-title"TagsInput— new optionaldelimiters,normalizer,validator(Zod) props; auto-confirm pending input on blurForm.Dialog— new optionalshowHeaderCloseprop (defaulttrue)Form.Field—items-startalignment,showErrorsprop, responsive help tooltip (w-[calc(100vw-2rem)] sm:w-auto sm:max-w-xs)TimeRangePicker— mobile sheet layout on mobile viewportsTooltip—TooltipContentgainsmax-w-[calc(100vw-2rem)]Dependencies
@tiptap/{react,starter-kit,extension-link,extension-underline,extension-character-count,extension-placeholder}(>=3). Required only if consumingRichTextEditor.isomorphic-dompurify(required byRichTextContentsanitization).Known items inherited from cloud-portal source
These behaviors match the cloud-portal source verbatim and ship with the sync. They are candidates for follow-up fixes but are out of scope for this PR:
ResponsiveDropdownmobile path wraps the user-providedtriggerin arole="button"<div>with its ownonClick— if the inner trigger is also clickable, the click can bubble and toggleonOpenChangetwice.Tooltiplong-press path and Radix desktop tooltip both renderrole="tooltip"elements. On touch-capable desktops, both could appear simultaneously and be announced by screen readers as separate tooltips.Form.Fieldlabel alignment changed fromitems-centertoitems-start. Multi-line labels now top-align with the help icon. Visual change only; no API break.Test plan
pnpm vitest run— 560 tests pass (including new useBreakpoint, MobileSheet, ResponsiveDropdown, RichTextEditor, Tooltip long-press, TagsInput UX, TimeRangePicker mobile cases)pnpm typecheck— cleanpnpm build— clean;dist/styles/canela.css,dist/styles/fonts/CanelaText-Regular.ttf,dist/mobile-sheet/index.mjs,dist/responsive-dropdown/index.mjs,dist/rich-text-editor/index.mjsall produced