feat: FDButton component with dark/light hover, fix yellow button on navy
This commit is contained in:
parent
80be2c4098
commit
f1462cf7c3
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
@ -1,6 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
import "./.next/types/routes.d.ts";
|
||||
import "./.next/dev/types/routes.d.ts";
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
|
||||
@ -453,6 +453,35 @@ html[data-theme='light'] {
|
||||
box-shadow: 0 4px 12px -2px rgba(254, 204, 2, 0.25);
|
||||
}
|
||||
|
||||
/* Same as fd-btn-primary but hovers to WHITE — use on navy/dark backgrounds.
|
||||
Applied automatically via <FDButton variant="primary" onDark={true}> */
|
||||
.fd-btn-primary-dark {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.75rem 2rem;
|
||||
background-color: var(--color-fd-yellow);
|
||||
color: var(--color-fd-navy);
|
||||
font-family: var(--font-joey-bold);
|
||||
font-size: var(--text-fd-btn);
|
||||
line-height: var(--text-fd-btn--line-height);
|
||||
border-radius: 9999px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
border: 2px solid transparent;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.fd-btn-primary-dark:hover {
|
||||
background-color: #ffffff;
|
||||
color: var(--color-fd-navy);
|
||||
box-shadow: 0 8px 24px -4px rgba(14, 35, 56, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.fd-btn-primary-dark:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 4px 12px -2px rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.fd-btn-secondary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@ -628,6 +657,7 @@ html[data-theme='light'] {
|
||||
@media (max-width: 47.9375rem) {
|
||||
/* Full-width buttons on mobile for clear tap targets */
|
||||
.fd-btn-primary,
|
||||
.fd-btn-primary-dark,
|
||||
.fd-btn-secondary,
|
||||
.fd-btn-secondary-dark,
|
||||
.fd-btn-navy,
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import React from 'react'
|
||||
import type { Metadata } from 'next'
|
||||
import { FDButton } from '@/components/FDButton'
|
||||
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: '404 – Sidan hittades inte | Fiber Direkt',
|
||||
@ -41,9 +43,9 @@ export default function NotFound() {
|
||||
|
||||
{/* CTA */}
|
||||
<div className="mt-2">
|
||||
<a href="/" className="fd-btn-primary">
|
||||
<FDButton href="/" variant="primary" onDark={false}>
|
||||
Tillbaka till startsidan
|
||||
</a>
|
||||
</FDButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -5,34 +5,30 @@ export const FDCtaSideImageBlock: Block = {
|
||||
interfaceName: 'FDCtaSideImageBlock',
|
||||
labels: {
|
||||
singular: 'FD CTA med bild',
|
||||
plural: 'FD CTA med bild',
|
||||
plural: 'FD CTA med bilder',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'heading',
|
||||
type: 'text',
|
||||
localized: true,
|
||||
required: true,
|
||||
label: 'Rubrik',
|
||||
},
|
||||
{
|
||||
name: 'body',
|
||||
type: 'textarea',
|
||||
localized: true,
|
||||
required: true,
|
||||
label: 'Brödtext',
|
||||
},
|
||||
{
|
||||
name: 'ctaText',
|
||||
type: 'text',
|
||||
localized: true,
|
||||
label: 'CTA-knapp text',
|
||||
defaultValue: 'Läs mer',
|
||||
},
|
||||
{
|
||||
name: 'ctaLink',
|
||||
type: 'text',
|
||||
localized: true,
|
||||
label: 'CTA-knapp länk',
|
||||
defaultValue: '#',
|
||||
},
|
||||
@ -40,8 +36,7 @@ export const FDCtaSideImageBlock: Block = {
|
||||
name: 'image',
|
||||
type: 'upload',
|
||||
relationTo: 'media',
|
||||
required: true,
|
||||
label: 'Bild',
|
||||
label: 'Bild (valfri)',
|
||||
},
|
||||
{
|
||||
name: 'imagePosition',
|
||||
@ -61,58 +56,6 @@ export const FDCtaSideImageBlock: Block = {
|
||||
options: [
|
||||
{ label: 'Ljust', value: 'light' },
|
||||
{ label: 'Mörkt', value: 'dark' },
|
||||
{ label: 'Anpassad färg', value: 'custom' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'customBackgroundColor',
|
||||
type: 'text',
|
||||
label: 'Anpassad bakgrundsfärg',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.theme === 'custom',
|
||||
description: 'Valfri HEX-färg, t.ex. #1a3a5c eller #fecc02',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'customTextLight',
|
||||
type: 'checkbox',
|
||||
label: 'Ljus text (för mörka bakgrunder)',
|
||||
defaultValue: true,
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.theme === 'custom',
|
||||
description: 'Aktivera för vit text på mörk anpassad bakgrund',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'imageOverlay',
|
||||
type: 'select',
|
||||
label: 'Bild-overlay',
|
||||
defaultValue: 'none',
|
||||
admin: {
|
||||
description: 'Tonad overlay över bilden med varumärkesfärg',
|
||||
},
|
||||
options: [
|
||||
{ label: 'Ingen', value: 'none' },
|
||||
{ label: 'Navy', value: 'navy' },
|
||||
{ label: 'Gul', value: 'yellow' },
|
||||
{ label: 'Svart', value: 'black' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'imageOverlayOpacity',
|
||||
type: 'select',
|
||||
label: 'Overlay-styrka',
|
||||
defaultValue: '30',
|
||||
admin: {
|
||||
condition: (_, siblingData) =>
|
||||
Boolean(siblingData?.imageOverlay) && siblingData?.imageOverlay !== 'none',
|
||||
description: 'Hur stark overlay över bilden',
|
||||
},
|
||||
options: [
|
||||
{ label: 'Lätt (20%)', value: '20' },
|
||||
{ label: 'Medium (30%)', value: '30' },
|
||||
{ label: 'Stark (50%)', value: '50' },
|
||||
{ label: 'Mycket stark (70%)', value: '70' },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@ -1,42 +1,56 @@
|
||||
import React from 'react'
|
||||
|
||||
type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>
|
||||
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>
|
||||
|
||||
type FDButtonProps = {
|
||||
href: string
|
||||
children: React.ReactNode
|
||||
variant?: 'primary' | 'outline'
|
||||
onDark?: boolean
|
||||
className?: string
|
||||
} & (
|
||||
| ({ as?: 'a' } & AnchorProps)
|
||||
| ({ as: 'button' } & ButtonProps)
|
||||
)
|
||||
|
||||
const classMap = {
|
||||
'primary-light': 'fd-btn-primary',
|
||||
'primary-dark': 'fd-btn-primary-dark',
|
||||
'outline-light': 'fd-btn-secondary',
|
||||
'outline-dark': 'fd-btn-secondary-dark',
|
||||
}
|
||||
|
||||
/**
|
||||
* FDButton — shared button component for all FD blocks.
|
||||
* FDButton — single button component for all FD blocks.
|
||||
*
|
||||
* variant="primary" onDark={true} → yellow bg, hover white (use on navy backgrounds)
|
||||
* variant="primary" onDark={false} → yellow bg, hover yellow/80 (use on light backgrounds)
|
||||
* variant="outline" onDark={true} → white border + text, hover white/10
|
||||
* variant="outline" onDark={false} → navy border + text, hover navy/5
|
||||
* Renders as <a> by default, or <button> when as="button" (e.g. forms, newsletter).
|
||||
*
|
||||
* variant="primary" onDark={false} → fd-btn-primary yellow → navy hover (light backgrounds)
|
||||
* variant="primary" onDark={true} → fd-btn-primary-dark yellow → white hover (navy backgrounds)
|
||||
* variant="outline" onDark={false} → fd-btn-secondary outline on light
|
||||
* variant="outline" onDark={true} → fd-btn-secondary-dark outline on dark
|
||||
*/
|
||||
export const FDButton: React.FC<FDButtonProps> = ({
|
||||
href,
|
||||
export const FDButton = ({
|
||||
children,
|
||||
variant = 'primary',
|
||||
onDark = false,
|
||||
className = '',
|
||||
}) => {
|
||||
const base =
|
||||
'inline-flex items-center justify-center px-8 py-2.5 rounded-full font-joey-bold text-lg md:text-2xl leading-[38px] transition-colors'
|
||||
as: Tag = 'a',
|
||||
...rest
|
||||
}: FDButtonProps) => {
|
||||
const key = `${variant}-${onDark ? 'dark' : 'light'}` as keyof typeof classMap
|
||||
const cls = `${classMap[key]} ${className}`.trim()
|
||||
|
||||
const styles = {
|
||||
'primary-dark': 'bg-fd-yellow text-fd-navy hover:bg-white hover:text-fd-navy',
|
||||
'primary-light': 'bg-fd-yellow text-fd-navy hover:bg-fd-yellow/80',
|
||||
'outline-dark': 'border-2 border-white text-white hover:bg-white/10',
|
||||
'outline-light': 'border-2 border-fd-navy text-fd-navy hover:bg-fd-navy/5',
|
||||
if (Tag === 'button') {
|
||||
return (
|
||||
<button className={cls} {...(rest as ButtonProps)}>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
const key = `${variant}-${onDark ? 'dark' : 'light'}` as keyof typeof styles
|
||||
|
||||
return (
|
||||
<a href={href} className={`${base} ${styles[key]} ${className}`}>
|
||||
<a className={cls} {...(rest as AnchorProps)}>
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user