@ably/ui 17.9.6 → 17.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- import{useCallback,useMemo}from"react";import Badge from"./Badge";import FeaturedLink from"./FeaturedLink";import Icon from"./Icon";import cn from"./utils/cn";const ContentTile=({title,className,description,cta,feature,featureType="image",featureIcons,centerFeature,badges,onClick,featureClassName,titleClassName,descriptionClassName,ctaClassName,featurePadding=true,encapsulated=true})=>{const handleClick=useCallback(()=>{if(!cta)return;if(onClick){onClick(cta.url)}else{window.location.href=cta.url}},[onClick,cta]);const renderedFeature=useMemo(()=>{if(!feature)return null;if(featureType==="image"){return React.createElement("div",{className:cn("content-tile__feature relative p-3 h-[200px] pb-0 flex items-end justify-center overflow-hidden rounded-lg bg-neutral-100 dark:bg-neutral-1200 border border-neutral-300 dark:border-neutral-1000 transition-[border-color,height]",centerFeature&&"items-center pb-3",cta&&!encapsulated&&"group-hover/content-tile:border-neutral-500 dark:group-hover/content-tile:border-neutral-800 transition-colors",featureClassName)},React.createElement("div",{className:cn("flex justify-center max-h-[200px]",!centerFeature&&"[&_img]:min-w-max [&_img]:h-[200px]",featurePadding&&!centerFeature&&"pt-6")},feature),featureIcons&&featureIcons?.length>0&&React.createElement("div",{className:"absolute bottom-3 right-3 flex gap-1.5 bg-neutral-000 dark:bg-neutral-1300 rounded border border-neutral-200 dark:border-neutral-1100 px-2 py-1.5"},featureIcons.map((icon,idx)=>React.createElement(Icon,{key:icon+idx,name:icon,size:"18px"}))))}if(featureType==="icon"){return React.createElement("div",{className:cn("h-9",featureClassName)},typeof feature==="string"?React.createElement(Icon,{name:feature,size:"36px"}):feature)}return null},[centerFeature,feature,featureClassName,featureIcons,encapsulated,featurePadding,featureType,cta]);return React.createElement("div",{className:cn("group/content-tile",encapsulated&&"p-5 border border-neutral-300 dark:border-neutral-1000 rounded-lg",cta&&"cursor-pointer",cta&&encapsulated&&"hover:border-neutral-500 dark:hover:border-neutral-800 transition-colors",className),...cta&&{onClick:handleClick,onKeyDown:e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();handleClick()}},tabIndex:0,role:"link","aria-label":title}},renderedFeature,React.createElement("div",{className:"content-tile__content pr-4"},title&&React.createElement("h2",{className:cn("content-tile__title mb-2 ui-text-h4 text-neutral-1300 dark:text-neutral-000",feature&&"mt-4",titleClassName)},title),description&&React.createElement("div",{className:cn("content-tile__description ui-text-p2 text-neutral-1000 dark:text-neutral-300",cta&&"text-neutral-800 dark:text-neutral-500 group-hover/content-tile:text-neutral-1000 dark:group-hover/content-tile:text-neutral-300 transition-colors",(badges||cta&&!cta.implicit)&&"mb-2",descriptionClassName)},description),badges&&badges.length>0&&React.createElement("div",{className:"content-tile__badges mb-2 flex flex-wrap gap-2"},badges.map(({label,className,...badgeProps},idx)=>React.createElement(Badge,{key:label+idx,className:cn("uppercase text-[10px]",className),...badgeProps},label))),cta&&!cta.implicit&&React.createElement(FeaturedLink,{url:"#",additionalCSS:cn("py-0 pointer-events-none font-medium items-center text-neutral-800 dark:text-neutral-500 group-hover/content-tile:text-neutral-1300 dark:group-hover/content-tile:text-neutral-000 transition-colors [&_svg]:group-hover/content-tile:left-0",ctaClassName),iconColor:"text-orange-600"},cta.text)))};export default ContentTile;
1
+ import React,{useCallback,useMemo}from"react";import Badge from"./Badge";import FeaturedLink from"./FeaturedLink";import Icon from"./Icon";import cn from"./utils/cn";const ContentTile=({title,className,description,cta,feature,featureType="image",featureIcons,centerFeature,badges,onClick,featureClassName,titleClassName,descriptionClassName,ctaClassName,featurePadding=true,encapsulated=true})=>{const handleClick=useCallback(()=>{if(!cta)return;if(onClick){onClick(cta.url)}else{window.location.href=cta.url}},[onClick,cta]);const renderedFeature=useMemo(()=>{if(!feature)return null;if(featureType==="image"){return React.createElement("div",{className:cn("content-tile__feature relative p-3 h-[200px] pb-0 flex items-end justify-center overflow-hidden rounded-lg bg-neutral-100 dark:bg-neutral-1200 border border-neutral-300 dark:border-neutral-1000 transition-[border-color,height]",centerFeature&&"items-center pb-3",cta&&!encapsulated&&"group-hover/content-tile:border-neutral-500 dark:group-hover/content-tile:border-neutral-800 transition-colors",featureClassName)},React.createElement("div",{className:cn("flex justify-center max-h-[200px]",!centerFeature&&"[&_img]:min-w-max [&_img]:h-[200px]",featurePadding&&!centerFeature&&"pt-6")},feature),featureIcons&&featureIcons?.length>0&&React.createElement("div",{className:"absolute bottom-3 right-3 flex gap-1.5 bg-neutral-000 dark:bg-neutral-1300 rounded border border-neutral-200 dark:border-neutral-1100 px-2 py-1.5"},featureIcons.map((icon,idx)=>React.createElement(Icon,{key:icon+idx,name:icon,size:"18px"}))))}if(featureType==="icon"){return React.createElement("div",{className:cn("h-9",featureClassName)},typeof feature==="string"?React.createElement(Icon,{name:feature,size:"36px"}):feature)}return null},[centerFeature,feature,featureClassName,featureIcons,encapsulated,featurePadding,featureType,cta]);return React.createElement("div",{className:cn("group/content-tile",encapsulated&&"p-5 border border-neutral-300 dark:border-neutral-1000 rounded-lg",cta&&"cursor-pointer",cta&&encapsulated&&"hover:border-neutral-500 dark:hover:border-neutral-800 transition-colors",className),...cta&&{onClick:handleClick,onKeyDown:e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();handleClick()}},tabIndex:0,role:"link","aria-label":title}},renderedFeature,React.createElement("div",{className:"content-tile__content pr-4"},title&&React.createElement("h2",{className:cn("content-tile__title mb-2 ui-text-h4 text-neutral-1300 dark:text-neutral-000",feature&&"mt-4",titleClassName)},title),description&&React.createElement("div",{className:cn("content-tile__description ui-text-p2 text-neutral-1000 dark:text-neutral-300",cta&&"text-neutral-800 dark:text-neutral-500 group-hover/content-tile:text-neutral-1000 dark:group-hover/content-tile:text-neutral-300 transition-colors",(badges||cta&&!cta.implicit)&&"mb-2",descriptionClassName)},description),badges&&badges.length>0&&React.createElement("div",{className:"content-tile__badges mb-2 flex flex-wrap gap-2"},badges.map(({label,className,...badgeProps},idx)=>React.createElement(Badge,{key:label+idx,className:cn("uppercase text-[10px]",className),...badgeProps},label))),cta&&!cta.implicit&&React.createElement(FeaturedLink,{url:"#",additionalCSS:cn("py-0 pointer-events-none font-medium items-center text-neutral-800 dark:text-neutral-500 group-hover/content-tile:text-neutral-1300 dark:group-hover/content-tile:text-neutral-000 transition-colors [&_svg]:group-hover/content-tile:left-0",ctaClassName),iconColor:"text-orange-600"},cta.text)))};export default ContentTile;
2
2
  //# sourceMappingURL=ContentTile.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/ContentTile.tsx"],"sourcesContent":["import type React from \"react\";\nimport { useCallback, useMemo } from \"react\";\nimport Badge, { type BadgeProps } from \"./Badge\";\nimport FeaturedLink from \"./FeaturedLink\";\nimport Icon from \"./Icon\";\nimport type { IconName } from \"./Icon/types\";\nimport cn from \"./utils/cn\";\n\ntype ContentTileProps = {\n /** The title text to display */\n title?: string;\n /** Additional CSS classes for the root container */\n className?: string;\n /** The description text to display */\n description?: string;\n /**\n * Call-to-action configuration.\n * - text: The CTA button or link text.\n * - url: The destination URL for the CTA.\n * - implicit: If true, no explicit CTA button is shown.\n */\n cta?: {\n text: string;\n url: string;\n implicit?: boolean;\n };\n /** Content to display in the feature area (image or icon) */\n feature?: React.ReactNode | string;\n /** Type of feature to render - either 'image' or 'icon' */\n featureType?: \"image\" | \"icon\";\n /** Array of icon names to display as overlays on the feature */\n featureIcons?: IconName[];\n /** Whether to vertically center the feature content */\n centerFeature?: boolean;\n /** Array of badges to display */\n badges?: (BadgeProps & { label: string })[];\n /** Custom click handler, receives the CTA URL if present */\n onClick?: (url?: string) => void;\n /** Additional CSS classes for the feature element */\n featureClassName?: string;\n /** Additional CSS classes for the title element */\n titleClassName?: string;\n /** Additional CSS classes for the description element */\n descriptionClassName?: string;\n /** Additional CSS classes for the CTA element */\n ctaClassName?: string;\n /** Whether to add padding-top to the feature content (default: true) */\n featurePadding?: boolean;\n /** Whether to encapsulate the content tile in an outer container (default: true) */\n encapsulated?: boolean;\n};\n\nconst ContentTile: React.FC<ContentTileProps> = ({\n title,\n className,\n description,\n cta,\n feature,\n featureType = \"image\",\n featureIcons,\n centerFeature,\n badges,\n onClick,\n featureClassName,\n titleClassName,\n descriptionClassName,\n ctaClassName,\n featurePadding = true,\n encapsulated = true,\n}) => {\n const handleClick = useCallback(() => {\n if (!cta) return;\n\n if (onClick) {\n onClick(cta.url);\n } else {\n window.location.href = cta.url;\n }\n }, [onClick, cta]);\n\n const renderedFeature = useMemo(() => {\n if (!feature) return null;\n\n if (featureType === \"image\") {\n return (\n <div\n className={cn(\n \"content-tile__feature relative p-3 h-[200px] pb-0 flex items-end justify-center overflow-hidden rounded-lg bg-neutral-100 dark:bg-neutral-1200 border border-neutral-300 dark:border-neutral-1000 transition-[border-color,height]\",\n centerFeature && \"items-center pb-3\",\n cta &&\n !encapsulated &&\n \"group-hover/content-tile:border-neutral-500 dark:group-hover/content-tile:border-neutral-800 transition-colors\",\n featureClassName,\n )}\n >\n <div\n className={cn(\n \"flex justify-center max-h-[200px]\",\n !centerFeature && \"[&_img]:min-w-max [&_img]:h-[200px]\",\n featurePadding && !centerFeature && \"pt-6\",\n )}\n >\n {feature}\n </div>\n {featureIcons && featureIcons?.length > 0 && (\n <div className=\"absolute bottom-3 right-3 flex gap-1.5 bg-neutral-000 dark:bg-neutral-1300 rounded border border-neutral-200 dark:border-neutral-1100 px-2 py-1.5\">\n {featureIcons.map((icon, idx) => (\n <Icon key={icon + idx} name={icon} size=\"18px\" />\n ))}\n </div>\n )}\n </div>\n );\n }\n\n if (featureType === \"icon\") {\n return (\n <div className={cn(\"h-9\", featureClassName)}>\n {typeof feature === \"string\" ? (\n <Icon name={feature as IconName} size=\"36px\" />\n ) : (\n feature\n )}\n </div>\n );\n }\n\n return null;\n }, [\n centerFeature,\n feature,\n featureClassName,\n featureIcons,\n encapsulated,\n featurePadding,\n featureType,\n cta,\n ]);\n\n return (\n <div\n className={cn(\n \"group/content-tile\",\n encapsulated &&\n \"p-5 border border-neutral-300 dark:border-neutral-1000 rounded-lg\",\n cta && \"cursor-pointer\",\n cta &&\n encapsulated &&\n \"hover:border-neutral-500 dark:hover:border-neutral-800 transition-colors\",\n className,\n )}\n {...(cta && {\n onClick: handleClick,\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleClick();\n }\n },\n tabIndex: 0,\n role: \"link\",\n \"aria-label\": title,\n })}\n >\n {renderedFeature}\n <div className=\"content-tile__content pr-4\">\n {title && (\n <h2\n className={cn(\n \"content-tile__title mb-2 ui-text-h4 text-neutral-1300 dark:text-neutral-000\",\n feature && \"mt-4\",\n titleClassName,\n )}\n >\n {title}\n </h2>\n )}\n {description && (\n <div\n className={cn(\n \"content-tile__description ui-text-p2 text-neutral-1000 dark:text-neutral-300\",\n cta &&\n \"text-neutral-800 dark:text-neutral-500 group-hover/content-tile:text-neutral-1000 dark:group-hover/content-tile:text-neutral-300 transition-colors\",\n (badges || (cta && !cta.implicit)) && \"mb-2\",\n descriptionClassName,\n )}\n >\n {description}\n </div>\n )}\n {badges && badges.length > 0 && (\n <div className=\"content-tile__badges mb-2 flex flex-wrap gap-2\">\n {badges.map(({ label, className, ...badgeProps }, idx) => (\n <Badge\n key={label + idx}\n className={cn(\"uppercase text-[10px]\", className)}\n {...badgeProps}\n >\n {label}\n </Badge>\n ))}\n </div>\n )}\n {cta && !cta.implicit && (\n <FeaturedLink\n url=\"#\"\n additionalCSS={cn(\n \"py-0 pointer-events-none font-medium items-center text-neutral-800 dark:text-neutral-500 group-hover/content-tile:text-neutral-1300 dark:group-hover/content-tile:text-neutral-000 transition-colors [&_svg]:group-hover/content-tile:left-0\",\n ctaClassName,\n )}\n iconColor=\"text-orange-600\"\n >\n {cta.text}\n </FeaturedLink>\n )}\n </div>\n </div>\n );\n};\n\nexport default ContentTile;\n"],"names":["useCallback","useMemo","Badge","FeaturedLink","Icon","cn","ContentTile","title","className","description","cta","feature","featureType","featureIcons","centerFeature","badges","onClick","featureClassName","titleClassName","descriptionClassName","ctaClassName","featurePadding","encapsulated","handleClick","url","window","location","href","renderedFeature","div","length","map","icon","idx","key","name","size","onKeyDown","e","preventDefault","tabIndex","role","h2","implicit","label","badgeProps","additionalCSS","iconColor","text"],"mappings":"AACA,OAASA,WAAW,CAAEC,OAAO,KAAQ,OAAQ,AAC7C,QAAOC,UAAgC,SAAU,AACjD,QAAOC,iBAAkB,gBAAiB,AAC1C,QAAOC,SAAU,QAAS,AAE1B,QAAOC,OAAQ,YAAa,CA8C5B,MAAMC,YAA0C,CAAC,CAC/CC,KAAK,CACLC,SAAS,CACTC,WAAW,CACXC,GAAG,CACHC,OAAO,CACPC,YAAc,OAAO,CACrBC,YAAY,CACZC,aAAa,CACbC,MAAM,CACNC,OAAO,CACPC,gBAAgB,CAChBC,cAAc,CACdC,oBAAoB,CACpBC,YAAY,CACZC,eAAiB,IAAI,CACrBC,aAAe,IAAI,CACpB,IACC,MAAMC,YAAcvB,YAAY,KAC9B,GAAI,CAACU,IAAK,OAEV,GAAIM,QAAS,CACXA,QAAQN,IAAIc,GAAG,CACjB,KAAO,CACLC,OAAOC,QAAQ,CAACC,IAAI,CAAGjB,IAAIc,GAAG,AAChC,CACF,EAAG,CAACR,QAASN,IAAI,EAEjB,MAAMkB,gBAAkB3B,QAAQ,KAC9B,GAAI,CAACU,QAAS,OAAO,KAErB,GAAIC,cAAgB,QAAS,CAC3B,OACE,oBAACiB,OACCrB,UAAWH,GACT,qOACAS,eAAiB,oBACjBJ,KACE,CAACY,cACD,iHACFL,mBAGF,oBAACY,OACCrB,UAAWH,GACT,oCACA,CAACS,eAAiB,sCAClBO,gBAAkB,CAACP,eAAiB,SAGrCH,SAEFE,cAAgBA,cAAciB,OAAS,GACtC,oBAACD,OAAIrB,UAAU,qJACZK,aAAakB,GAAG,CAAC,CAACC,KAAMC,MACvB,oBAAC7B,MAAK8B,IAAKF,KAAOC,IAAKE,KAAMH,KAAMI,KAAK,WAMpD,CAEA,GAAIxB,cAAgB,OAAQ,CAC1B,OACE,oBAACiB,OAAIrB,UAAWH,GAAG,MAAOY,mBACvB,OAAON,UAAY,SAClB,oBAACP,MAAK+B,KAAMxB,QAAqByB,KAAK,SAEtCzB,QAIR,CAEA,OAAO,IACT,EAAG,CACDG,cACAH,QACAM,iBACAJ,aACAS,aACAD,eACAT,YACAF,IACD,EAED,OACE,oBAACmB,OACCrB,UAAWH,GACT,qBACAiB,cACE,oEACFZ,KAAO,iBACPA,KACEY,cACA,2EACFd,WAED,GAAIE,KAAO,CACVM,QAASO,YACTc,UAAW,AAACC,IACV,GAAIA,EAAEJ,GAAG,GAAK,SAAWI,EAAEJ,GAAG,GAAK,IAAK,CACtCI,EAAEC,cAAc,GAChBhB,aACF,CACF,EACAiB,SAAU,EACVC,KAAM,OACN,aAAclC,KAChB,CAAC,EAEAqB,gBACD,oBAACC,OAAIrB,UAAU,8BACZD,OACC,oBAACmC,MACClC,UAAWH,GACT,8EACAM,SAAW,OACXO,iBAGDX,OAGJE,aACC,oBAACoB,OACCrB,UAAWH,GACT,+EACAK,KACE,qJACF,AAACK,CAAAA,QAAWL,KAAO,CAACA,IAAIiC,QAAQ,GAAM,OACtCxB,uBAGDV,aAGJM,QAAUA,OAAOe,MAAM,CAAG,GACzB,oBAACD,OAAIrB,UAAU,kDACZO,OAAOgB,GAAG,CAAC,CAAC,CAAEa,KAAK,CAAEpC,SAAS,CAAE,GAAGqC,WAAY,CAAEZ,MAChD,oBAAC/B,OACCgC,IAAKU,MAAQX,IACbzB,UAAWH,GAAG,wBAAyBG,WACtC,GAAGqC,UAAU,EAEbD,SAKRlC,KAAO,CAACA,IAAIiC,QAAQ,EACnB,oBAACxC,cACCqB,IAAI,IACJsB,cAAezC,GACb,+OACAe,cAEF2B,UAAU,mBAETrC,IAAIsC,IAAI,GAMrB,CAEA,gBAAe1C,WAAY"}
