@leabankab/component-library 8.6.1 → 8.8.0
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.
- package/CHANGELOG.md +94 -0
- package/dist/component-library.es.js +1930 -1091
- package/dist/component-library.es.js.map +1 -1
- package/dist/component-library.umd.js +2 -2
- package/dist/component-library.umd.js.map +1 -1
- package/dist/components/buttons/action-button.d.ts +34 -4
- package/dist/components/buttons/button-base.d.ts +5 -2
- package/dist/components/buttons/icon-button.d.ts +16 -2
- package/dist/components/color-roles.d.ts +7 -1
- package/dist/components/data-display/arrow-circle.d.ts +21 -0
- package/dist/components/data-display/article-card.d.ts +88 -0
- package/dist/components/data-display/avatar.d.ts +33 -0
- package/dist/components/data-display/chip.d.ts +8 -3
- package/dist/components/data-display/featured-image.d.ts +42 -0
- package/dist/components/data-display/index.d.ts +12 -0
- package/dist/components/data-display/link-card.d.ts +52 -0
- package/dist/components/data-display/media-card.d.ts +102 -0
- package/dist/components/data-display/partner-row.d.ts +46 -0
- package/dist/components/data-display/rich-text.d.ts +27 -0
- package/dist/components/data-display/service-card.d.ts +80 -0
- package/dist/components/data-display/star-rating.d.ts +26 -0
- package/dist/components/data-display/table.d.ts +93 -0
- package/dist/components/data-display/testimonial-card.d.ts +43 -0
- package/dist/components/data-display/use-star-rating-labels.d.ts +5 -0
- package/dist/components/data-display/use-video-player-labels.d.ts +2 -0
- package/dist/components/data-display/video-player.d.ts +22 -0
- package/dist/components/data-display/website-card.d.ts +10 -0
- package/dist/components/feedback/index.d.ts +1 -0
- package/dist/components/feedback/skeleton.d.ts +22 -0
- package/dist/components/form/slider.d.ts +15 -2
- package/dist/components/navigation/breadcrumbs.d.ts +38 -0
- package/dist/components/navigation/index.d.ts +3 -0
- package/dist/components/navigation/pagination-dots.d.ts +34 -0
- package/dist/components/navigation/pagination.d.ts +37 -0
- package/dist/components/navigation/use-breadcrumbs-labels.d.ts +2 -0
- package/dist/components/navigation/use-pagination-labels.d.ts +7 -0
- package/dist/components/surfaces/accordion.d.ts +5 -1
- package/dist/components/surfaces/index.d.ts +1 -0
- package/dist/components/surfaces/panel.d.ts +30 -0
- package/dist/components/typography/link.d.ts +14 -1
- package/dist/cookie-consent-react.cjs +1 -1
- package/dist/cookie-consent-react.cjs.map +1 -1
- package/dist/cookie-consent-react.mjs +13 -13
- package/dist/cookie-consent-react.mjs.map +1 -1
- package/dist/cookie-consent.css +1 -1
- package/dist/date-picker.cjs +1 -1
- package/dist/date-picker.cjs.map +1 -1
- package/dist/date-picker.mjs +216 -203
- package/dist/date-picker.mjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/tailwind.css +16 -0
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/token-types.d.ts +13 -3
- package/dist/theme/tokens/breakpoints.d.ts +20 -0
- package/dist/theme/tokens/font-family.d.ts +6 -0
- package/dist/theme/tokens/index.d.ts +1 -0
- package/dist/theme/tokens/shadows.d.ts +6 -0
- package/dist/theme/tokens/text-styles.d.ts +8 -0
- package/dist/theme/tokens/widths.d.ts +10 -0
- package/dist/theme/types.d.ts +9 -1
- package/dist/website/brand-letters.d.ts +40 -0
- package/dist/website/calculator.d.ts +58 -0
- package/dist/website/carousel.d.ts +55 -0
- package/dist/website/cta-banner.d.ts +42 -0
- package/dist/website/expanding-cards-context.d.ts +8 -0
- package/dist/website/expanding-cards-item.d.ts +69 -0
- package/dist/website/expanding-cards.d.ts +48 -0
- package/dist/website/hero-service-grid.d.ts +52 -0
- package/dist/website/hero.d.ts +57 -0
- package/dist/website/index.d.ts +33 -0
- package/dist/website/navigation-grid.d.ts +39 -0
- package/dist/website/paragraphs.d.ts +11 -0
- package/dist/website/partner-list.d.ts +79 -0
- package/dist/website/payment-feature.d.ts +85 -0
- package/dist/website/promo-grid.d.ts +71 -0
- package/dist/website/section-header.d.ts +53 -0
- package/dist/website/section.d.ts +53 -0
- package/dist/website/service-card-grid.d.ts +33 -0
- package/dist/website/split-content.d.ts +69 -0
- package/dist/website/stats.d.ts +52 -0
- package/dist/website/testimonials.d.ts +100 -0
- package/dist/website/use-brand-letters-labels.d.ts +2 -0
- package/dist/website/use-carousel-labels.d.ts +6 -0
- package/dist/website/use-carousel.d.ts +50 -0
- package/dist/website/use-partner-list-labels.d.ts +6 -0
- package/dist/website/use-testimonials-labels.d.ts +6 -0
- package/dist/website.cjs +2 -0
- package/dist/website.cjs.map +1 -0
- package/dist/website.css +1 -0
- package/dist/website.mjs +1226 -0
- package/dist/website.mjs.map +1 -0
- package/package.json +7 -2
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ReactElement, ReactNode, Ref } from 'react';
|
|
3
|
+
export type NavigationGridProps = Omit<useRender.ComponentProps<"div">, "ref" | "title" | "children"> & {
|
|
4
|
+
/** The rendered element: the `<div>`, or the element passed to `render`. */
|
|
5
|
+
ref?: Ref<HTMLElement>;
|
|
6
|
+
/**
|
|
7
|
+
* The heading over the cards. Left out, there is no heading and no room
|
|
8
|
+
* kept for one.
|
|
9
|
+
*/
|
|
10
|
+
title?: ReactNode;
|
|
11
|
+
/** The element for the title, an `<h2>` by default: `titleRender={<h3 />}`. */
|
|
12
|
+
titleRender?: ReactElement;
|
|
13
|
+
/**
|
|
14
|
+
* The cards: `LinkCard`s, three to five as on the website. Each one is put
|
|
15
|
+
* in an item of a list.
|
|
16
|
+
*/
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* A grid of `LinkCard`s under a title, as the "Hva kan vi hjelpe deg med?"
|
|
21
|
+
* block on leabank.no's customer service page.
|
|
22
|
+
*
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <Section surface="subtle">
|
|
25
|
+
* <NavigationGrid title="Hva kan vi hjelpe deg med?">
|
|
26
|
+
* <LinkCard render={<NextLink href="/lan" />} title="Lån" surface="muted" />
|
|
27
|
+
* <LinkCard render={<NextLink href="/sparing" />} title="Sparing" surface="contrast" />
|
|
28
|
+
* <LinkCard render={<NextLink href="/forsikring" />} title="Forsikring" surface="muted" />
|
|
29
|
+
* </NavigationGrid>
|
|
30
|
+
* </Section>
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* From 1024px the cards are two to a row of four columns, each two columns
|
|
34
|
+
* wide; with an odd number of cards the first row holds three, the first two
|
|
35
|
+
* one column wide (1 + 1 + 2). Rows are 300px, or taller for a long title.
|
|
36
|
+
* Between 768 and 1024px two columns, the wide cards taking a row of their
|
|
37
|
+
* own; below 768px one column. The cards are a list.
|
|
38
|
+
*/
|
|
39
|
+
export declare function NavigationGrid({ title, titleRender, render, ref, className, children, ...rest }: NavigationGridProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* A text prop of the sections: a string or a number becomes one `<p>`, and
|
|
4
|
+
* anything else (paragraphs the page passes, rich text from the CMS) goes in
|
|
5
|
+
* a `<div>`, so a `<p>` never holds another. Internal.
|
|
6
|
+
*/
|
|
7
|
+
export declare function Paragraphs({ className, id, children, }: {
|
|
8
|
+
className?: string;
|
|
9
|
+
id?: string;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ReactElement, ReactNode, Ref } from 'react';
|
|
3
|
+
/** `alt` is required with a logo. */
|
|
4
|
+
type PartnerListLogo = {
|
|
5
|
+
/** The partner's logo, shown on a white tile. */
|
|
6
|
+
src: string;
|
|
7
|
+
/**
|
|
8
|
+
* The partner's name, for screen readers; `""` when the text beside
|
|
9
|
+
* the logo already names the partner.
|
|
10
|
+
*/
|
|
11
|
+
alt: string;
|
|
12
|
+
/**
|
|
13
|
+
* The image element to render instead of the plain `<img>`, as on
|
|
14
|
+
* `PartnerRow`: `next/image`, or an `<img loading="lazy">`.
|
|
15
|
+
*/
|
|
16
|
+
imageRender?: ReactElement;
|
|
17
|
+
} | {
|
|
18
|
+
src?: undefined;
|
|
19
|
+
alt?: undefined;
|
|
20
|
+
imageRender?: undefined;
|
|
21
|
+
};
|
|
22
|
+
/** One partner in the list. */
|
|
23
|
+
export type PartnerListItem = PartnerListLogo & {
|
|
24
|
+
/** The partner's name. The list is sorted by it. */
|
|
25
|
+
name: string;
|
|
26
|
+
/**
|
|
27
|
+
* The text about the partner, beside the logo: usually `RichText` with the
|
|
28
|
+
* CMS content, whose heading is the name.
|
|
29
|
+
*/
|
|
30
|
+
content: ReactNode;
|
|
31
|
+
};
|
|
32
|
+
export type PartnerListProps = Omit<useRender.ComponentProps<"div">, "ref" | "children" | "defaultValue" | "onChange"> & {
|
|
33
|
+
/** The rendered element: the `<div>`, or the element passed to `render`. */
|
|
34
|
+
ref?: Ref<HTMLElement>;
|
|
35
|
+
/** The partners, in any order. */
|
|
36
|
+
items: readonly PartnerListItem[];
|
|
37
|
+
/**
|
|
38
|
+
* How many partners a page shows.
|
|
39
|
+
* @default 9
|
|
40
|
+
*/
|
|
41
|
+
pageSize?: number;
|
|
42
|
+
/** The page shown, counted from 1. Pass it to control the list. */
|
|
43
|
+
value?: number;
|
|
44
|
+
/**
|
|
45
|
+
* The page shown first when the list is not controlled.
|
|
46
|
+
* @default 1
|
|
47
|
+
*/
|
|
48
|
+
defaultValue?: number;
|
|
49
|
+
/** Called with the page number when the visitor turns the page. */
|
|
50
|
+
onValueChange?: (page: number) => void;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The website's list of partners, as on leabank.no/om-oss/samarbeidspartnere:
|
|
54
|
+
* a `PartnerRow` per partner, sorted by name, nine to a page, with previous
|
|
55
|
+
* and next buttons and a dot per page under them.
|
|
56
|
+
*
|
|
57
|
+
* ```tsx
|
|
58
|
+
* <Section surface="subtle" width="wide">
|
|
59
|
+
* <PartnerList
|
|
60
|
+
* items={partners.map((partner) => ({
|
|
61
|
+
* name: partner.name,
|
|
62
|
+
* content: <RichText>…</RichText>,
|
|
63
|
+
* src: partner.logo,
|
|
64
|
+
* alt: "",
|
|
65
|
+
* }))}
|
|
66
|
+
* />
|
|
67
|
+
* </Section>
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* The partners are sorted in the `LeaProvider` language (Å after Z in
|
|
71
|
+
* Norwegian and Swedish, Ä and Ö in Swedish and Finnish order), so the
|
|
72
|
+
* order follows the market. The controls show from two pages: elevated
|
|
73
|
+
* buttons named "Forrige side" and "Neste side", which stay focusable at the
|
|
74
|
+
* first and last page, and `PaginationDots`; the new page is announced as
|
|
75
|
+
* "Side 2 av 3". The list takes the width it is given: on the website a
|
|
76
|
+
* `Section` with `width="wide"`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function PartnerList({ items, pageSize, value: valueProp, defaultValue, onValueChange, render, ref, className, ...rest }: PartnerListProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | null;
|
|
79
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import { PanelProps } from '../index';
|
|
3
|
+
export type PaymentFeatureImagePosition = "start" | "end";
|
|
4
|
+
/** A logo in the row at the top. */
|
|
5
|
+
export type PaymentFeatureLogo = {
|
|
6
|
+
/** The logo file. */
|
|
7
|
+
src: string;
|
|
8
|
+
/** The name of the brand, for screen readers. */
|
|
9
|
+
alt: string;
|
|
10
|
+
/**
|
|
11
|
+
* The image element to render instead of the plain `<img>`, such as
|
|
12
|
+
* `next/image` with the logo's own `width` and `height`.
|
|
13
|
+
*/
|
|
14
|
+
imageRender?: ReactElement;
|
|
15
|
+
};
|
|
16
|
+
/** `alt` is required with a photo, `""` when it is decoration. */
|
|
17
|
+
type PaymentFeatureImage = {
|
|
18
|
+
/** The photo beside the text. Without one, the text takes the card. */
|
|
19
|
+
src: string;
|
|
20
|
+
/**
|
|
21
|
+
* What the photo shows, for screen readers; `""` when it is decoration
|
|
22
|
+
* and the text says it all.
|
|
23
|
+
*/
|
|
24
|
+
alt: string;
|
|
25
|
+
/**
|
|
26
|
+
* The image element to render instead of the plain `<img>`, such as
|
|
27
|
+
* `next/image`. Its own props win over `src` and `alt`.
|
|
28
|
+
*/
|
|
29
|
+
imageRender?: ReactElement;
|
|
30
|
+
} | {
|
|
31
|
+
src?: undefined;
|
|
32
|
+
alt?: undefined;
|
|
33
|
+
imageRender?: undefined;
|
|
34
|
+
};
|
|
35
|
+
export type PaymentFeatureProps = Omit<PanelProps, "title" | "children" | "size"> & PaymentFeatureImage & {
|
|
36
|
+
/** The logos of the payment brands, in a row over the text. */
|
|
37
|
+
logos?: readonly PaymentFeatureLogo[];
|
|
38
|
+
/** The title. */
|
|
39
|
+
title: ReactNode;
|
|
40
|
+
/** The element for the title, an `<h2>` by default: `titleRender={<h3 />}`. */
|
|
41
|
+
titleRender?: ReactElement;
|
|
42
|
+
/**
|
|
43
|
+
* The text under the title. A string becomes one paragraph; pass `<p>`
|
|
44
|
+
* elements for several.
|
|
45
|
+
*/
|
|
46
|
+
text?: ReactNode;
|
|
47
|
+
/**
|
|
48
|
+
* The calls to action, in a row that wraps: an `ActionButton`, a `Link`
|
|
49
|
+
* with `arrow`, or both.
|
|
50
|
+
*/
|
|
51
|
+
actions?: ReactNode;
|
|
52
|
+
/** The price example under the actions, in the small print. */
|
|
53
|
+
priceExample?: ReactNode;
|
|
54
|
+
/**
|
|
55
|
+
* Where the photo sits: `"start"` before the text (on the left, or on
|
|
56
|
+
* top below 1024px), `"end"` after it.
|
|
57
|
+
* @default "end"
|
|
58
|
+
*/
|
|
59
|
+
imagePosition?: PaymentFeatureImagePosition;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* A payment feature on a white `Panel`: a row of brand logos, a title, a
|
|
63
|
+
* text and the calls to action in one column, and a photo in the other.
|
|
64
|
+
*
|
|
65
|
+
* ```tsx
|
|
66
|
+
* <Section surface="subtle">
|
|
67
|
+
* <PaymentFeature
|
|
68
|
+
* logos={[{ src: "/logoer/vipps.svg", alt: "Vipps" }, { src: "/logoer/visa.svg", alt: "Visa" }]}
|
|
69
|
+
* title="Betal med Lea Bank i nettbutikken"
|
|
70
|
+
* text="Del opp betalingen eller betal senere når du handler hos våre partnere."
|
|
71
|
+
* actions={<ActionButton render={<NextLink href="/betaling" />}>Les mer</ActionButton>}
|
|
72
|
+
* src="/bilder/betaling.jpg"
|
|
73
|
+
* alt=""
|
|
74
|
+
* />
|
|
75
|
+
* </Section>
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* From 1024px the text column is at most 560px and the photo, at most 435px
|
|
79
|
+
* wide, sits at the end of the other column; below 1024px they stack 32px
|
|
80
|
+
* apart. The logos are up to 48px tall (32px below 768px) with a line between
|
|
81
|
+
* them, and wrap on a narrow screen. Put it on a coloured section: the panel
|
|
82
|
+
* is white.
|
|
83
|
+
*/
|
|
84
|
+
export declare function PaymentFeature({ logos, title, titleRender, text, actions, priceExample, src, alt, imageRender, imagePosition, className, ...rest }: PaymentFeatureProps): import("react").JSX.Element;
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ReactElement, ReactNode, Ref } from 'react';
|
|
3
|
+
export type PromoGridImagePosition = "start" | "end";
|
|
4
|
+
/** One of the smaller photos over the text. */
|
|
5
|
+
export type PromoGridImage = {
|
|
6
|
+
/** The photo. */
|
|
7
|
+
src: string;
|
|
8
|
+
/** What the photo shows, for screen readers; `""` when it is decoration. */
|
|
9
|
+
alt: string;
|
|
10
|
+
/**
|
|
11
|
+
* The image element to render instead of the plain `<img>`, such as
|
|
12
|
+
* `next/image` with `fill`. Its own props win over `src` and `alt`.
|
|
13
|
+
*/
|
|
14
|
+
imageRender?: ReactElement;
|
|
15
|
+
};
|
|
16
|
+
export type PromoGridProps = Omit<useRender.ComponentProps<"div">, "ref" | "title" | "children"> & {
|
|
17
|
+
/** The rendered element: the `<div>`, or the element passed to `render`. */
|
|
18
|
+
ref?: Ref<HTMLElement>;
|
|
19
|
+
/** The large photo. */
|
|
20
|
+
src: string;
|
|
21
|
+
/** What the large photo shows, for screen readers; `""` when it is decoration. */
|
|
22
|
+
alt: string;
|
|
23
|
+
/**
|
|
24
|
+
* The image element to render for the large photo instead of the plain
|
|
25
|
+
* `<img>`, as on `FeaturedImage`.
|
|
26
|
+
*/
|
|
27
|
+
imageRender?: ReactElement;
|
|
28
|
+
/** A call to action on the large photo: an `ActionButton`. */
|
|
29
|
+
action?: ReactNode;
|
|
30
|
+
/** One or two smaller photos over the text, side by side. */
|
|
31
|
+
images?: readonly [PromoGridImage] | readonly [PromoGridImage, PromoGridImage];
|
|
32
|
+
/** The title on the beige block, in capitals. */
|
|
33
|
+
title: ReactNode;
|
|
34
|
+
/** The element for the title, an `<h2>` by default: `titleRender={<h3 />}`. */
|
|
35
|
+
titleRender?: ReactElement;
|
|
36
|
+
/**
|
|
37
|
+
* The text under the title. A string becomes one paragraph; pass `<p>`
|
|
38
|
+
* elements for several.
|
|
39
|
+
*/
|
|
40
|
+
subtitle?: ReactNode;
|
|
41
|
+
/**
|
|
42
|
+
* Where the large photo sits from 1024px: `"start"` (on the left) or
|
|
43
|
+
* `"end"`. Below 1024px it is always on top.
|
|
44
|
+
* @default "start"
|
|
45
|
+
*/
|
|
46
|
+
imagePosition?: PromoGridImagePosition;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* A promotion of photos and a title: a large `FeaturedImage` on one side, and
|
|
50
|
+
* on the other one or two photos over a beige block with the title in
|
|
51
|
+
* capitals, as on leabank.no's about page.
|
|
52
|
+
*
|
|
53
|
+
* ```tsx
|
|
54
|
+
* <Section>
|
|
55
|
+
* <PromoGrid
|
|
56
|
+
* src="/bilder/kontor.jpg"
|
|
57
|
+
* alt=""
|
|
58
|
+
* action={<ActionButton render={<NextLink href="/lan" />}>Se våre lån</ActionButton>}
|
|
59
|
+
* images={[{ src: "/bilder/team.jpg", alt: "" }]}
|
|
60
|
+
* title="Lån til det du trenger"
|
|
61
|
+
* subtitle="Vi hjelper deg med lån uten sikkerhet til det du har lyst på."
|
|
62
|
+
* />
|
|
63
|
+
* </Section>
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* From 1024px two equal columns 600px tall, 16px apart, the smaller photos
|
|
67
|
+
* taking the room the block leaves. Below 1024px everything stacks, the
|
|
68
|
+
* photos at 1 : 0.5, the two smaller ones side by side down to 768px. The
|
|
69
|
+
* block is beige with dark text on any section.
|
|
70
|
+
*/
|
|
71
|
+
export declare function PromoGrid({ src, alt, imageRender, action, images, title, titleRender, subtitle, imagePosition, render, ref, className, ...rest }: PromoGridProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ReactElement, ReactNode, Ref } from 'react';
|
|
3
|
+
export type SectionHeaderTitleSize = "sm" | "lg";
|
|
4
|
+
export type SectionHeaderProps = Omit<useRender.ComponentProps<"div">, "ref" | "title" | "children"> & {
|
|
5
|
+
/** The rendered element: the `<div>`, or the element passed to `render`. */
|
|
6
|
+
ref?: Ref<HTMLElement>;
|
|
7
|
+
/** The short line above the title. */
|
|
8
|
+
eyebrow?: ReactNode;
|
|
9
|
+
/** The title of the section. */
|
|
10
|
+
title: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* The element for the title, an `<h2>` by default. Pass another level where
|
|
13
|
+
* the page outline needs one: `titleRender={<h1 />}`.
|
|
14
|
+
*/
|
|
15
|
+
titleRender?: ReactElement;
|
|
16
|
+
/**
|
|
17
|
+
* `"lg"`: 41px (26px below 768px). `"sm"`: 26px at every width.
|
|
18
|
+
* @default "lg"
|
|
19
|
+
*/
|
|
20
|
+
titleSize?: SectionHeaderTitleSize;
|
|
21
|
+
/**
|
|
22
|
+
* The text under the title, at most 720px wide. A string becomes one
|
|
23
|
+
* paragraph; pass `<p>` elements for several.
|
|
24
|
+
*/
|
|
25
|
+
subtitle?: ReactNode;
|
|
26
|
+
/**
|
|
27
|
+
* The calls to action, in a centred row that wraps: an `ActionButton`,
|
|
28
|
+
* a `Link` with `arrow`, or both. The row is only there when this is.
|
|
29
|
+
*/
|
|
30
|
+
actions?: ReactNode;
|
|
31
|
+
/** The price example under the actions, in the small print. */
|
|
32
|
+
priceExample?: ReactNode;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The centred heading of a website section: a short line, the title, a text
|
|
36
|
+
* of at most 720px and a row of calls to action, as at the top of the
|
|
37
|
+
* sections on leabank.no.
|
|
38
|
+
*
|
|
39
|
+
* ```tsx
|
|
40
|
+
* <Section>
|
|
41
|
+
* <SectionHeader
|
|
42
|
+
* eyebrow="Om Lea Bank"
|
|
43
|
+
* title="Vi gjør det enkelt å ta smarte økonomiske valg"
|
|
44
|
+
* subtitle="Lea Bank er en digital bank …"
|
|
45
|
+
* actions={<ActionButton render={<NextLink href="/om-oss" />}>Les mer om oss</ActionButton>}
|
|
46
|
+
* />
|
|
47
|
+
* </Section>
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* It takes the text colour of its section. The parts are 16px apart and the
|
|
51
|
+
* actions 32px under them; the actions are 32px apart.
|
|
52
|
+
*/
|
|
53
|
+
export declare function SectionHeader({ eyebrow, title, titleRender, titleSize, subtitle, actions, priceExample, render, ref, className, ...rest }: SectionHeaderProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { Ref } from 'react';
|
|
3
|
+
import { SurfaceRoles } from '../components/color-roles';
|
|
4
|
+
export type SectionSurface = SurfaceRoles<"base" | "subtle" | "muted" | "contrast" | "contrast-accent">;
|
|
5
|
+
export type SectionSpacing = "none" | "sm" | "lg";
|
|
6
|
+
export type SectionWidth = "full" | "wide" | "narrow";
|
|
7
|
+
export type SectionProps = Omit<useRender.ComponentProps<"section">, "ref"> & {
|
|
8
|
+
/** The rendered element: the `<section>`, or the element passed to `render`. */
|
|
9
|
+
ref?: Ref<HTMLElement>;
|
|
10
|
+
/**
|
|
11
|
+
* The colour of the band, after its `bg` token: `"base"` (white),
|
|
12
|
+
* `"subtle"` (grey), `"muted"` (beige), `"contrast"` (near-black) or
|
|
13
|
+
* `"contrast-accent"` (deep purple). On the last two the text is white;
|
|
14
|
+
* give a `Link` inside `color="contrast"` there.
|
|
15
|
+
* @default "base"
|
|
16
|
+
*/
|
|
17
|
+
surface?: SectionSurface;
|
|
18
|
+
/**
|
|
19
|
+
* The room above the content: `"lg"` 112px (64px below 768px), `"sm"` 64px
|
|
20
|
+
* (32px), `"none"`.
|
|
21
|
+
* @default "lg"
|
|
22
|
+
*/
|
|
23
|
+
spacingTop?: SectionSpacing;
|
|
24
|
+
/**
|
|
25
|
+
* The room below the content, in the same steps as `spacingTop`.
|
|
26
|
+
* @default "lg"
|
|
27
|
+
*/
|
|
28
|
+
spacingBottom?: SectionSpacing;
|
|
29
|
+
/**
|
|
30
|
+
* How much of the content column the content takes, centred: `"full"`,
|
|
31
|
+
* `"wide"` (75 %) or `"narrow"` (60 %). Below 1024px it is always the full
|
|
32
|
+
* column.
|
|
33
|
+
* @default "full"
|
|
34
|
+
*/
|
|
35
|
+
width?: SectionWidth;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* A band of a website page: the colour from edge to edge, the content in a
|
|
39
|
+
* column of at most 1312px in the middle, 64px from the sides (16px below
|
|
40
|
+
* 768px). Every block on leabank.no sits in one.
|
|
41
|
+
*
|
|
42
|
+
* ```tsx
|
|
43
|
+
* <Section surface="subtle" spacingTop="none">
|
|
44
|
+
* <SectionHeader title="Vi gjør det enkelt å ta smarte økonomiske valg" />
|
|
45
|
+
* </Section>
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* The section sets the text colour for what is inside it, white on the dark
|
|
49
|
+
* surfaces, so text, a vertical `MediaCard` and the sections that have no
|
|
50
|
+
* colour of their own follow it. Renders a `section`; pass `render` for
|
|
51
|
+
* another element.
|
|
52
|
+
*/
|
|
53
|
+
export declare function Section({ surface, spacingTop, spacingBottom, width, render, ref, className, children, ...rest }: SectionProps): import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ReactNode, Ref } from 'react';
|
|
3
|
+
export type ServiceCardGridProps = Omit<useRender.ComponentProps<"div">, "ref" | "children"> & {
|
|
4
|
+
/** The rendered element: the `<div>`, or the element passed to `render`. */
|
|
5
|
+
ref?: Ref<HTMLElement>;
|
|
6
|
+
/**
|
|
7
|
+
* The cards: one to four `ServiceCard`s, in the order of the website's
|
|
8
|
+
* grid. The first two are `layout="stacked"` (the default); give the third
|
|
9
|
+
* and fourth `layout="row"`. Each one is put in an item of a list.
|
|
10
|
+
*/
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* The website's grid of service cards, as on leabank.no/lan: a large card
|
|
15
|
+
* and a narrow one side by side, then a wide row under them.
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <Section surface="muted">
|
|
19
|
+
* <ServiceCardGrid>
|
|
20
|
+
* <ServiceCard render={<NextLink href="/lan/forbrukslan" />} title="Forbrukslån" … />
|
|
21
|
+
* <ServiceCard render={<NextLink href="/lan/refinansiering" />} title="Refinansiering" … />
|
|
22
|
+
* <ServiceCard render={<NextLink href="/sparing" />} layout="row" title="Sparing" … />
|
|
23
|
+
* <ServiceCard render={<NextLink href="/betalingsforsikring" />} layout="row" title="Betalingsforsikring" … />
|
|
24
|
+
* </ServiceCardGrid>
|
|
25
|
+
* </Section>
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* From 1024px three columns: the first card two columns wide and the second
|
|
29
|
+
* one, both 576px tall; a third card takes the row under them (320px) on its
|
|
30
|
+
* own, or the first column of it with a fourth in the other two. Below
|
|
31
|
+
* 1024px one column, each card at most 440px tall. The cards are a list.
|
|
32
|
+
*/
|
|
33
|
+
export declare function ServiceCardGrid({ render, ref, className, children, ...rest }: ServiceCardGridProps): import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ReactElement, ReactNode, Ref } from 'react';
|
|
3
|
+
export type SplitContentImagePosition = "start" | "end";
|
|
4
|
+
/** `alt` is required with a photo, `""` when it is decoration. */
|
|
5
|
+
type SplitContentImage = {
|
|
6
|
+
/** The photo. Without one, the text takes the whole width. */
|
|
7
|
+
src: string;
|
|
8
|
+
/**
|
|
9
|
+
* What the photo shows, for screen readers; `""` when it is decoration
|
|
10
|
+
* and the text says it all.
|
|
11
|
+
*/
|
|
12
|
+
alt: string;
|
|
13
|
+
/**
|
|
14
|
+
* The image element to render instead of the plain `<img>`, such as
|
|
15
|
+
* `next/image`, or an `<img loading="lazy">`. Its own props win over
|
|
16
|
+
* `src` and `alt`.
|
|
17
|
+
*/
|
|
18
|
+
imageRender?: ReactElement;
|
|
19
|
+
} | {
|
|
20
|
+
src?: undefined;
|
|
21
|
+
alt?: undefined;
|
|
22
|
+
imageRender?: undefined;
|
|
23
|
+
};
|
|
24
|
+
export type SplitContentProps = Omit<useRender.ComponentProps<"div">, "ref" | "title" | "children"> & SplitContentImage & {
|
|
25
|
+
/** The rendered element: the `<div>`, or the element passed to `render`. */
|
|
26
|
+
ref?: Ref<HTMLElement>;
|
|
27
|
+
/** The title. */
|
|
28
|
+
title: ReactNode;
|
|
29
|
+
/** The element for the title, an `<h2>` by default: `titleRender={<h3 />}`. */
|
|
30
|
+
titleRender?: ReactElement;
|
|
31
|
+
/**
|
|
32
|
+
* The text under the title. A string becomes one paragraph; pass `<p>`
|
|
33
|
+
* elements for several.
|
|
34
|
+
*/
|
|
35
|
+
text?: ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Where the photo sits: `"start"` before the text (on the left, or on
|
|
38
|
+
* top below 1024px), `"end"` after it.
|
|
39
|
+
* @default "end"
|
|
40
|
+
*/
|
|
41
|
+
imagePosition?: SplitContentImagePosition;
|
|
42
|
+
/** The call to action under both columns: an `ActionButton`. */
|
|
43
|
+
action?: ReactNode;
|
|
44
|
+
/** The price example under the action, in the small print. */
|
|
45
|
+
priceExample?: ReactNode;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Text beside a photo, on the section's own colour: a title and a text in one
|
|
49
|
+
* column, a photo without corners in the other, and the call to action
|
|
50
|
+
* centred under both.
|
|
51
|
+
*
|
|
52
|
+
* ```tsx
|
|
53
|
+
* <Section surface="subtle">
|
|
54
|
+
* <SplitContent
|
|
55
|
+
* title="Refinansier dyre smålån"
|
|
56
|
+
* text="Samle kredittkortgjeld og smålån i ett lån med én månedlig betaling."
|
|
57
|
+
* src="/bilder/par.jpg"
|
|
58
|
+
* alt=""
|
|
59
|
+
* action={<ActionButton render={<NextLink href="/refinansiering" />}>Søk om refinansiering</ActionButton>}
|
|
60
|
+
* />
|
|
61
|
+
* </Section>
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* Two equal columns 64px apart from 1024px, the photo at most 560px wide at
|
|
65
|
+
* the end of its column; one column below, the photo at most 440px and
|
|
66
|
+
* the action at the start. It takes the text colour of its section.
|
|
67
|
+
*/
|
|
68
|
+
export declare function SplitContent({ title, titleRender, text, src, alt, imageRender, imagePosition, action, priceExample, render, ref, className, ...rest }: SplitContentProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ReactElement, ReactNode, Ref } from 'react';
|
|
3
|
+
/** One number, with what it stands for. */
|
|
4
|
+
export type StatsItem = {
|
|
5
|
+
/** The big number: a figure, or the step of a process. */
|
|
6
|
+
number: ReactNode;
|
|
7
|
+
/** What the number is. */
|
|
8
|
+
title?: ReactNode;
|
|
9
|
+
/** A line about it, under the title. */
|
|
10
|
+
text?: ReactNode;
|
|
11
|
+
};
|
|
12
|
+
export type StatsProps = Omit<useRender.ComponentProps<"div">, "ref" | "children"> & {
|
|
13
|
+
/** The rendered element: the `<div>`, or the element passed to `render`. */
|
|
14
|
+
ref?: Ref<HTMLElement>;
|
|
15
|
+
/** The heading above the numbers: a `SectionHeader`. */
|
|
16
|
+
header?: ReactNode;
|
|
17
|
+
/** The numbers, in a row from 1024px. Two to four fit the website's row. */
|
|
18
|
+
items: readonly StatsItem[];
|
|
19
|
+
/**
|
|
20
|
+
* The element for the title of each number, an `<h3>` by default, as the
|
|
21
|
+
* titles sit under the section's `<h2>`: `titleRender={<p />}` where they
|
|
22
|
+
* should not be headings.
|
|
23
|
+
*/
|
|
24
|
+
titleRender?: ReactElement;
|
|
25
|
+
/** The call to action under the numbers: an `ActionButton`. */
|
|
26
|
+
action?: ReactNode;
|
|
27
|
+
/** The price example under the action, in the small print. */
|
|
28
|
+
priceExample?: ReactNode;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A row of big numbers with a line on each side, each with a title and a
|
|
32
|
+
* line of text, as the four steps of "Slik fungerer det" on leabank.no's
|
|
33
|
+
* loan pages. The numbers are a list.
|
|
34
|
+
*
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <Section>
|
|
37
|
+
* <Stats
|
|
38
|
+
* header={<SectionHeader eyebrow="Søk uforpliktende" title="Slik fungerer det" />}
|
|
39
|
+
* items={[
|
|
40
|
+
* { number: "1", title: "Fyll inn søknaden", text: "Tar ca. 3 minutter." },
|
|
41
|
+
* { number: "2", title: "Send inn søknad", text: "…" },
|
|
42
|
+
* ]}
|
|
43
|
+
* />
|
|
44
|
+
* </Section>
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* From 1024px the numbers are 224px, at least 200px wide each, with rounded
|
|
48
|
+
* bars filling the space between and around them; below 1024px they are
|
|
49
|
+
* 160px in a row without bars, and below 768px 128px in a column. The bars
|
|
50
|
+
* and the text follow the section's text colour.
|
|
51
|
+
*/
|
|
52
|
+
export declare function Stats({ header, items, titleRender, action, priceExample, render, ref, className, ...rest }: StatsProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import { ReactElement, ReactNode, Ref } from 'react';
|
|
3
|
+
export type TestimonialsVideoPosition = "start" | "end";
|
|
4
|
+
/** The video's other props only make sense with a video. */
|
|
5
|
+
type TestimonialsVideo = {
|
|
6
|
+
/**
|
|
7
|
+
* A video of the featured customer, shown as a square still with a
|
|
8
|
+
* play button that opens it in a dialog, with sound and controls.
|
|
9
|
+
*/
|
|
10
|
+
videoSrc: string;
|
|
11
|
+
/**
|
|
12
|
+
* The still to show. Left out, the video's first frame is shown, which
|
|
13
|
+
* loads the start of the video with the page.
|
|
14
|
+
*/
|
|
15
|
+
videoPoster?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Captions for the video, a WebVTT file in the `LeaProvider` language.
|
|
18
|
+
* A video in which people speak needs them.
|
|
19
|
+
*/
|
|
20
|
+
videoCaptions?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Where the video sits from 768px: `"start"` (on the left of the quote)
|
|
23
|
+
* or `"end"`. Below 768px it is always above the quote.
|
|
24
|
+
* @default "start"
|
|
25
|
+
*/
|
|
26
|
+
videoPosition?: TestimonialsVideoPosition;
|
|
27
|
+
} | {
|
|
28
|
+
videoSrc?: undefined;
|
|
29
|
+
videoPoster?: undefined;
|
|
30
|
+
videoCaptions?: undefined;
|
|
31
|
+
videoPosition?: undefined;
|
|
32
|
+
};
|
|
33
|
+
/** A subtitle goes under a title. */
|
|
34
|
+
type TestimonialsHeader = {
|
|
35
|
+
/** The title of the section. It also names the carousel. */
|
|
36
|
+
title: ReactNode;
|
|
37
|
+
/**
|
|
38
|
+
* The element for the title, an `<h2>` by default, as on
|
|
39
|
+
* `SectionHeader`.
|
|
40
|
+
*/
|
|
41
|
+
titleRender?: ReactElement;
|
|
42
|
+
/** The text under the title. */
|
|
43
|
+
subtitle?: ReactNode;
|
|
44
|
+
} | {
|
|
45
|
+
title?: undefined;
|
|
46
|
+
titleRender?: undefined;
|
|
47
|
+
subtitle?: undefined;
|
|
48
|
+
};
|
|
49
|
+
export type TestimonialsProps = Omit<useRender.ComponentProps<"div">, "ref" | "title" | "children"> & TestimonialsHeader & TestimonialsVideo & {
|
|
50
|
+
/** The rendered element: the `<div>`, or the element passed to `render`. */
|
|
51
|
+
ref?: Ref<HTMLElement>;
|
|
52
|
+
/**
|
|
53
|
+
* What the featured customer said, without quotation marks: the section
|
|
54
|
+
* adds them. Shown large beside the video. A string becomes one
|
|
55
|
+
* paragraph; pass `<p>` elements for several.
|
|
56
|
+
*/
|
|
57
|
+
quote?: ReactNode;
|
|
58
|
+
/** Who said the featured quote. */
|
|
59
|
+
name?: ReactNode;
|
|
60
|
+
/** A line under the name, such as the position and the company. */
|
|
61
|
+
meta?: ReactNode;
|
|
62
|
+
/** Stars above the featured quote, from 0 to 5. Left out, no stars. */
|
|
63
|
+
rating?: number;
|
|
64
|
+
/** The reviews in the carousel: `TestimonialCard`s. */
|
|
65
|
+
children?: ReactNode;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* The website's block of customer reviews: a centred title, a featured
|
|
69
|
+
* customer with a video, and a carousel of `TestimonialCard`s, as on the home
|
|
70
|
+
* page of leabank.no.
|
|
71
|
+
*
|
|
72
|
+
* ```tsx
|
|
73
|
+
* <Section surface="subtle">
|
|
74
|
+
* <Testimonials
|
|
75
|
+
* title="Kundeanmeldelser"
|
|
76
|
+
* subtitle="Se hva andre synes om oss"
|
|
77
|
+
* rating={5}
|
|
78
|
+
* quote="Lea Bank gjorde det enkelt å samle lånene mine."
|
|
79
|
+
* name="Marte Olsen"
|
|
80
|
+
* meta="Kunde, Oslo"
|
|
81
|
+
* videoSrc="/video/marte.mp4"
|
|
82
|
+
* videoPoster="/video/marte.jpg"
|
|
83
|
+
* >
|
|
84
|
+
* <TestimonialCard rating={5} quote="…" name="Kari Nordmann" meta="Kunde, bytt.no" />
|
|
85
|
+
* <TestimonialCard rating={5} quote="…" name="Ola Hansen" meta="Kunde, bytt.no" />
|
|
86
|
+
* </Testimonials>
|
|
87
|
+
* </Section>
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* The parts are 64px apart. From 768px the video (a square with 64px
|
|
91
|
+
* corners, dimmed under its play button) and the featured quote share the
|
|
92
|
+
* width, 64px apart; below 768px the video is on top. The play button,
|
|
93
|
+
* named "Spill av video", opens the video in a dialog with its controls and
|
|
94
|
+
* captions, and the focus comes back to it when the dialog closes. The
|
|
95
|
+
* reviews are a `Carousel`, named by the title (or "Kundeomtaler" without
|
|
96
|
+
* one). It takes the text colour of its section; the carousel's controls
|
|
97
|
+
* are made for the light surfaces.
|
|
98
|
+
*/
|
|
99
|
+
export declare function Testimonials({ title, titleRender, subtitle, quote, name, meta, rating, videoSrc, videoPoster, videoCaptions, videoPosition, render, ref, className, children, ...rest }: TestimonialsProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
100
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words of `Carousel`. `carousel` describes the region to screen readers
|
|
3
|
+
* (`aria-roledescription`); `{page}` and `{count}` in `status` are replaced
|
|
4
|
+
* with the page shown and the number of pages.
|
|
5
|
+
*/
|
|
6
|
+
export declare const useCarouselLabels: () => Record<"status" | "next" | "previous" | "carousel", string>;
|