* docs: add feature opt-in banner system plan
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* docs: iterate on feature opt-in banner plan based on feedback
- Use config.ts for feature metadata instead of TRPC response
- Consolidate localStorage dismissal into single key to avoid bloat
- Replace separate success dialog with in-dialog success state for smoother UX
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: implement feature opt-in banner system
- Add checkFeatureOptInEligibility TRPC procedure to check if user can opt-in
- Create useFeatureOptInBanner hook with localStorage dismissal state
- Create FeatureOptInBanner floating component for bottom-right display
- Create FeatureOptInConfirmDialog with role-based options and success state
- Integrate banner into bookings-view.tsx as example usage
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add i18n translation keys for feature opt-in banner
* refactor: create FeatureOptInBannerWrapper for simpler consumer integration
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: use @calcom/lib/webstorage and add Zod schema for localStorage
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: address PR review comments - use PBAC, move logic to service, improve typing
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
# Conflicts:
# packages/features/feature-opt-in/services/FeatureOptInService.ts
* test: add comprehensive tests for checkFeatureOptInEligibility method
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: correct import and Checkbox type errors
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update message
* invalidate after dialog dismiss
* feat: simulate user opt-in to determine banner eligibility
When a feature has a strict policy and org/team hasn't explicitly
enabled it, user opt-in alone won't enable the feature. This change
simulates what would happen if the user opts in and only shows the
banner if opting in would actually enable the feature.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add early return for missing featureConfig and clarify simulation comment
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix repository usage
* refactor: simplify FeatureOptInConfirmDialog UI and remove unused translation
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: replace radio buttons with multi-select dropdown in FeatureOptInConfirmDialog
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* resize banner
* refactor: use AnimatedPopover pattern for team selection and rename titleI18nKey to nameI18nKey
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: change 'Just for me' to 'For me', fix width clipping, remove divider
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update style
* feat: make 'Just for me' mutually exclusive with teams/org and store opt-ins in localStorage
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: remove barrel imports and update to direct imports
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add modal prop to AnimatedPopover to fix scroll lock conflict in dialogs
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: wrap Popover.Content with Portal to prevent layout interference in dialogs
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: use flexbox gap instead of space-y to prevent popover wrapper from affecting layout
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* Revert "fix: use flexbox gap instead of space-y to prevent popover wrapper from affecting layout"
This reverts commit 8385adafa890c2f2674aa3ae3b10ca6e0c55ba5c.
* Revert "fix: wrap Popover.Content with Portal to prevent layout interference in dialogs"
This reverts commit e84301a35a99b3559d47c2d37316af290834ca2d.
* Revert "fix: add modal prop to AnimatedPopover to fix scroll lock conflict in dialogs"
This reverts commit b015af2f1cf31ef7087c02cb8535d96cc4a34125.
* feat: replace Radix Dialog and AnimatedPopover with coss-ui components
This migration uses @coss/ui Dialog and Popover components which are built on
Base UI instead of Radix. Base UI handles scroll locking and positioning
differently, which should fix the gap issue when opening the popover inside
the dialog.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: replace remaining @calcom/ui components with coss-ui
- Replace Divider with Separator from @coss/ui
- Replace Label with Label from @coss/ui
- Replace CheckboxField with Checkbox + Label from @coss/ui
- Replace Icon with direct lucide-react icons (UserIcon, BuildingIcon, UsersIcon, CheckIcon)
- Replace showToast with toastManager.add() from @coss/ui
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: replace Popover with Menu component from coss-ui
- Replace Popover + FilterCheckboxField with Menu + MenuCheckboxItem
- MenuCheckboxItem provides built-in checkbox indicator and styling
- MenuSeparator provides proper menu separators
- Cleaner API with onCheckedChange callback
- Better keyboard navigation support
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: align icon and text on same line in MenuCheckboxItem, widen dialog
- Wrap icon and text in flex container with items-center gap-2
- Change dialog width from sm:max-w-md to sm:max-w-lg to prevent text wrapping
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* use dimmed bg for coss dialog title
* refactor: change nameI18nKey/descriptionI18nKey to nested i18n object
- Change OptInFeatureConfig interface to use i18n: { name, description }
- Update all component usages to use featureConfig.i18n.name and featureConfig.i18n.description
- Update test mocks to use new structure
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add i18n.title to OptInFeatureConfig type definition
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update texts
* use title instead of name
* update banner style
* refactor: split FeatureOptInConfirmDialog into separate success and confirmation dialogs
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: don't record dismissed info in local storage after successful opt-in
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add checkFeatureOptInEligibility to IFeatureOptInService interface
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update common.json
* refactor: move tRPC usage from features package to apps/web/modules
Addresses Cubic AI review feedback (confidence 9/10):
- Remove @calcom/trpc import from FeatureOptInConfirmDialog.tsx
- Add FeatureOptInMutations type for passing mutation functions via props
- Move tRPC hooks to useFeatureOptInBanner hook in apps/web/modules
- Pass mutations through FeatureOptInBannerWrapper to dialog component
This maintains the architectural constraint that packages/features
should not import from @calcom/trpc to prevent circular dependencies.
Co-Authored-By: unknown <>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ui): update coss ui components
* fix(sidebar): remove redundant overflow-auto from SidebarContent
ScrollArea already provides the scroll container, so keeping overflow-auto
on the child creates a nested scroll area and prevents scrollFade from
reflecting actual overflow.
Addresses Cubic AI review feedback with confidence 9/10.
Co-Authored-By: unknown <>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>