Adjust button hover
This commit is contained in:
@@ -88,7 +88,7 @@ function CustomMethodCardWizardViewComponent({
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{!fieldTypeModal && wizardStep === 3 ? (
|
{!fieldTypeModal && wizardStep === 3 ? (
|
||||||
<div className="flex w-full flex-col gap-4">
|
<div className="flex w-full flex-col gap-4 pt-1">
|
||||||
{draftFieldBlocks.length > 0 ? (
|
{draftFieldBlocks.length > 0 ? (
|
||||||
<CustomMethodCardWizardBlocksList
|
<CustomMethodCardWizardBlocksList
|
||||||
blocks={draftFieldBlocks}
|
blocks={draftFieldBlocks}
|
||||||
|
|||||||
+17
-9
@@ -40,19 +40,27 @@ function CustomMethodCardWizardBlocksListViewComponent({
|
|||||||
onDragEnd,
|
onDragEnd,
|
||||||
}: CustomMethodCardWizardBlocksListViewProps) {
|
}: CustomMethodCardWizardBlocksListViewProps) {
|
||||||
return (
|
return (
|
||||||
<ul className="flex list-none flex-col gap-2 p-0" aria-label={listLabel}>
|
<ul
|
||||||
|
className="flex list-none flex-col gap-2 p-0 pt-1"
|
||||||
|
aria-label={listLabel}
|
||||||
|
>
|
||||||
{blocks.map((block, index) => {
|
{blocks.map((block, index) => {
|
||||||
const kind = block.kind as AddCustomFieldType;
|
const kind = block.kind as AddCustomFieldType;
|
||||||
const typeLabel = fieldTypeLabels[kind];
|
const typeLabel = fieldTypeLabels[kind];
|
||||||
const isOver = overIndex === index && draggingIndex !== index;
|
const title = block.blockTitle.trim() || typeLabel;
|
||||||
|
const isDragging = draggingIndex === index;
|
||||||
|
const isDropTarget = overIndex === index && draggingIndex !== index;
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
key={block.id}
|
key={block.id}
|
||||||
className={`flex min-h-[52px] items-stretch gap-2 rounded-[var(--measures-radius-medium,8px)] border border-[var(--color-border-default-primary)] bg-[var(--color-surface-default-secondary)] pl-1 pr-3 py-2 transition-shadow ${
|
aria-grabbed={isDragging ? true : undefined}
|
||||||
isOver
|
className={`group flex min-h-[52px] items-stretch gap-2 rounded-[var(--measures-radius-medium,8px)] border-2 bg-[var(--color-surface-default-secondary)] py-2 pl-1 pr-3 transition-[border-color,box-shadow,opacity] ${
|
||||||
? "ring-2 ring-[var(--color-border-invert-primary)] ring-offset-2 ring-offset-[var(--color-surface-default-primary)]"
|
isDropTarget
|
||||||
: ""
|
? "relative z-10 border-[var(--color-border-invert-primary)]"
|
||||||
} ${draggingIndex === index ? "opacity-60" : ""}`}
|
: isDragging
|
||||||
|
? "relative z-20 border-[var(--color-border-default-primary)] opacity-60 shadow-[0_4px_12px_rgba(0,0,0,0.12)]"
|
||||||
|
: "border-[var(--color-border-default-primary)] hover:border-[var(--color-content-default-secondary)]"
|
||||||
|
}`}
|
||||||
onDragOver={onDragOver(index)}
|
onDragOver={onDragOver(index)}
|
||||||
onDrop={onDrop(index)}
|
onDrop={onDrop(index)}
|
||||||
>
|
>
|
||||||
@@ -61,8 +69,8 @@ function CustomMethodCardWizardBlocksListViewComponent({
|
|||||||
draggable
|
draggable
|
||||||
onDragStart={onDragStart(index)}
|
onDragStart={onDragStart(index)}
|
||||||
onDragEnd={onDragEnd}
|
onDragEnd={onDragEnd}
|
||||||
className="flex shrink-0 cursor-grab touch-manipulation items-center justify-center rounded-[var(--measures-radius-200,8px)] border-0 bg-transparent px-1 text-[var(--color-content-default-secondary)] active:cursor-grabbing focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-invert-primary)]"
|
|
||||||
aria-label={dragHandleAriaLabel}
|
aria-label={dragHandleAriaLabel}
|
||||||
|
className="flex shrink-0 cursor-grab touch-manipulation items-center self-stretch rounded-[var(--measures-radius-200,8px)] border-0 bg-transparent px-1 text-[var(--color-content-default-secondary)] transition-colors active:cursor-grabbing focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--color-border-invert-primary)] group-hover:text-[var(--color-content-default-primary)]"
|
||||||
>
|
>
|
||||||
<DragHandleGlyph />
|
<DragHandleGlyph />
|
||||||
</button>
|
</button>
|
||||||
@@ -75,7 +83,7 @@ function CustomMethodCardWizardBlocksListViewComponent({
|
|||||||
</span>
|
</span>
|
||||||
<div className="flex min-w-0 flex-1 flex-col justify-center gap-0.5">
|
<div className="flex min-w-0 flex-1 flex-col justify-center gap-0.5">
|
||||||
<span className="truncate font-inter text-[14px] font-medium leading-[18px] text-[var(--color-content-default-primary)]">
|
<span className="truncate font-inter text-[14px] font-medium leading-[18px] text-[var(--color-content-default-primary)]">
|
||||||
{block.blockTitle.trim() || typeLabel}
|
{title}
|
||||||
</span>
|
</span>
|
||||||
<span className="font-inter text-[12px] leading-4 text-[var(--color-content-default-secondary)]">
|
<span className="font-inter text-[12px] leading-4 text-[var(--color-content-default-secondary)]">
|
||||||
{typeLabel}
|
{typeLabel}
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ const CASE_STUDY_TILE_RADIUS_CLASS = "rounded-[23.093px]";
|
|||||||
|
|
||||||
const CASE_STUDY_LINK_CLASS = [
|
const CASE_STUDY_LINK_CLASS = [
|
||||||
CASE_STUDY_TILE_RADIUS_CLASS,
|
CASE_STUDY_TILE_RADIUS_CLASS,
|
||||||
"block shrink-0 cursor-pointer outline-none transition-transform duration-200",
|
"block shrink-0 cursor-pointer outline-none transition-[opacity,transform] duration-200",
|
||||||
"hover:scale-[1.02] hover:opacity-95",
|
"hover:opacity-95",
|
||||||
"focus-visible:ring-2 focus-visible:ring-[var(--color-border-default-brand-primary)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-default-primary)]",
|
"focus-visible:ring-2 focus-visible:ring-[var(--color-border-default-brand-primary)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-default-primary)]",
|
||||||
"active:scale-[0.98]",
|
"active:scale-[0.98]",
|
||||||
].join(" ");
|
].join(" ");
|
||||||
|
|||||||
@@ -102,15 +102,15 @@ const Logo = memo<LogoProps>(
|
|||||||
: "hidden";
|
: "hidden";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href="/" className="block" aria-label={t("logoAlt")}>
|
<Link href="/" className="group block" aria-label={t("logoAlt")}>
|
||||||
<div
|
<div
|
||||||
className={`flex items-center ${config.containerHeight} ${
|
className={`flex items-center ${config.containerHeight} ${
|
||||||
wordmark ? config.gap : ""
|
wordmark ? config.gap : ""
|
||||||
} transition-all duration-200 ease-in-out hover:scale-[1.02] cursor-pointer`}
|
} cursor-pointer`}
|
||||||
>
|
>
|
||||||
{/* Logo Text - responsive visibility for topNav sizes */}
|
{/* Logo Text - responsive visibility for topNav sizes */}
|
||||||
<div
|
<div
|
||||||
className={`font-bricolage-grotesque ${textColorClass} ${config.textSize} ${config.lineHeight} font-normal tracking-[0px] transition-colors duration-200 ${wordmarkVisibilityClass}`}
|
className={`font-bricolage-grotesque ${textColorClass} ${config.textSize} ${config.lineHeight} font-normal tracking-[0px] transition-opacity duration-200 ease-out group-hover:opacity-80 ${wordmarkVisibilityClass}`}
|
||||||
aria-label={t("logoText")}
|
aria-label={t("logoText")}
|
||||||
>
|
>
|
||||||
{t("logoText")}
|
{t("logoText")}
|
||||||
@@ -123,7 +123,7 @@ const Logo = memo<LogoProps>(
|
|||||||
alt={t("logoAlt")}
|
alt={t("logoAlt")}
|
||||||
width={27.05}
|
width={27.05}
|
||||||
height={27.05}
|
height={27.05}
|
||||||
className={`flex-shrink-0 ${config.iconSize} transition-all duration-200 ${
|
className={`flex-shrink-0 ${config.iconSize} origin-center transition-transform duration-200 ease-out group-hover:scale-110 ${
|
||||||
isInverse ? "brightness-0" : ""
|
isInverse ? "brightness-0" : ""
|
||||||
}`}
|
}`}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
|||||||
@@ -115,48 +115,29 @@ const Button = memo<ButtonProps>(
|
|||||||
|
|
||||||
const variantStyles: Record<string, string> = {
|
const variantStyles: Record<string, string> = {
|
||||||
filled:
|
filled:
|
||||||
"bg-[var(--color-surface-inverse-primary)] text-[var(--color-content-inverse-primary)] border-[1.5px] border-transparent hover:bg-[var(--color-surface-inverse-primary)] hover:text-[var(--color-content-invert-brand-primary)] hover:border-[var(--color-border-invert-brand-primary)] hover:scale-[1.02] focus-visible:bg-[var(--color-surface-inverse-primary)] focus-visible:text-[var(--color-content-invert-brand-primary)] focus-visible:outline-none focus-visible:border-transparent focus-visible:shadow-[0_0_0px_2px_var(--color-border-default-primary),0_0_0px_4px_var(--color-border-invert-primary)] focus-visible:scale-[1.02] active:bg-[var(--color-surface-invert-brand-primary)] active:text-[var(--color-content-invert-primary)] active:border-[var(--color-border-invert-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-invert-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:active:scale-100",
|
"bg-[var(--color-surface-inverse-primary)] text-[var(--color-content-inverse-primary)] border-[1.5px] border-transparent hover:bg-[var(--color-surface-inverse-primary)] hover:text-[var(--color-content-invert-brand-primary)] hover:border-[var(--color-border-invert-brand-primary)] focus-visible:bg-[var(--color-surface-inverse-primary)] focus-visible:text-[var(--color-content-invert-brand-primary)] focus-visible:outline-none focus-visible:border-transparent focus-visible:shadow-[0_0_0px_2px_var(--color-border-default-primary),0_0_0px_4px_var(--color-border-invert-primary)] active:bg-[var(--color-surface-invert-brand-primary)] active:text-[var(--color-content-invert-primary)] active:border-[var(--color-border-invert-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-invert-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:active:scale-100",
|
||||||
"filled-inverse":
|
"filled-inverse":
|
||||||
"bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border-[1.5px] border-transparent hover:bg-[var(--color-surface-default-primary)] hover:text-[var(--color-content-default-brand-primary)] hover:border-[var(--color-border-default-brand-primary)] hover:scale-[1.02] focus-visible:bg-[var(--color-surface-default-primary)] focus-visible:text-[var(--color-content-default-brand-primary)] focus-visible:outline-none focus-visible:border-transparent focus-visible:shadow-[0_0_0px_2px_var(--color-border-invert-primary),0_0_0px_4px_var(--color-border-default-primary)] focus-visible:scale-[1.02] active:bg-[var(--color-surface-default-brand-primary)] active:text-[var(--color-content-default-primary)] active:border-[var(--color-border-default-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-invert-secondary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:active:scale-100",
|
"bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border-[1.5px] border-transparent hover:bg-[var(--color-surface-default-primary)] hover:text-[var(--color-content-default-brand-primary)] hover:border-[var(--color-border-default-brand-primary)] focus-visible:bg-[var(--color-surface-default-primary)] focus-visible:text-[var(--color-content-default-brand-primary)] focus-visible:outline-none focus-visible:border-transparent focus-visible:shadow-[0_0_0px_2px_var(--color-border-invert-primary),0_0_0px_4px_var(--color-border-default-primary)] active:bg-[var(--color-surface-default-brand-primary)] active:text-[var(--color-content-default-primary)] active:border-[var(--color-border-default-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-invert-secondary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:active:scale-100",
|
||||||
outline:
|
outline:
|
||||||
"bg-transparent text-[var(--color-content-default-primary)] border-[1.5px] border-[var(--color-border-invert-primary)] hover:bg-transparent hover:text-[var(--color-content-default-brand-primary)] hover:border-[1.5px] hover:border-[var(--color-border-default-brand-primary)] hover:scale-[1.02] focus-visible:bg-transparent focus-visible:text-[var(--color-content-default-primary)] focus-visible:outline-none focus-visible:border-[1.5px] focus-visible:border-[var(--color-border-invert-primary)] focus-visible:shadow-[0_0_0px_2px_var(--color-border-default-primary),0_0_0px_4px_var(--color-border-invert-primary)] focus-visible:scale-[1.02] active:bg-transparent active:text-[var(--color-content-default-primary)] active:border-[1.5px] active:border-[var(--color-border-default-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-invert-tertiary)] disabled:border-[1.5px] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:active:scale-100",
|
"bg-transparent text-[var(--color-content-default-primary)] border-[1.5px] border-[var(--color-border-invert-primary)] hover:bg-transparent hover:text-[var(--color-content-default-brand-primary)] hover:border-[1.5px] hover:border-[var(--color-border-default-brand-primary)] focus-visible:bg-transparent focus-visible:text-[var(--color-content-default-primary)] focus-visible:outline-none focus-visible:border-[1.5px] focus-visible:border-[var(--color-border-invert-primary)] focus-visible:shadow-[0_0_0px_2px_var(--color-border-default-primary),0_0_0px_4px_var(--color-border-invert-primary)] active:bg-transparent active:text-[var(--color-content-default-primary)] active:border-[1.5px] active:border-[var(--color-border-default-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-invert-tertiary)] disabled:border-[1.5px] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:active:scale-100",
|
||||||
"outline-inverse":
|
"outline-inverse":
|
||||||
"bg-transparent text-[var(--color-content-invert-primary)] border-[1.5px] border-[var(--color-border-default-primary)] hover:bg-transparent hover:text-[var(--color-content-invert-brand-primary)] hover:border-[1.5px] hover:border-[var(--color-border-invert-brand-primary)] hover:scale-[1.02] focus-visible:bg-transparent focus-visible:text-[var(--color-content-invert-primary)] focus-visible:outline-none focus-visible:border-[1.5px] focus-visible:border-[var(--color-border-default-primary)] focus-visible:shadow-[0_0_0px_2px_var(--color-border-invert-primary),0_0_0px_4px_var(--color-border-default-primary)] focus-visible:scale-[1.02] active:bg-transparent active:text-[var(--color-content-invert-primary)] active:border-[1.5px] active:border-[var(--color-border-invert-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-invert-secondary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-[1.5px] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:active:scale-100",
|
"bg-transparent text-[var(--color-content-invert-primary)] border-[1.5px] border-[var(--color-border-default-primary)] hover:bg-transparent hover:text-[var(--color-content-invert-brand-primary)] hover:border-[1.5px] hover:border-[var(--color-border-invert-brand-primary)] focus-visible:bg-transparent focus-visible:text-[var(--color-content-invert-primary)] focus-visible:outline-none focus-visible:border-[1.5px] focus-visible:border-[var(--color-border-default-primary)] focus-visible:shadow-[0_0_0px_2px_var(--color-border-invert-primary),0_0_0px_4px_var(--color-border-default-primary)] active:bg-transparent active:text-[var(--color-content-invert-primary)] active:border-[1.5px] active:border-[var(--color-border-invert-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-invert-secondary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-[1.5px] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:active:scale-100",
|
||||||
ghost:
|
ghost:
|
||||||
"bg-transparent text-[var(--color-content-default-brand-primary)] border-[1.5px] border-transparent hover:bg-transparent hover:text-[var(--color-content-default-primary)] hover:border-transparent hover:scale-[1.02] focus-visible:bg-transparent focus-visible:text-[var(--color-content-default-brand-primary)] focus-visible:outline-none focus-visible:border-transparent focus-visible:shadow-[0_0_0px_2px_var(--color-border-default-primary),0_0_0px_4px_var(--color-border-invert-primary)] focus-visible:scale-[1.02] active:bg-transparent active:text-[var(--color-content-default-primary)] active:border-[var(--color-border-default-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-invert-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:active:scale-100",
|
"bg-transparent text-[var(--color-content-default-brand-primary)] border-[1.5px] border-transparent hover:bg-transparent hover:text-[var(--color-content-default-primary)] hover:border-transparent focus-visible:bg-transparent focus-visible:text-[var(--color-content-default-brand-primary)] focus-visible:outline-none focus-visible:border-transparent focus-visible:shadow-[0_0_0px_2px_var(--color-border-default-primary),0_0_0px_4px_var(--color-border-invert-primary)] active:bg-transparent active:text-[var(--color-content-default-primary)] active:border-[var(--color-border-default-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-invert-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:active:scale-100",
|
||||||
"ghost-inverse":
|
"ghost-inverse":
|
||||||
"bg-transparent text-[var(--color-content-invert-primary)] border-[1.5px] border-transparent hover:bg-transparent hover:text-[var(--color-content-invert-primary)] hover:border-transparent hover:scale-[1.02] focus-visible:bg-transparent focus-visible:text-[var(--color-content-invert-brand-primary)] focus-visible:outline-none focus-visible:border-transparent focus-visible:shadow-[0_0_0px_2px_var(--color-border-invert-primary),0_0_0px_4px_var(--color-border-default-primary)] focus-visible:scale-[1.02] active:bg-[var(--color-surface-invert-brand-primary)] active:text-[var(--color-content-invert-primary)] active:border-[var(--color-border-invert-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-invert-secondary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:active:scale-100",
|
"bg-transparent text-[var(--color-content-invert-primary)] border-[1.5px] border-transparent hover:bg-transparent hover:text-[var(--color-content-invert-primary)] hover:border-transparent focus-visible:bg-transparent focus-visible:text-[var(--color-content-invert-brand-primary)] focus-visible:outline-none focus-visible:border-transparent focus-visible:shadow-[0_0_0px_2px_var(--color-border-invert-primary),0_0_0px_4px_var(--color-border-default-primary)] active:bg-[var(--color-surface-invert-brand-primary)] active:text-[var(--color-content-invert-primary)] active:border-[var(--color-border-invert-brand-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-invert-secondary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:active:scale-100",
|
||||||
danger:
|
danger:
|
||||||
"bg-transparent text-[var(--color-border-default-negative-primary)] border border-[var(--color-border-default-negative-primary)] hover:bg-[var(--color-surface-invert-negative-secondary)] hover:text-[var(--color-border-default-negative-primary)] hover:border-[var(--color-border-default-negative-primary)] hover:scale-[1.02] focus-visible:bg-transparent focus-visible:text-[var(--color-border-default-negative-primary)] focus-visible:outline-none focus-visible:border-[var(--color-border-default-negative-primary)] focus-visible:shadow-[0_0_0px_2px_var(--color-border-default-primary),0_0_0px_4px_var(--color-border-invert-primary)] focus-visible:scale-[1.02] active:bg-[var(--color-surface-invert-negative-primary)] active:text-[var(--color-content-invert-negative-primary)] active:border-[1.5px] active:border-[var(--color-border-default-negative-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-inverse-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:active:scale-100",
|
"bg-transparent text-[var(--color-border-default-negative-primary)] border border-[var(--color-border-default-negative-primary)] hover:bg-[var(--color-surface-invert-negative-secondary)] hover:text-[var(--color-border-default-negative-primary)] hover:border-[var(--color-border-default-negative-primary)] focus-visible:bg-transparent focus-visible:text-[var(--color-border-default-negative-primary)] focus-visible:outline-none focus-visible:border-[var(--color-border-default-negative-primary)] focus-visible:shadow-[0_0_0px_2px_var(--color-border-default-primary),0_0_0px_4px_var(--color-border-invert-primary)] active:bg-[var(--color-surface-invert-negative-primary)] active:text-[var(--color-content-invert-negative-primary)] active:border-[1.5px] active:border-[var(--color-border-default-negative-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-inverse-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:active:scale-100",
|
||||||
"danger-inverse":
|
"danger-inverse":
|
||||||
"bg-transparent text-[var(--color-content-invert-negative-primary)] border border-[var(--color-border-invert-negative-primary)] hover:bg-transparent hover:text-[var(--color-content-invert-negative-primary)] hover:border-[var(--color-border-invert-negative-primary)] hover:scale-[1.02] focus-visible:bg-transparent focus-visible:text-[var(--color-content-invert-negative-primary)] focus-visible:outline-none focus-visible:border-[var(--color-border-invert-negative-primary)] focus-visible:shadow-[0_0_0px_2px_var(--color-border-invert-primary),0_0_0px_4px_var(--color-border-default-primary)] focus-visible:scale-[1.02] active:bg-[var(--color-surface-default-negative-primary)] active:text-[var(--color-content-default-primary)] active:border-[1.5px] active:border-[var(--color-border-default-negative-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-inverse-secondary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100 disabled:active:scale-100",
|
"bg-transparent text-[var(--color-content-invert-negative-primary)] border border-[var(--color-border-invert-negative-primary)] hover:bg-transparent hover:text-[var(--color-content-invert-negative-primary)] hover:border-[var(--color-border-invert-negative-primary)] focus-visible:bg-transparent focus-visible:text-[var(--color-content-invert-negative-primary)] focus-visible:outline-none focus-visible:border-[var(--color-border-invert-negative-primary)] focus-visible:shadow-[0_0_0px_2px_var(--color-border-invert-primary),0_0_0px_4px_var(--color-border-default-primary)] active:bg-[var(--color-surface-default-negative-primary)] active:text-[var(--color-content-default-primary)] active:border-[1.5px] active:border-[var(--color-border-default-negative-primary)] active:shadow-none active:scale-[0.98] disabled:bg-[var(--color-surface-inverse-secondary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-transparent disabled:cursor-not-allowed disabled:opacity-50 disabled:active:scale-100",
|
||||||
};
|
};
|
||||||
|
|
||||||
const hoverOutlineStyles: Record<string, string> = {
|
// Hover/focus: color + border only — no scale and no extra outline (those
|
||||||
xsmall: "hover:outline-1",
|
// enlarge the label). Press: active:scale-[0.98]. Same rule for nav items
|
||||||
small: "hover:outline-1",
|
// and cards: color, opacity, or shadow on hover; scale only on press.
|
||||||
medium: "hover:outline-1",
|
// State prop is informational for Figma alignment; CSS pseudo-classes own
|
||||||
large: "hover:outline-2",
|
// the actual interaction states.
|
||||||
xlarge: "hover:outline-[2.5px]",
|
const baseStyles = `inline-flex items-center justify-start box-border whitespace-nowrap shrink-0 touch-manipulation [-webkit-tap-highlight-color:transparent] ${sizeStyles[size]} rounded-[var(--radius-measures-radius-full)] ${fontStyles[size]} transition-[transform,color,background-color,border-color,box-shadow] duration-150 ease-out cursor-pointer ${variantStyles[variant]}`;
|
||||||
};
|
|
||||||
|
|
||||||
// Only apply outline styles to filled variant, not filled-inverse, outline, outline-inverse, ghost, ghost-inverse, danger, or danger-inverse
|
|
||||||
const outlineStyles =
|
|
||||||
variant === "filled-inverse" ||
|
|
||||||
variant === "outline" ||
|
|
||||||
variant === "outline-inverse" ||
|
|
||||||
variant === "ghost" ||
|
|
||||||
variant === "ghost-inverse" ||
|
|
||||||
variant === "danger" ||
|
|
||||||
variant === "danger-inverse"
|
|
||||||
? ""
|
|
||||||
: hoverOutlineStyles[size];
|
|
||||||
|
|
||||||
// Apply state-based styles if state prop is provided (overrides default hover/focus/active)
|
|
||||||
// Note: State prop is informational for Figma alignment - actual state is handled by CSS pseudo-classes
|
|
||||||
// For now, we maintain existing behavior and state prop is for documentation/alignment purposes
|
|
||||||
|
|
||||||
const baseStyles = `inline-flex items-center justify-start box-border whitespace-nowrap shrink-0 touch-manipulation [-webkit-tap-highlight-color:transparent] ${sizeStyles[size]} rounded-[var(--radius-measures-radius-full)] ${fontStyles[size]} transition-[transform,color,background-color,border-color,box-shadow,outline-color] duration-150 ease-out cursor-pointer ${variantStyles[variant]} ${outlineStyles}`;
|
|
||||||
const combinedStyles = `${baseStyles} ${className}`;
|
const combinedStyles = `${baseStyles} ${className}`;
|
||||||
|
|
||||||
const sharedA11y = {
|
const sharedA11y = {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function IconView({
|
|||||||
onKeyDown,
|
onKeyDown,
|
||||||
}: IconViewProps) {
|
}: IconViewProps) {
|
||||||
const interactionClass = interactive
|
const interactionClass = interactive
|
||||||
? "cursor-pointer transition-all duration-200 hover:scale-[1.02] hover:shadow-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-brand-primary)] focus:ring-offset-2"
|
? "cursor-pointer transition-shadow duration-200 hover:shadow-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-brand-primary)] focus:ring-offset-2"
|
||||||
: "cursor-default";
|
: "cursor-default";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const MiniContainer = memo<MiniProps>(
|
|||||||
...baseProps,
|
...baseProps,
|
||||||
href,
|
href,
|
||||||
className:
|
className:
|
||||||
"block focus:outline-none focus:ring-2 focus:ring-[var(--color-surface-default-brand-royal)] focus:ring-offset-2 rounded-[var(--radius-measures-radius-xlarge)] transition-all duration-200 hover:scale-[1.02]",
|
"block focus:outline-none focus:ring-2 focus:ring-[var(--color-surface-default-brand-royal)] focus:ring-offset-2 rounded-[var(--radius-measures-radius-xlarge)]",
|
||||||
tabIndex: 0,
|
tabIndex: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -64,7 +64,7 @@ const MiniContainer = memo<MiniProps>(
|
|||||||
...baseProps,
|
...baseProps,
|
||||||
onClick,
|
onClick,
|
||||||
className:
|
className:
|
||||||
"block w-full text-left focus:outline-none focus:ring-2 focus:ring-[var(--color-surface-default-brand-royal)] focus:ring-offset-2 rounded-[var(--radius-measures-radius-xlarge)] transition-all duration-200 hover:scale-[1.02]",
|
"block w-full text-left focus:outline-none focus:ring-2 focus:ring-[var(--color-surface-default-brand-royal)] focus:ring-offset-2 rounded-[var(--radius-measures-radius-xlarge)]",
|
||||||
tabIndex: 0,
|
tabIndex: 0,
|
||||||
onKeyDown: (e: React.KeyboardEvent<HTMLButtonElement>) => {
|
onKeyDown: (e: React.KeyboardEvent<HTMLButtonElement>) => {
|
||||||
if (e.key === "Enter" || e.key === " ") {
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function MiniView({
|
|||||||
|
|
||||||
const panelClass = featureGridShell
|
const panelClass = featureGridShell
|
||||||
? `h-[138px] shrink-0 rounded-[var(--measures-radius-400,16px)] px-[24px] py-[32px] ${backgroundColor} flex items-center justify-center`
|
? `h-[138px] shrink-0 rounded-[var(--measures-radius-400,16px)] px-[24px] py-[32px] ${backgroundColor} flex items-center justify-center`
|
||||||
: `flex-1 rounded-[var(--radius-measures-radius-xlarge)] border border-[1px] py-[var(--spacing-scale-032)] px-[var(--spacing-scale-024)] ${backgroundColor} flex items-center justify-center transition-all duration-200 hover:scale-[1.02] hover:shadow-lg`;
|
: `flex-1 rounded-[var(--radius-measures-radius-xlarge)] border border-[1px] py-[var(--spacing-scale-032)] px-[var(--spacing-scale-024)] ${backgroundColor} flex items-center justify-center transition-shadow duration-200 hover:shadow-lg`;
|
||||||
|
|
||||||
const imageClass = featureGridShell
|
const imageClass = featureGridShell
|
||||||
? `max-h-[48px] max-w-[56px] w-auto h-auto object-contain${panelImageClassName ? ` ${panelImageClassName}` : ""}`
|
? `max-h-[48px] max-w-[56px] w-auto h-auto object-contain${panelImageClassName ? ` ${panelImageClassName}` : ""}`
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ function ContentThumbnailTemplateView({
|
|||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href={`/blog/${post.slug}`}
|
href={`/blog/${post.slug}`}
|
||||||
className={`group block w-full transition-transform duration-200 hover:scale-[1.02] ${className}`}
|
className={`group block w-full ${className}`}
|
||||||
>
|
>
|
||||||
<div className="relative aspect-[320/225.5] w-full overflow-hidden smd:aspect-[260/390]">
|
<div className="relative aspect-[320/225.5] w-full overflow-hidden smd:aspect-[260/390]">
|
||||||
<div className="absolute inset-0 z-0">
|
<div className="absolute inset-0 z-0">
|
||||||
@@ -49,7 +49,7 @@ function ContentThumbnailTemplateView({
|
|||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href={`/blog/${post.slug}`}
|
href={`/blog/${post.slug}`}
|
||||||
className={`group block transition-transform duration-200 hover:scale-[1.02] ${className}`}
|
className={`group block ${className}`}
|
||||||
>
|
>
|
||||||
<div className="relative h-[390px] w-[260px] overflow-hidden">
|
<div className="relative h-[390px] w-[260px] overflow-hidden">
|
||||||
<div className="absolute inset-0 z-0">
|
<div className="absolute inset-0 z-0">
|
||||||
@@ -71,7 +71,7 @@ function ContentThumbnailTemplateView({
|
|||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href={`/blog/${post.slug}`}
|
href={`/blog/${post.slug}`}
|
||||||
className={`group block w-full transition-transform duration-200 hover:scale-[1.02] ${className}`}
|
className={`group block w-full ${className}`}
|
||||||
>
|
>
|
||||||
<div className="relative aspect-[260/390] w-full overflow-hidden">
|
<div className="relative aspect-[260/390] w-full overflow-hidden">
|
||||||
<div className="absolute inset-0 z-0">
|
<div className="absolute inset-0 z-0">
|
||||||
@@ -92,10 +92,7 @@ function ContentThumbnailTemplateView({
|
|||||||
|
|
||||||
if (sizing === "fixed") {
|
if (sizing === "fixed") {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link href={`/blog/${post.slug}`} className={`group block ${className}`}>
|
||||||
href={`/blog/${post.slug}`}
|
|
||||||
className={`group block transition-transform duration-200 hover:scale-[1.02] ${className}`}
|
|
||||||
>
|
|
||||||
<div className="relative h-[225.5px] w-[320px] overflow-hidden">
|
<div className="relative h-[225.5px] w-[320px] overflow-hidden">
|
||||||
<div className="absolute inset-0 z-0">
|
<div className="absolute inset-0 z-0">
|
||||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||||
@@ -116,7 +113,7 @@ function ContentThumbnailTemplateView({
|
|||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href={`/blog/${post.slug}`}
|
href={`/blog/${post.slug}`}
|
||||||
className={`group block w-full transition-transform duration-200 hover:scale-[1.02] ${className}`}
|
className={`group block w-full ${className}`}
|
||||||
>
|
>
|
||||||
<div className="relative aspect-[320/225.5] w-full overflow-hidden">
|
<div className="relative aspect-[320/225.5] w-full overflow-hidden">
|
||||||
<div className="absolute inset-0 z-0">
|
<div className="absolute inset-0 z-0">
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ function ChipView({
|
|||||||
focus-visible:ring-[var(--color-border-default-primary,#141414)]
|
focus-visible:ring-[var(--color-border-default-primary,#141414)]
|
||||||
focus-visible:ring-offset-2
|
focus-visible:ring-offset-2
|
||||||
focus-visible:ring-offset-transparent
|
focus-visible:ring-offset-transparent
|
||||||
transition-[background,border-color,color,box-shadow,transform]
|
transition-[background,border-color,color,box-shadow]
|
||||||
duration-200
|
duration-200
|
||||||
ease-in-out
|
ease-in-out
|
||||||
`
|
`
|
||||||
@@ -118,7 +118,7 @@ function ChipView({
|
|||||||
|
|
||||||
const stateClasses = isDisabled
|
const stateClasses = isDisabled
|
||||||
? "cursor-not-allowed opacity-60"
|
? "cursor-not-allowed opacity-60"
|
||||||
: "cursor-pointer hover:scale-[1.02]";
|
: "cursor-pointer";
|
||||||
|
|
||||||
const combinedClasses = [
|
const combinedClasses = [
|
||||||
baseClasses,
|
baseClasses,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { memo } from "react";
|
|||||||
import type { IncrementerViewProps } from "./Incrementer.types";
|
import type { IncrementerViewProps } from "./Incrementer.types";
|
||||||
|
|
||||||
const STEP_BUTTON_CLASSES =
|
const STEP_BUTTON_CLASSES =
|
||||||
"bg-[var(--color-surface-default-secondary,#141414)] text-[var(--color-content-default-primary,#fff)] inline-flex shrink-0 items-center justify-center overflow-clip rounded-[var(--measures-radius-full,9999px)] px-[var(--space-200,8px)] py-[var(--measures-spacing-150,6px)] transition-[background,color,transform] duration-200 ease-in-out hover:scale-[1.02] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-invert-primary,#fff)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-default-primary,#000)] disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100";
|
"bg-[var(--color-surface-default-secondary,#141414)] text-[var(--color-content-default-primary,#fff)] inline-flex shrink-0 items-center justify-center overflow-clip rounded-[var(--measures-radius-full,9999px)] px-[var(--space-200,8px)] py-[var(--measures-spacing-150,6px)] transition-[background,color,opacity] duration-200 ease-in-out hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-invert-primary,#fff)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-default-primary,#000)] disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:opacity-50";
|
||||||
|
|
||||||
function MinusIcon() {
|
function MinusIcon() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const MenuItemContainer = memo<MenuItemProps>(
|
|||||||
|
|
||||||
// Interactive styles
|
// Interactive styles
|
||||||
const interactiveStyles =
|
const interactiveStyles =
|
||||||
"hover:scale-[1.02] active:scale-[0.98] focus:scale-[1.02] disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:active:scale-100";
|
"active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed disabled:active:scale-100";
|
||||||
|
|
||||||
// Disabled styles
|
// Disabled styles
|
||||||
const disabledStyles = disabled
|
const disabledStyles = disabled
|
||||||
|
|||||||
@@ -23,16 +23,14 @@ function LogoWallView({
|
|||||||
{displayLogos.map((logo, index) => (
|
{displayLogos.map((logo, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={`flex items-center justify-center transition-opacity duration-500 hover:opacity-100 ${
|
className={`flex items-center justify-center ${
|
||||||
logo.order || ""
|
logo.order || ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={logo.src}
|
src={logo.src}
|
||||||
alt={logo.alt}
|
alt={logo.alt}
|
||||||
className={`${
|
className={`${logo.size || "h-8"} w-auto object-contain`}
|
||||||
logo.size || "h-8"
|
|
||||||
} w-auto object-contain transition-transform duration-500 hover:scale-105`}
|
|
||||||
priority={index < 2} // Prioritize first 2 logos for above-the-fold loading
|
priority={index < 2} // Prioritize first 2 logos for above-the-fold loading
|
||||||
unoptimized // Skip optimization for local images
|
unoptimized // Skip optimization for local images
|
||||||
width={0}
|
width={0}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ Quick map from the Figma file **Community Rule System** (`agv0VBLiBlcnSAaiAORgPR
|
|||||||
## Button conventions (Figma “Button” canvas)
|
## Button conventions (Figma “Button” canvas)
|
||||||
|
|
||||||
- **`buttons/Button/`** — **`Button.tsx`** + **`index.tsx`**. Variants (**filled**, **outline**, **ghost**, **danger**) and **`palette`** / **`size`** align with **`lib/propNormalization`**. **`href`** renders an `<a>` when not disabled.
|
- **`buttons/Button/`** — **`Button.tsx`** + **`index.tsx`**. Variants (**filled**, **outline**, **ghost**, **danger**) and **`palette`** / **`size`** align with **`lib/propNormalization`**. **`href`** renders an `<a>` when not disabled.
|
||||||
|
- **Interaction:** hover and focus change color/border (or opacity/shadow on cards) — they must not scale the control, because that enlarges the label. Reserve `active:scale-[0.98]` for press. Same rule for nav items (`MenuItem`) and cards (`Mini`, `Icon`, article thumbnails).
|
||||||
- **`buttons/InlineTextButton/`** — tertiary inline **`<button>`** (underline, inherited typography) for in-paragraph controls—**not** primary actions.
|
- **`buttons/InlineTextButton/`** — tertiary inline **`<button>`** (underline, inherited typography) for in-paragraph controls—**not** primary actions.
|
||||||
|
|
||||||
## Control conventions (Figma [“Control”](https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=5944-58611) canvas)
|
## Control conventions (Figma [“Control”](https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=5944-58611) canvas)
|
||||||
|
|||||||
@@ -225,10 +225,13 @@ maintenance window — after the final Cloudron backup (§5 phase 3 step
|
|||||||
([CR-101](https://linear.app/community-rule/issue/CR-101/backend-decommission-legacy-communityrule-lamp-app))
|
([CR-101](https://linear.app/community-rule/issue/CR-101/backend-decommission-legacy-communityrule-lamp-app))
|
||||||
for operator recovery if manual lookup from the export is ever needed.
|
for operator recovery if manual lookup from the export is ever needed.
|
||||||
|
|
||||||
**User discoverability:** link to the archive repo (or a release
|
**No app-side surface.** The archive lives in the repo only. It exists
|
||||||
download) from the new app — footer, help page, or a static
|
for posterity and operator lookup, not end-user self-service — there is
|
||||||
`/legacy-archive` page — so users looking for pre-cutover rules can
|
no footer link, help-page entry, or `/legacy-archive` page in the new
|
||||||
find it without knowing Gitea exists.
|
app, and none is required to close
|
||||||
|
[CR-102](https://linear.app/community-rule/issue/CR-102). Operators
|
||||||
|
answering a "where did my rule go?" question point at the Gitea repo
|
||||||
|
directly.
|
||||||
|
|
||||||
## 7. Old vs new deltas
|
## 7. Old vs new deltas
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ export default {
|
|||||||
## Animations & Transitions
|
## Animations & Transitions
|
||||||
|
|
||||||
- **Fade-in Effect**: Logos fade in from opacity 0 to 60% after component mounts (500ms transition)
|
- **Fade-in Effect**: Logos fade in from opacity 0 to 60% after component mounts (500ms transition)
|
||||||
- **Hover Interactions**: Individual logos respond to hover with:
|
|
||||||
- Opacity change from 60% to 100%
|
|
||||||
- Scale transform (105% zoom)
|
|
||||||
- 500ms smooth transitions for all effects
|
|
||||||
- **Loading States**: Progressive loading with fallback timer for reliable display
|
- **Loading States**: Progressive loading with fallback timer for reliable display
|
||||||
|
|
||||||
## Props
|
## Props
|
||||||
@@ -74,7 +70,7 @@ export const Default = {
|
|||||||
docs: {
|
docs: {
|
||||||
description: {
|
description: {
|
||||||
story:
|
story:
|
||||||
"Default LogoWall with all partner logos. Displays in a 3×2 grid on mobile, 2×3 grid on small screens, single row on medium screens, and larger sizes on large screens. Features smooth fade-in animations and hover interactions.",
|
"Default LogoWall with all partner logos. Displays in a 3×2 grid on mobile, 2×3 grid on small screens, single row on medium screens, and larger sizes on large screens. Features a fade-in on mount.",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ describe("Button (behavioral tests)", () => {
|
|||||||
expect(button.className).toContain("duration-150");
|
expect(button.className).toContain("duration-150");
|
||||||
expect(button.className).not.toContain("duration-500");
|
expect(button.className).not.toContain("duration-500");
|
||||||
expect(button.className).toContain("active:scale-[0.98]");
|
expect(button.className).toContain("active:scale-[0.98]");
|
||||||
|
expect(button.className).not.toContain("hover:scale-");
|
||||||
|
expect(button.className).not.toContain("focus-visible:scale-");
|
||||||
|
expect(button.className).not.toContain("hover:outline-");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders as a link when href is provided", () => {
|
it("renders as a link when href is provided", () => {
|
||||||
|
|||||||
@@ -36,6 +36,16 @@ describe("Logo (behavioral tests)", () => {
|
|||||||
expect(logo).toHaveAttribute("aria-label", "CommunityRule Logo");
|
expect(logo).toHaveAttribute("aria-label", "CommunityRule Logo");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("animates the mark on hover without scaling the wordmark", () => {
|
||||||
|
render(<Logo />);
|
||||||
|
const logo = screen.getByRole("link", { name: /communityrule logo/i });
|
||||||
|
const wordmark = screen.getByText("CommunityRule");
|
||||||
|
const mark = logo.querySelector("img");
|
||||||
|
expect(logo).toHaveClass("group");
|
||||||
|
expect(wordmark.className).not.toContain("scale-");
|
||||||
|
expect(mark).toHaveClass("group-hover:scale-110");
|
||||||
|
});
|
||||||
|
|
||||||
it("renders logo icon", () => {
|
it("renders logo icon", () => {
|
||||||
render(<Logo />);
|
render(<Logo />);
|
||||||
expect(screen.getByAltText("CommunityRule Logo")).toBeInTheDocument();
|
expect(screen.getByAltText("CommunityRule Logo")).toBeInTheDocument();
|
||||||
|
|||||||
@@ -92,13 +92,15 @@ describe("LogoWall Component", () => {
|
|||||||
expect(screen.getByAltText("Food Not Bombs")).toBeInTheDocument();
|
expect(screen.getByAltText("Food Not Bombs")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("applies hover effects", () => {
|
test("does not apply hover effects on partner logos", () => {
|
||||||
render(<LogoWall />);
|
render(<LogoWall />);
|
||||||
|
|
||||||
const logoContainers = document.querySelectorAll(
|
expect(
|
||||||
'[class*="hover:opacity-100"]',
|
document.querySelectorAll('[class*="hover:opacity"]').length,
|
||||||
);
|
).toBe(0);
|
||||||
expect(logoContainers.length).toBeGreaterThan(0);
|
expect(
|
||||||
|
document.querySelectorAll('[class*="hover:scale"]').length,
|
||||||
|
).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("renders with proper semantic structure", () => {
|
test("renders with proper semantic structure", () => {
|
||||||
@@ -142,13 +144,4 @@ describe("LogoWall Component", () => {
|
|||||||
expect(foodNotBombsLogo).toBeInTheDocument();
|
expect(foodNotBombsLogo).toBeInTheDocument();
|
||||||
expect(startCoopLogo).toBeInTheDocument();
|
expect(startCoopLogo).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("applies scale effect on hover", () => {
|
|
||||||
render(<LogoWall />);
|
|
||||||
|
|
||||||
const logos = screen.getAllByRole("img");
|
|
||||||
logos.forEach((logo) => {
|
|
||||||
expect(logo).toHaveClass("hover:scale-105");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user