1
+ {"version":3,"sources":["../../src/core/ContentTile.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport Badge, { type BadgeProps } from \"./Badge\";\nimport FeaturedLink from \"./FeaturedLink\";\nimport Icon from \"./Icon\";\nimport type { IconName } from \"./Icon/types\";\nimport cn from \"./utils/cn\";\n\ntype ContentTileProps = {\n /** The title text to display */\n title?: string;\n /** Additional CSS classes for the root container */\n className?: string;\n /** The description content to display (text or React elements) */\n description?: string | React.ReactNode;\n /**\n * Call-to-action configuration.\n * - text: The CTA button or link text.\n * - url: The destination URL for the CTA.\n * - implicit: If true, no explicit CTA button is shown.\n */\n cta?: {\n text: string;\n url: string;\n implicit?: boolean;\n };\n /** Content to display in the feature area (image or icon) */\n feature?: React.ReactNode | string;\n /** Type of feature to render - either 'image' or 'icon' */\n featureType?: \"image\" | \"icon\";\n /** Array of icon names to display as overlays on the feature */\n featureIcons?: IconName[];\n /** Whether to vertically center the feature content */\n centerFeature?: boolean;\n /** Array of badges to display */\n badges?: (BadgeProps & { label: string })[];\n /** Custom click handler, receives the CTA URL if present */\n onClick?: (url?: string) => void;\n /** Additional CSS classes for the feature element */\n featureClassName?: string;\n /** Additional CSS classes for the title element */\n titleClassName?: string;\n /** Additional CSS classes for the description element */\n descriptionClassName?: string;\n /** Additional CSS classes for the CTA element */\n ctaClassName?: string;\n /** Whether to add padding-top to the feature content (default: true) */\n featurePadding?: boolean;\n /** Whether to encapsulate the content tile in an outer container (default: true) */\n encapsulated?: boolean;\n};\n\nconst ContentTile: React.FC<ContentTileProps> = ({\n title,\n className,\n description,\n cta,\n feature,\n featureType = \"image\",\n featureIcons,\n centerFeature,\n badges,\n onClick,\n featureClassName,\n titleClassName,\n descriptionClassName,\n ctaClassName,\n featurePadding = true,\n encapsulated = true,\n}) => {\n const handleClick = useCallback(() => {\n if (!cta) return;\n\n if (onClick) {\n onClick(cta.url);\n } else {\n window.location.href = cta.url;\n }\n }, [onClick, cta]);\n\n const renderedFeature = useMemo(() => {\n if (!feature) return null;\n\n if (featureType === \"image\") {\n return (\n <div\n className={cn(\n \"content-tile__feature relative p-3 h-[200px] pb-0 flex items-end justify-center overflow-hidden rounded-lg bg-neutral-100 dark:bg-neutral-1200 border border-neutral-300 dark:border-neutral-1000 transition-[border-color,height]\",\n centerFeature && \"items-center pb-3\",\n cta &&\n !encapsulated &&\n \"group-hover/content-tile:border-neutral-500 dark:group-hover/content-tile:border-neutral-800 transition-colors\",\n featureClassName,\n )}\n >\n <div\n className={cn(\n \"flex justify-center max-h-[200px]\",\n !centerFeature && \"[&_img]:min-w-max [&_img]:h-[200px]\",\n featurePadding && !centerFeature && \"pt-6\",\n )}\n >\n {feature}\n </div>\n {featureIcons && featureIcons?.length > 0 && (\n <div className=\"absolute bottom-3 right-3 flex gap-1.5 bg-neutral-000 dark:bg-neutral-1300 rounded border border-neutral-200 dark:border-neutral-1100 px-2 py-1.5\">\n {featureIcons.map((icon, idx) => (\n <Icon key={icon + idx} name={icon} size=\"18px\" />\n ))}\n </div>\n )}\n </div>\n );\n }\n\n if (featureType === \"icon\") {\n return (\n <div className={cn(\"h-9\", featureClassName)}>\n {typeof feature === \"string\" ? (\n <Icon name={feature as IconName} size=\"36px\" />\n ) : (\n feature\n )}\n </div>\n );\n }\n\n return null;\n }, [\n centerFeature,\n feature,\n featureClassName,\n featureIcons,\n encapsulated,\n featurePadding,\n featureType,\n cta,\n ]);\n\n return (\n <div\n className={cn(\n \"group/content-tile\",\n encapsulated &&\n \"p-5 border border-neutral-300 dark:border-neutral-1000 rounded-lg\",\n cta && \"cursor-pointer\",\n cta &&\n encapsulated &&\n \"hover:border-neutral-500 dark:hover:border-neutral-800 transition-colors\",\n className,\n )}\n {...(cta && {\n onClick: handleClick,\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleClick();\n }\n },\n tabIndex: 0,\n role: \"link\",\n \"aria-label\": title,\n })}\n >\n {renderedFeature}\n <div className=\"content-tile__content pr-4\">\n {title && (\n <h2\n className={cn(\n \"content-tile__title mb-2 ui-text-h4 text-neutral-1300 dark:text-neutral-000\",\n feature && \"mt-4\",\n titleClassName,\n )}\n >\n {title}\n </h2>\n )}\n {description && (\n <div\n className={cn(\n \"content-tile__description ui-text-p2 text-neutral-1000 dark:text-neutral-300\",\n cta &&\n \"text-neutral-800 dark:text-neutral-500 group-hover/content-tile:text-neutral-1000 dark:group-hover/content-tile:text-neutral-300 transition-colors\",\n (badges || (cta && !cta.implicit)) && \"mb-2\",\n descriptionClassName,\n )}\n >\n {description}\n </div>\n )}\n {badges && badges.length > 0 && (\n <div className=\"content-tile__badges mb-2 flex flex-wrap gap-2\">\n {badges.map(({ label, className, ...badgeProps }, idx) => (\n <Badge\n key={label + idx}\n className={cn(\"uppercase text-[10px]\", className)}\n {...badgeProps}\n >\n {label}\n </Badge>\n ))}\n </div>\n )}\n {cta && !cta.implicit && (\n <FeaturedLink\n url=\"#\"\n additionalCSS={cn(\n \"py-0 pointer-events-none font-medium items-center text-neutral-800 dark:text-neutral-500 group-hover/content-tile:text-neutral-1300 dark:group-hover/content-tile:text-neutral-000 transition-colors [&_svg]:group-hover/content-tile:left-0\",\n ctaClassName,\n )}\n iconColor=\"text-orange-600\"\n >\n {cta.text}\n </FeaturedLink>\n )}\n </div>\n </div>\n );\n};\n\nexport default ContentTile;\n"],"names":["React","useCallback","useMemo","Badge","FeaturedLink","Icon","cn","ContentTile","title","className","description","cta","feature","featureType","featureIcons","centerFeature","badges","onClick","featureClassName","titleClassName","descriptionClassName","ctaClassName","featurePadding","encapsulated","handleClick","url","window","location","href","renderedFeature","div","length","map","icon","idx","key","name","size","onKeyDown","e","preventDefault","tabIndex","role","h2","implicit","label","badgeProps","additionalCSS","iconColor","text"],"mappings":"AAAA,OAAOA,OAASC,WAAW,CAAEC,OAAO,KAAQ,OAAQ,AACpD,QAAOC,UAAgC,SAAU,AACjD,QAAOC,iBAAkB,gBAAiB,AAC1C,QAAOC,SAAU,QAAS,AAE1B,QAAOC,OAAQ,YAAa,CA8C5B,MAAMC,YAA0C,CAAC,CAC/CC,KAAK,CACLC,SAAS,CACTC,WAAW,CACXC,GAAG,CACHC,OAAO,CACPC,YAAc,OAAO,CACrBC,YAAY,CACZC,aAAa,CACbC,MAAM,CACNC,OAAO,CACPC,gBAAgB,CAChBC,cAAc,CACdC,oBAAoB,CACpBC,YAAY,CACZC,eAAiB,IAAI,CACrBC,aAAe,IAAI,CACpB,IACC,MAAMC,YAAcvB,YAAY,KAC9B,GAAI,CAACU,IAAK,OAEV,GAAIM,QAAS,CACXA,QAAQN,IAAIc,GAAG,CACjB,KAAO,CACLC,OAAOC,QAAQ,CAACC,IAAI,CAAGjB,IAAIc,GAAG,AAChC,CACF,EAAG,CAACR,QAASN,IAAI,EAEjB,MAAMkB,gBAAkB3B,QAAQ,KAC9B,GAAI,CAACU,QAAS,OAAO,KAErB,GAAIC,cAAgB,QAAS,CAC3B,OACE,oBAACiB,OACCrB,UAAWH,GACT,qOACAS,eAAiB,oBACjBJ,KACE,CAACY,cACD,iHACFL,mBAGF,oBAACY,OACCrB,UAAWH,GACT,oCACA,CAACS,eAAiB,sCAClBO,gBAAkB,CAACP,eAAiB,SAGrCH,SAEFE,cAAgBA,cAAciB,OAAS,GACtC,oBAACD,OAAIrB,UAAU,qJACZK,aAAakB,GAAG,CAAC,CAACC,KAAMC,MACvB,oBAAC7B,MAAK8B,IAAKF,KAAOC,IAAKE,KAAMH,KAAMI,KAAK,WAMpD,CAEA,GAAIxB,cAAgB,OAAQ,CAC1B,OACE,oBAACiB,OAAIrB,UAAWH,GAAG,MAAOY,mBACvB,OAAON,UAAY,SAClB,oBAACP,MAAK+B,KAAMxB,QAAqByB,KAAK,SAEtCzB,QAIR,CAEA,OAAO,IACT,EAAG,CACDG,cACAH,QACAM,iBACAJ,aACAS,aACAD,eACAT,YACAF,IACD,EAED,OACE,oBAACmB,OACCrB,UAAWH,GACT,qBACAiB,cACE,oEACFZ,KAAO,iBACPA,KACEY,cACA,2EACFd,WAED,GAAIE,KAAO,CACVM,QAASO,YACTc,UAAW,AAACC,IACV,GAAIA,EAAEJ,GAAG,GAAK,SAAWI,EAAEJ,GAAG,GAAK,IAAK,CACtCI,EAAEC,cAAc,GAChBhB,aACF,CACF,EACAiB,SAAU,EACVC,KAAM,OACN,aAAclC,KAChB,CAAC,EAEAqB,gBACD,oBAACC,OAAIrB,UAAU,8BACZD,OACC,oBAACmC,MACClC,UAAWH,GACT,8EACAM,SAAW,OACXO,iBAGDX,OAGJE,aACC,oBAACoB,OACCrB,UAAWH,GACT,+EACAK,KACE,qJACF,AAACK,CAAAA,QAAWL,KAAO,CAACA,IAAIiC,QAAQ,GAAM,OACtCxB,uBAGDV,aAGJM,QAAUA,OAAOe,MAAM,CAAG,GACzB,oBAACD,OAAIrB,UAAU,kDACZO,OAAOgB,GAAG,CAAC,CAAC,CAAEa,KAAK,CAAEpC,SAAS,CAAE,GAAGqC,WAAY,CAAEZ,MAChD,oBAAC/B,OACCgC,IAAKU,MAAQX,IACbzB,UAAWH,GAAG,wBAAyBG,WACtC,GAAGqC,UAAU,EAEbD,SAKRlC,KAAO,CAACA,IAAIiC,QAAQ,EACnB,oBAACxC,cACCqB,IAAI,IACJsB,cAAezC,GACb,+OACAe,cAEF2B,UAAU,mBAETrC,IAAIsC,IAAI,GAMrB,CAEA,gBAAe1C,WAAY"}
package/index.d.ts CHANGED
@@ -476,7 +476,7 @@ export default ConnectStateWrapper;
476
476
  }
