@leabankab/component-library 8.7.0 → 8.9.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/component-library.es.js +906 -881
  3. package/dist/component-library.es.js.map +1 -1
  4. package/dist/component-library.umd.js +2 -2
  5. package/dist/component-library.umd.js.map +1 -1
  6. package/dist/components/form/select-field.d.ts +20 -1
  7. package/dist/components/form/select.d.ts +13 -3
  8. package/dist/components/form/slider.d.ts +15 -2
  9. package/dist/index.css +1 -1
  10. package/dist/website/alert-banner.d.ts +48 -0
  11. package/dist/website/arrow-reveal-link.d.ts +22 -0
  12. package/dist/website/brand-letters.d.ts +40 -0
  13. package/dist/website/calculator.d.ts +58 -0
  14. package/dist/website/carousel.d.ts +55 -0
  15. package/dist/website/cta-banner.d.ts +42 -0
  16. package/dist/website/expanding-cards-context.d.ts +8 -0
  17. package/dist/website/expanding-cards-item.d.ts +69 -0
  18. package/dist/website/expanding-cards.d.ts +48 -0
  19. package/dist/website/flags.d.ts +7 -0
  20. package/dist/website/hero-service-grid.d.ts +52 -0
  21. package/dist/website/hero.d.ts +57 -0
  22. package/dist/website/index.d.ts +37 -0
  23. package/dist/website/navigation-grid.d.ts +39 -0
  24. package/dist/website/paragraphs.d.ts +11 -0
  25. package/dist/website/partner-list.d.ts +79 -0
  26. package/dist/website/payment-feature.d.ts +85 -0
  27. package/dist/website/promo-grid.d.ts +71 -0
  28. package/dist/website/section-header.d.ts +53 -0
  29. package/dist/website/section.d.ts +53 -0
  30. package/dist/website/service-card-grid.d.ts +33 -0
  31. package/dist/website/side-nav.d.ts +57 -0
  32. package/dist/website/site-footer.d.ts +122 -0
  33. package/dist/website/site-header-link.d.ts +16 -0
  34. package/dist/website/site-header-menu.d.ts +21 -0
  35. package/dist/website/site-header.d.ts +141 -0
  36. package/dist/website/split-content.d.ts +69 -0
  37. package/dist/website/stats.d.ts +52 -0
  38. package/dist/website/testimonials.d.ts +100 -0
  39. package/dist/website/use-brand-letters-labels.d.ts +2 -0
  40. package/dist/website/use-carousel-labels.d.ts +6 -0
  41. package/dist/website/use-carousel.d.ts +50 -0
  42. package/dist/website/use-partner-list-labels.d.ts +6 -0
  43. package/dist/website/use-side-nav-labels.d.ts +5 -0
  44. package/dist/website/use-site-footer-labels.d.ts +7 -0
  45. package/dist/website/use-site-header-labels.d.ts +7 -0
  46. package/dist/website/use-testimonials-labels.d.ts +6 -0
  47. package/dist/website.cjs +2 -0
  48. package/dist/website.cjs.map +1 -0
  49. package/dist/website.css +1 -0
  50. package/dist/website.mjs +1933 -0
  51. package/dist/website.mjs.map +1 -0
  52. package/package.json +7 -2
