Files
cosscom__coss/apps/examples/calcom/components/particles/image-checkbox-option.tsx
Pasquale Vitiello f285280759 feat(calcom): add settings page prototypes & refactor titles to AppHeader layout (#693)
* create some webhook pages

* mc

* wip

* wip

* add filtering system for webhooks

* feat(calcom): add nativeButton prop to CollapsibleTrigger in new webhook form

* mc

* mc

* card component improvements

* format

* feat(calcom): add push-notifications settings page prototype

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor: use SettingsToggle with Switch instead of Button

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor: use Switch directly inside Card/CardPanel instead of SettingsToggle wrapper

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor

* feat: add toast notifications on push notification toggle

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor: extract client logic into separate component, keep page.tsx as server component

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* update toast position

* feat(calcom): add features settings page prototype

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* fix: use correct ToggleGroup value type (array) and remove invalid toggleMultiple prop

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* mc

* feat(calcom): add billing settings page prototype

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* add billing page

* refactor: update layout of Features and Push Notifications pages for improved styling

* feat(calcom): add organizations profile settings page prototype

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor(calcom): update org profile page to match production Cal.com fields

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor(calcom): match org profile page to production screenshot

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor(calcom): align org profile page with my-account/profile patterns

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor(calcom): extract client logic from page.tsx into separate components

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor(calcom): keep only CardPanel content as client components

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* mc

* refactor(calcom): align org profile layout with my-account/profile pattern

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* feat(calcom): add no-permissions prototype for org profile page

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* add no permission page

* fix(calcom): remove duplicate ListItemTitleLink export

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor(calcom): move org profile to /settings/teams/[id]/profile and add team nav links

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* add conferencing page

* add conferencing page

* add appearance page

* add password page

* format

* add impersonation page

* create 2fa page

* improve empty component spacing

* feat(calcom): add compliance settings page prototype

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* improve compliance docs section

* simplify the structure

* feat(calcom): add calendars settings page with CardFrame structure

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* feat(calcom): add calendars empty state view

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* feat(calcom): add calendars demo page with CardFrame structure

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* feat(calcom): add calendars demo page with fieldset, selects, and footer

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* add calendars page

* add alert dialog + route changes

* create oauth page

* feat(calcom): add OAuth client creation dialog prototype

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* implement new dialog

* refactor(calcom): use detached triggers for OAuth dialog and match webhooks empty pattern

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor(calcom): use avatar component pattern for logo upload in OAuth dialog

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* create 2 step dialog

* feat(calcom): add OAuth clients list with items matching booking/past pattern

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* mc

* feat(calcom): add edit OAuth client dialog with button trigger on list items

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* refactor list item

* mc

* further changes

* fix alert dialog

* mc

* mc

* fix alert dialog

* mc

* mc

* refactor list items

* mc

* feat(calcom): add API keys page with list, create/edit dialogs, and revoke confirmation

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* various changes

* fix(calcom): update API keys list badge to show active/expired status, description shows expiration info

Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>

* improve settings sidebar

* further improvements

* improve appearance page

* various improvements

* complete appearance page.

* add team billing

* build registry

* feat(calcom): enhance billing page with date range selection and calendar integration

* mc

* mc

* mc

* fix sidebar

* rework page title and descriptions

* refactor: move page titles/descriptions to AppHeader for all remaining settings pages

Co-Authored-By: unknown <>

* refactor: use SettingsToggle for push notifications and impersonation pages

Co-Authored-By: unknown <>

* various adjustments

* refactor: rework webhooks demo to use CardFrame/CardFrameHeader per user with ListItems

Co-Authored-By: unknown <>

* refactor: match webhooks empty state to conferencing pattern with dashed border

Co-Authored-By: unknown <>

* mc

* refactor: remove Card wrapping from OAuth empty state to match conferencing pattern

Co-Authored-By: unknown <>

* refactor: remove Card wrapping from API keys empty state to match conferencing pattern

Co-Authored-By: unknown <>

* mc

* refactor: put calendar selects side-by-side to match team settings pattern

Co-Authored-By: unknown <>

* use list item throughout

* refactor: extract DangerZoneSection reusable component from profile pages

Co-Authored-By: unknown <>

* refactor: rename DangerZoneSection to DangerZone

Co-Authored-By: unknown <>

* refactor: extract FieldGrid reusable component for responsive form layouts

Co-Authored-By: unknown <>

* refactor: use FieldGrid in more settings forms

Co-Authored-By: unknown <>

* feat(calcom): add admin settings sidebar links

Co-Authored-By: unknown <>

* refactor: move admin sidebar section after organization links

Co-Authored-By: unknown <>

* feat(calcom): add admin flags page with expandable frame sections

Co-Authored-By: unknown <>

* fix(calcom): use lowercase admin flag group labels

Co-Authored-By: unknown <>

* mc

* feat(calcom): prototype assign-users sheet for flags

Co-Authored-By: unknown <>

* refactor(calcom): use switches in assign-users sheet

Co-Authored-By: unknown <>

* refactor(calcom): add tooltip to flag switch

Co-Authored-By: unknown <>

* feat(calcom): add load more button to assign-users sheet

Co-Authored-By: unknown <>

* feat(calcom): add admin billing page

Co-Authored-By: unknown <>

* fix(calcom): match admin billing page structure with billing page

Co-Authored-By: unknown <>

* mc

* mc

* feat(calcom): add admin impersonation page

Co-Authored-By: unknown <>

* mc

* mc

* feat(calcom): add admin OAuth clients page with status groups

Co-Authored-By: unknown <>

* fix(calcom): match admin oauth list items with developer/oauth pattern and add empty states

Co-Authored-By: unknown <>

* mc

* refactor(ui): clean up ListItem and remove unused ListItemDescription component

* mc

* mc

* improve admin billing

* implement apps prototype

* mc

* mc

* mc

* remove unused OAuthClientSubmittedDialog component and update ListItem styles for improved layout

* remove unneeded comments

* improve compliance layout

* update the settings toggle to reflect cal changes

* re-format

* re-format

* refactor: align list-item.tsx with cal's coss-ui version

Co-Authored-By: pasquale <pasqualevitiello@gmail.com>

* fix: revert ItemLabel import to relative path and widen SortableListeners type

Co-Authored-By: pasquale <pasqualevitiello@gmail.com>

* fix: widen SortableListeners to accept Function type from dnd-kit

Co-Authored-By: pasquale <pasqualevitiello@gmail.com>

* fix: revert SortableListeners to match cal's exact type signature

Co-Authored-By: pasquale <pasqualevitiello@gmail.com>

* fix: restore SyntheticListenerMap import from dnd-kit (coss has dnd-kit installed)

Co-Authored-By: pasquale <pasqualevitiello@gmail.com>

* build registry

* update toggle

* fix toggles

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-04-01 10:57:54 +02:00

73 lines
2.7 KiB
TypeScript

"use client";
import { Checkbox } from "@coss/ui/components/checkbox";
import { CheckboxGroup } from "@coss/ui/components/checkbox-group";
import { FieldItem, FieldLabel } from "@coss/ui/components/field";
import Image from "next/image";
export interface ImageCheckboxOptionItem {
label: string;
value: string;
imageSrc: string;
}
export interface ImageCheckboxOptionProps {
items: ImageCheckboxOptionItem[];
defaultValue?: string[];
/** Controlled mode: which items are checked. */
value?: string[];
/** Called when checked items change. */
onValueChange?: (value: string[]) => void;
/** Value of the item that is the default. Shows "Default" after its label when set. */
defaultItem?: string;
}
export function ImageCheckboxOption({
items,
defaultValue,
value,
onValueChange,
defaultItem,
}: ImageCheckboxOptionProps) {
const isControlled = value != null && onValueChange != null;
return (
<CheckboxGroup
className="flex w-full flex-row gap-4 md:gap-6"
defaultValue={
!isControlled ? (defaultValue ?? items.map((i) => i.value)) : undefined
}
onValueChange={onValueChange}
value={isControlled ? value : undefined}
>
{items.map((item) => (
<FieldItem className="flex-1" key={item.value}>
<FieldLabel className="grid w-full cursor-pointer grid-cols-[auto_1fr] grid-rows-[auto_auto] gap-x-2 gap-y-3 max-sm:grid-cols-1">
<Checkbox
className="peer col-start-1 row-start-2 shrink-0 max-sm:hidden"
value={item.value}
/>
<span className="relative col-span-2 row-start-1 block aspect-208/120 w-full min-w-0 overflow-hidden rounded-lg not-peer-data-checked:opacity-80 shadow-xs transition-[box-shadow,opacity] peer-data-disabled:cursor-not-allowed peer-data-disabled:opacity-64 peer-data-checked:ring-2 peer-data-checked:ring-primary peer-data-checked:ring-offset-1 peer-data-checked:ring-offset-background max-sm:col-span-1">
<Image
alt={item.label}
className="h-full w-full object-cover object-center shadow-xs"
fill
sizes="(min-width: 0) 100vw"
src={item.imageSrc}
/>
</span>
<span className="col-start-2 row-start-2 flex items-center gap-1 self-center not-peer-data-checked:text-muted-foreground/72 max-sm:col-start-1 max-sm:justify-self-center max-sm:text-center">
{item.label}
{defaultItem === item.value && (
<span className="font-normal text-muted-foreground">
(default)
</span>
)}
</span>
</FieldLabel>
</FieldItem>
))}
</CheckboxGroup>
);
}