477
477
 
478
478
  declare module '@ably/ui/core/ContentTile' {
479
- import type React from "react";
479
+ import React from "react";
480
480
  import { type BadgeProps } from "@ably/ui/core/Badge";
481
481
  import type { IconName } from "@ably/ui/core/Icon/types";
482
482
  type ContentTileProps = {
@@ -484,8 +484,8 @@ type ContentTileProps = {
484
484
  title?: string;
485
485
  /** Additional CSS classes for the root container */
486
486
  className?: string;
487
- /** The description text to display */
488
- description?: string;
487
+ /** The description content to display (text or React elements) */
488
+ description?: string | React.ReactNode;
489
489
  /**
490
490
  * Call-to-action configuration.
491
491
  * - text: The CTA button or link text.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ably/ui",
3
- "version": "17.9.6",
3
+ "version": "17.9.7",
4
4
  "description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,7 +38,7 @@
38
38
  "@vitejs/plugin-react-swc": "^4.0.1",
39
39
  "@vitest/browser": "3.2.4",
40
40
  "@vitest/coverage-v8": "3.2.4",
41
- "@vueless/storybook-dark-mode": "^9.0.8",
41
+ "@vueless/storybook-dark-mode": "^10.0.1",
42
42
  "autoprefixer": "^10.0.2",
43
43
  "eslint": "^8.57.1",
44
44
  "eslint-config-prettier": "^10.1.8",