@@ -0,0 +1,48 @@
1
+ import { ComponentProps, ReactElement, ReactNode } from 'react';
2
+ /** A title, a text or both: a banner with neither does not compile. */
3
+ type AlertBannerContent = {
4
+ /** The title, 14px semibold, a heading (`titleRender`). */
5
+ title: ReactNode;
6
+ /**
7
+ * The notice. A string becomes a `<p>`; anything else (the CMS's
8
+ * paragraphs, with links) goes in a `<div>`.
9
+ */
10
+ text?: ReactNode;
11
+ } | {
12
+ title?: ReactNode;
13
+ text: ReactNode;
14
+ };
15
+ export type AlertBannerProps = Omit<ComponentProps<"div">, "children" | "title"> & AlertBannerContent & {
16
+ /**
17
+ * The element of the title.
18
+ * @default <h2 />
19
+ */
20
+ titleRender?: ReactElement;
21
+ /**
22
+ * The picture before the text, 48px, decoration: the CMS's image with
23
+ * `alt=""`, or an icon. Left out, Lucide's `TriangleAlert`; `null` for
24
+ * none.
25
+ */
26
+ icon?: ReactNode;
27
+ };
28
+ /**
29
+ * The website's notice (`AlertBanner`, the global one at the foot of every
30
+ * page and the `sections.alert-banner` block): a 48px icon beside a short
31
+ * title and a text, in the colour of the `Section` it sits in.
32
+ *
33
+ * ```tsx
34
+ * <Section surface="muted" spacingTop="sm" spacingBottom="sm">
35
+ * <AlertBanner
36
+ * title="Viktig informasjon"
37
+ * text="Lea Bank ringer deg aldri for å be om BankID, passord eller kortopplysninger."
38
+ * />
39
+ * </Section>
40
+ * ```
41
+ *
42
+ * A notice that stays on the page, not a message that has just appeared: it
43
+ * has no `role="alert"` and is not announced, and it has no close button.
44
+ * For a status message over the page, use `GlobalAlert`. The icon and the
45
+ * text are 32px apart (16 below 768px); title and text are 14px.
46
+ */
47
+ export declare function AlertBanner({ title, text, titleRender, icon, className, ...rest }: AlertBannerProps): import("react").JSX.Element;
48
+ export {};
@@ -0,0 +1,22 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ export type ArrowRevealLinkProps = useRender.ComponentProps<"a"> & {
3
+ /**
4
+ * `"md"`: the header's menus, 16px, the arrow growing in on hover. `"lg"`:
5
+ * the `SideNav`, 18px, underlined on hover, the arrow before the link to
6
+ * the current page (`aria-current="page"`) only.
7
+ * @default "md"
8
+ */
9
+ size?: "md" | "lg";
10
+ };
11
+ /**
12
+ * Internal: Figma's `.ArrowRevealLink`. At `md`, the links of the header's
13
+ * menus: a plain 16px link whose purple arrow grows in on hover while the
14
+ * text turns purple and steps aside, as the website's `DropdownLink`. At
15
+ * `lg`, the links of `SideNav`: 18px, underlined on hover, and the arrow
16
+ * marks the current page, as the website's `SidebarLink`. Not exported.
17
+ *
18
+ * Renders an `<a>`, or the element passed to `render`: a router link, or the
19
+ * `NavigationMenu.Link` of the desktop menu, which renders the page's own
20
+ * link in turn.
21
+ */
22
+ export declare function ArrowRevealLink({ render, className, children, size, ...rest }: ArrowRevealLinkProps): import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
@@ -0,0 +1,40 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ import { Ref } from 'react';
3
+ /** The video in one letter. */
4
+ export type BrandLettersVideo = {
5
+ /** The video file. It plays without sound, so it should need none. */
6
+ src: string;
7
+ /** A still to show before the video starts, and while it is paused. */
8
+ poster?: string;
9
+ };
10
+ export type BrandLettersProps = Omit<useRender.ComponentProps<"div">, "ref" | "children"> & {
11
+ /** The rendered element: the `<div>`, or the element passed to `render`. */
12
+ ref?: Ref<HTMLElement>;
13
+ /** The three videos, in the L, the E and the A. */
14
+ videos: readonly [BrandLettersVideo, BrandLettersVideo, BrandLettersVideo];
15
+ };
16
+ /**
17
+ * The letters L, E and A of the logo side by side, each filled with a silent
18
+ * video in a loop, as the brand block of leabank.no.
19
+ *
20
+ * ```tsx
21
+ * <Section>
22
+ * <BrandLetters
23
+ * videos={[
24
+ * { src: "/video/l.mp4", poster: "/video/l.jpg" },
25
+ * { src: "/video/e.mp4", poster: "/video/e.jpg" },
26
+ * { src: "/video/a.mp4", poster: "/video/a.jpg" },
27
+ * ]}
28
+ * />
29
+ * </Section>
30
+ * ```
31
+ *
32
+ * The letters share the width they are given, each 437 : 510. The videos
33
+ * start on their own once the page has loaded, unless the visitor has asked
34
+ * for reduced motion: then they wait for the button. One button under the
35
+ * letters pauses and plays all three, named "Sett videoene på pause" or
36
+ * "Spill av videoene" in the `LeaProvider` language, since moving content
37
+ * that plays on its own needs a way to stop it. The videos are decoration
38
+ * and hidden from screen readers.
39
+ */
40
+ export declare function BrandLetters({ videos, render, ref, className, ...rest }: BrandLettersProps): import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
@@ -0,0 +1,58 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ import { ReactNode, Ref } from 'react';
3
+ /** A figure the calculator works out, shown in the summary column. */
4
+ export type CalculatorResult = {
5
+ /** What the figure is: "Beregnet sparesaldo". */
6
+ label: ReactNode;
7
+ /** The figure, written out: "399 418 kr". */
8
+ value: ReactNode;
9
+ };
10
+ export type CalculatorProps = Omit<useRender.ComponentProps<"div">, "ref" | "children" | "results"> & {
11
+ /** The rendered element: the `<div>`, or the element passed to `render`. */
12
+ ref?: Ref<HTMLElement>;
13
+ /** The heading above the calculator: a `SectionHeader`. */
14
+ header?: ReactNode;
15
+ /**
16
+ * The inputs, in the panel: `Slider`s with `color="contrast"`, each with
17
+ * its `label`, `min`, `max`, `step`, `format` and `locale`.
18
+ */
19
+ children: ReactNode;
20
+ /**
21
+ * The figures worked out from the inputs, at the top of the summary
22
+ * column. The page does the sums: one result for savings, three for
23
+ * refinancing on leabank.no. A change is announced to screen readers.
24
+ */
25
+ results: readonly CalculatorResult[];
26
+ /** The call to action under the results: an `ActionButton`. */
27
+ action?: ReactNode;
28
+ /** The price example under the action, in the small print. */
29
+ priceExample?: ReactNode;
30
+ };
31
+ /**
32
+ * The website's savings and refinancing calculator: a heading, a panel of
33
+ * sliders and a column with the results and a call to action, as on
34
+ * leabank.no/sparing and leabank.no/lan. It lays the parts out; the inputs
35
+ * are `Slider`s and the sums stay with the page.
36
+ *
37
+ * ```tsx
38
+ * <Section surface="contrast-accent">
39
+ * <Calculator
40
+ * header={<SectionHeader eyebrow="Sparekalkulator" title="Se hvor mye sparingen din kan vokse" />}
41
+ * results={[{ label: "Beregnet sparesaldo", value: format(balance) }]}
42
+ * action={<ActionButton render={<NextLink href="/sparing/apne-konto" />}>Opprett konto</ActionButton>}
43
+ * >
44
+ * <Slider color="contrast" label="Startbeløp" min={0} max={1000000} step={1000} value={start} onValueChange={setStart} locale="nb-NO" format={{ style: "currency", currency: "NOK", maximumFractionDigits: 0 }} />
45
+ * …
46
+ * </Calculator>
47
+ * </Section>
48
+ * ```
49
+ *
50
+ * The header is 80px above the rest (32px below 768px). From 1024px the
51
+ * panel and a 280px column sit side by side, 64px apart: the results at the
52
+ * top of the column, right-aligned, the action and the price example at its
53
+ * foot; below 1024px one under the other, left-aligned, 32px apart. The
54
+ * panel is black at 30 % over the section, with `5xl` corners and 32px
55
+ * inside, the sliders 16px apart. It has no colour of its own and is made
56
+ * for the dark surfaces, `contrast` and `contrast-accent`.
57
+ */
58
+ export declare function Calculator({ header, results, action, priceExample, render, ref, className, children, ...rest }: CalculatorProps): import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
@@ -0,0 +1,55 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ import { ReactNode, Ref } from 'react';
3
+ /**
4
+ * A carousel is a region, so it needs a name: the title of what it shows.
5
+ * Provide exactly one of `aria-label` or `aria-labelledby`.
6
+ */
7
+ type CarouselName = {
8
+ "aria-label": string;
9
+ "aria-labelledby"?: never;
10
+ } | {
11
+ "aria-labelledby": string;
12
+ "aria-label"?: never;
13
+ };
14
+ export type CarouselProps = Omit<useRender.ComponentProps<"div">, "ref" | "children" | "aria-label" | "aria-labelledby"> & CarouselName & {
15
+ /** The rendered element: the `<div>`, or the element passed to `render`. */
16
+ ref?: Ref<HTMLElement>;
17
+ /**
18
+ * The slides, such as `TestimonialCard`s. Each one is put in an item of
19
+ * a list and stretched to the height of the tallest.
20
+ */
21
+ children: ReactNode;
22
+ /**
23
+ * The name of each dot, when "Gå til side 3" does not say enough, as on
24
+ * `PaginationDots`.
25
+ */
26
+ getItemLabel?: (page: number) => string;
27
+ };
28
+ /**
29
+ * A row of slides that scrolls sideways, as the website's carousel of
30
+ * reviews: 2.2 slides in view from 1024px and 1.15 below, 16px apart, with
31
+ * previous and next buttons and a dot per place under them.
32
+ *
33
+ * ```tsx
34
+ * <Carousel aria-labelledby={titleId}>
35
+ * <TestimonialCard rating={5} quote="…" name="Kari Nordmann" meta="Kunde, Oslo" />
36
+ * <TestimonialCard rating={5} quote="…" name="Ola Hansen" meta="Kunde, Bergen" />
37
+ * <TestimonialCard rating={4} quote="…" name="Ingrid Berg" meta="Kunde, Trondheim" />
38
+ * </Carousel>
39
+ * ```
40
+ *
41
+ * The track scrolls on its own, with scroll snap: swipe it, scroll it with a
42
+ * trackpad, or focus it and use the arrow keys. It stops at the start of
43
+ * each slide; the last slides, which can't reach the start, share the end.
44
+ * The buttons and dots move it a place at a time, and once it has moved, the
45
+ * place it comes to rest at is announced ("Side 2 av 3"). The edges fade into the section's colour where
46
+ * there is more to scroll. Under reduced motion the buttons jump instead of
47
+ * scrolling smoothly.
48
+ *
49
+ * It is a region named by `aria-label` or `aria-labelledby`, described as a
50
+ * carousel in the `LeaProvider` language. The controls show only when the
51
+ * slides don't fit. The buttons and dots are made for the light surfaces
52
+ * (`base`, `subtle`, `muted`).
53
+ */
54
+ export declare function Carousel({ getItemLabel, render, ref, className, children, ...rest }: CarouselProps): import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
55
+ export {};
@@ -0,0 +1,42 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ import { ReactElement, ReactNode, Ref } from 'react';
3
+ export type CtaBannerProps = Omit<useRender.ComponentProps<"div">, "ref" | "title" | "children"> & {
4
+ /** The rendered element: the `<div>`, or the element passed to `render`. */
5
+ ref?: Ref<HTMLElement>;
6
+ /** The big title. */
7
+ title: ReactNode;
8
+ /**
9
+ * The element for the title, an `<h2>` by default: `titleRender={<h1 />}`
10
+ * where the banner opens the page.
11
+ */
12
+ titleRender?: ReactElement;
13
+ /**
14
+ * The text beside the title. A string becomes one paragraph; pass `<p>`
15
+ * elements for several.
16
+ */
17
+ text?: ReactNode;
18
+ /** The call to action under the text: an `ActionButton`. */
19
+ action?: ReactNode;
20
+ /** The price example under the action, in the small print. */
21
+ priceExample?: ReactNode;
22
+ };
23
+ /**
24
+ * A closing call to action: a big title on the left, and a text, a button
25
+ * and the price example on the right, as at the foot of leabank.no's home
26
+ * page.
27
+ *
28
+ * ```tsx
29
+ * <Section surface="muted">
30
+ * <CtaBanner
31
+ * title="Klar for å komme i gang med Lea Bank?"
32
+ * text="Vi er her for deg og står klare til å hjelpe deg."
33
+ * action={<ActionButton render={<NextLink href="/lan" />}>Søk om forbrukslån</ActionButton>}
34
+ * />
35
+ * </Section>
36
+ * ```
37
+ *
38
+ * Two equal columns 64px apart from 1024px, one column below with the title
39
+ * at 41px. With only a title, the title takes the whole width. It takes the
40
+ * text colour of its section.
41
+ */
42
+ export declare function CtaBanner({ title, titleRender, text, action, priceExample, render, ref, className, ...rest }: CtaBannerProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Whether an `ExpandingCardsItem` is open: the one card `ExpandingCards`
3
+ * keeps open in its row from 1312px, or every card below that and outside
4
+ * the row. Internal.
5
+ */
6
+ export declare const ExpandingCardsContext: import('react').Context<{
7
+ open: boolean;
8
+ }>;
@@ -0,0 +1,69 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ import { ReactElement, ReactNode, Ref } from 'react';
3
+ import { SurfaceRoles } from '../components/color-roles';
4
+ export type ExpandingCardsItemSurface = SurfaceRoles<"base" | "subtle" | "muted" | "contrast" | "contrast-accent">;
5
+ /** `alt` is required with a photo, `""` when it is decoration. */
6
+ type ExpandingCardsItemImage = {
7
+ /** The photo: the whole card while it is closed, half of it open. */
8
+ src: string;
9
+ /** What the photo shows, for screen readers; `""` for decoration. */
10
+ alt: string;
11
+ /**
12
+ * The image element to render instead of the plain `<img>`, such as
13
+ * `next/image` with `fill`. Its own props win over `src` and `alt`.
14
+ */
15
+ imageRender?: ReactElement;
16
+ } | {
17
+ src?: undefined;
18
+ alt?: undefined;
19
+ imageRender?: undefined;
20
+ };
21
+ export type ExpandingCardsItemProps = Omit<useRender.ComponentProps<"div">, "ref" | "title" | "children"> & ExpandingCardsItemImage & {
22
+ /** The rendered element: the `<div>`, or the element passed to `render`. */
23
+ ref?: Ref<HTMLElement>;
24
+ /** The title, in capitals. */
25
+ title: ReactNode;
26
+ /**
27
+ * The element for the title, an `<h2>` by default. Pass another level
28
+ * where the page outline needs one: `titleRender={<h3 />}`.
29
+ */
30
+ titleRender?: ReactElement;
31
+ /** The text under the title. A string becomes one paragraph. */
32
+ text?: ReactNode;
33
+ /**
34
+ * The call to action: an `ActionButton`. While the card is closed it
35
+ * shows only its arrow, with the label kept for screen readers.
36
+ */
37
+ action?: ReactNode;
38
+ /**
39
+ * The colour of the card, after its `bg` token, as on `Section`. On
40
+ * `"contrast"` and `"contrast-accent"` the text is white.
41
+ * @default "base"
42
+ */
43
+ surface?: ExpandingCardsItemSurface;
44
+ };
45
+ /**
46
+ * A card of `ExpandingCards`: a photo, a title in capitals, a text and a
47
+ * call to action, on one of the five section colours.
48
+ *
49
+ * ```tsx
50
+ * <ExpandingCardsItem
51
+ * surface="contrast"
52
+ * title="Forbrukslån"
53
+ * text="Lån til det du trenger, uten sikkerhet. Søk på få minutter."
54
+ * src="/bilder/forbrukslan.jpg"
55
+ * alt=""
56
+ * action={<ActionButton render={<NextLink href="/lan/forbrukslan" />}>Søk nå</ActionButton>}
57
+ * />
58
+ * ```
59
+ *
60
+ * Open, the text takes the start half (32px inside, at the bottom) and the
61
+ * photo the end half, 16px from the card's edges. Closed (in the row of
62
+ * `ExpandingCards` from 1312px), the photo fills the card and only the
63
+ * `ActionButton`'s arrow shows; the title and text are still there for
64
+ * screen readers, and focusing the button opens the card. Below 640px the
65
+ * photo is on top at 2 : 1. Outside `ExpandingCards` the card is always
66
+ * open. At least 280px tall; it grows with its text.
67
+ */
68
+ export declare function ExpandingCardsItem({ title, titleRender, text, action, src, alt, imageRender, surface, render, ref, className, ...rest }: ExpandingCardsItemProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
69
+ export {};
@@ -0,0 +1,48 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ import { ReactNode, Ref } from 'react';
3
+ export type ExpandingCardsDefaultOpen = "first" | "last";
4
+ export type ExpandingCardsProps = Omit<useRender.ComponentProps<"div">, "ref" | "children"> & {
5
+ /** The rendered element: the `<div>`, or the element passed to `render`. */
6
+ ref?: Ref<HTMLElement>;
7
+ /**
8
+ * The cards: `ExpandingCardsItem`s, usually three. Each one is put in an
9
+ * item of a list.
10
+ */
11
+ children: ReactNode;
12
+ /**
13
+ * The card that is open before the visitor points at one: the website's
14
+ * "Main card".
15
+ * @default "first"
16
+ */
17
+ defaultOpen?: ExpandingCardsDefaultOpen;
18
+ };
19
+ /**
20
+ * A row of photo cards in which one is open, as on the home page of
21
+ * leabank.no: the open card is twice as wide as the others, with its title,
22
+ * text and call to action beside its photo; the others show the photo and
23
+ * the arrow.
24
+ *
25
+ * ```tsx
26
+ * <Section>
27
+ * <ExpandingCards>
28
+ * <ExpandingCardsItem
29
+ * surface="contrast"
30
+ * title="Forbrukslån"
31
+ * text="Lån til det du trenger, uten sikkerhet."
32
+ * src="/bilder/forbrukslan.jpg"
33
+ * alt=""
34
+ * action={<ActionButton render={<NextLink href="/lan/forbrukslan" />}>Søk nå</ActionButton>}
35
+ * />
36
+ * …
37
+ * </ExpandingCards>
38
+ * </Section>
39
+ * ```
40
+ *
41
+ * From 1312px the cards share a row, 16px apart, and the card the pointer
42
+ * or the keyboard focus moves into opens; the last one opened stays open.
43
+ * The row keeps its height while a card opens, so the page under it does
44
+ * not move. Below 1312px every card is open, one under the other, and below
45
+ * 640px the photo sits on top of the text. The cards are a list. Under
46
+ * reduced motion they open without moving.
47
+ */
48
+ export declare function ExpandingCards({ defaultOpen, render, ref, className, children, ...rest }: ExpandingCardsProps): import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
@@ -0,0 +1,7 @@
1
+ import { ComponentProps } from 'react';
2
+ type FlagProps = Omit<ComponentProps<"svg">, "children">;
3
+ export declare function FlagNorway(props: FlagProps): import("react").JSX.Element;
4
+ export declare function FlagSweden(props: FlagProps): import("react").JSX.Element;
5
+ export declare function FlagFinland(props: FlagProps): import("react").JSX.Element;
6
+ export declare function FlagSpain(props: FlagProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,52 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ import { ReactElement, ReactNode, Ref } from 'react';
3
+ export type HeroServiceGridImagePosition = "start" | "end";
4
+ export type HeroServiceGridProps = Omit<useRender.ComponentProps<"div">, "ref" | "children"> & {
5
+ /** The rendered element: the `<div>`, or the element passed to `render`. */
6
+ ref?: Ref<HTMLElement>;
7
+ /** The large photo. */
8
+ src: string;
9
+ /** What the photo shows, for screen readers; `""` when it is decoration. */
10
+ alt: string;
11
+ /**
12
+ * The image element to render instead of the plain `<img>`, as on
13
+ * `FeaturedImage`: `next/image` with `fill`, or an `<img loading="lazy">`.
14
+ */
15
+ imageRender?: ReactElement;
16
+ /** A call to action on the photo: an `ActionButton`. */
17
+ action?: ReactNode;
18
+ /**
19
+ * Where the photo sits from 1024px: `"start"` (on the left) or `"end"`.
20
+ * Below 1024px it is always on top.
21
+ * @default "start"
22
+ */
23
+ imagePosition?: HeroServiceGridImagePosition;
24
+ /**
25
+ * The cards beside the photo: up to four `LinkCard`s, two by two. Each one
26
+ * is put in an item of a list.
27
+ */
28
+ children?: ReactNode;
29
+ };
30
+ /**
31
+ * A large photo beside a block of link cards, as on leabank.no's home page:
32
+ * a `FeaturedImage` with a call to action, and up to four `LinkCard`s.
33
+ *
34
+ * ```tsx
35
+ * <Section>
36
+ * <HeroServiceGrid
37
+ * src="/bilder/familie.jpg"
38
+ * alt=""
39
+ * action={<ActionButton render={<NextLink href="/lan" />}>Se våre lån</ActionButton>}
40
+ * >
41
+ * <LinkCard render={<NextLink href="/lan" />} title="Lån etter dine behov." surface="contrast" />
42
+ * <LinkCard render={<NextLink href="/sparing" />} title="Se hvor mye du kan spare." surface="muted" />
43
+ * </HeroServiceGrid>
44
+ * </Section>
45
+ * ```
46
+ *
47
+ * From 1024px two equal columns 16px apart, at least 600px tall: the photo
48
+ * fills one, the cards share the other two by two. Below 1024px the photo is
49
+ * on top at 1 : 0.7, the cards two by two under it, and one under the other
50
+ * below 768px. The cards are a list.
51
+ */
52
+ export declare function HeroServiceGrid({ src, alt, imageRender, action, imagePosition, render, ref, className, children, ...rest }: HeroServiceGridProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
@@ -0,0 +1,57 @@
1
+ import { useRender } from '@base-ui/react/use-render';
2
+ import { ReactElement, ReactNode, Ref } from 'react';
3
+ export type HeroProps = Omit<useRender.ComponentProps<"section">, "ref" | "title" | "children"> & {
4
+ /** The rendered element: the `<section>`, or the element passed to `render`. */
5
+ ref?: Ref<HTMLElement>;
6
+ /** The photo behind the band, cropped to fill it. */
7
+ src: string;
8
+ /**
9
+ * What the photo shows, for screen readers; `""` when it is decoration,
10
+ * as a photo behind a title usually is.
11
+ */
12
+ alt: string;
13
+ /**
14
+ * The image element to render instead of the plain `<img>`, such as
15
+ * `next/image` with `fill` and `priority` (the hero photo is usually the
16
+ * largest thing on the page). Its own props win over `src` and `alt`.
17
+ */
18
+ imageRender?: ReactElement;
19
+ /** The title of the page. */
20
+ title: ReactNode;
21
+ /**
22
+ * The element for the title, an `<h1>` by default, as a hero opens the
23
+ * page: `titleRender={<h2 />}` where it does not.
24
+ */
25
+ titleRender?: ReactElement;
26
+ /**
27
+ * The text under the title. A string becomes one paragraph; pass `<p>`
28
+ * elements for several.
29
+ */
30
+ text?: ReactNode;
31
+ /** The call to action under the text: an `ActionButton`. */
32
+ action?: ReactNode;
33
+ /** The price example under the action, in the small print. */
34
+ priceExample?: ReactNode;
35
+ };
36
+ /**
37
+ * The top of a product page: a photo from edge to edge, and on it a white
38
+ * `Panel` with the page title, a text, a call to action and the price
39
+ * example, as on leabank.no's loan pages.
40
+ *
41
+ * ```tsx
42
+ * <Hero
43
+ * src="/bilder/kjokken.jpg"
44
+ * alt=""
45
+ * imageRender={<NextImage src={kitchen} alt="" fill priority />}
46
+ * title="Forbrukslån med rente fra 7,90 %"
47
+ * text="Søk om lån uten sikkerhet på få minutter og få svar med én gang."
48
+ * action={<ActionButton render={<NextLink href="/sok" />}>Søk om lån</ActionButton>}
49
+ * />
50
+ * ```
51
+ *
52
+ * It is a band of its own, not inside a `Section`: at least 700px tall
53
+ * (600px below 768px, 500px below 640px), with the panel at most 600px wide
54
+ * at the start of the 1312px column. In the reading order the panel comes
55
+ * first and the photo after it.
56
+ */
57
+ export declare function Hero({ src, alt, imageRender, title, titleRender, text, action, priceExample, render, ref, className, ...rest }: HeroProps): ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The `@leabankab/component-library/website` entry: the sections that
3
+ * leabank.no is built from. They are website-only, so they are not part of
4
+ * the main entry, and an app ships them, and their stylesheet, only where it
5
+ * imports them. The build writes their CSS Modules to dist/website.css,
6
+ * which the entry imports itself.
7
+ *
8
+ * The primitives and cards the sections hold (`Panel`, `FeaturedImage`,
9
+ * `MediaCard` and the rest) stay in the main entry. Import what this folder
10
+ * shares with the main entry from "../index" (see vite.website.config.ts and
11
+ * tests/entries.test.tsx).
12
+ *
13
+ * Names are flat (`SectionHeader`, not `Section.Header`): the website renders
14
+ * these from server components, which can't dot into a client bundle.
15
+ */
16
+ export * from './alert-banner';
17
+ export * from './brand-letters';
18
+ export * from './calculator';
19
+ export * from './carousel';
20
+ export * from './cta-banner';
21
+ export * from './expanding-cards';
22
+ export * from './expanding-cards-item';
23
+ export * from './hero';
24
+ export * from './hero-service-grid';
25
+ export * from './navigation-grid';
26
+ export * from './partner-list';
27
+ export * from './payment-feature';
28
+ export * from './promo-grid';
29
+ export * from './section';
30
+ export * from './section-header';
31
+ export * from './service-card-grid';
32
+ export * from './side-nav';
33
+ export * from './site-footer';
34
+ export * from './site-header';
35
+ export * from './split-content';
36
+ export * from './stats';
37
+ export * from './testimonials';
@@ -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;