@elmeragroup/fuse 0.1.0-canary.113 → 0.1.0-canary.115
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/README.md +2 -0
- package/components/card/card-section-button.d.ts +23 -0
- package/components/card/card-section-button.d.ts.map +1 -0
- package/components/card/card-section-button.js +35 -0
- package/components/card/card-section-button.js.map +1 -0
- package/components/card/card-variants.d.ts +47 -0
- package/components/card/card-variants.d.ts.map +1 -1
- package/components/card/card-variants.js +33 -3
- package/components/card/card-variants.js.map +1 -1
- package/components/card/card.d.ts +25 -0
- package/components/card/card.d.ts.map +1 -1
- package/components/card/card.js +43 -2
- package/components/card/card.js.map +1 -1
- package/components/description-list/description-list.d.ts +14 -2
- package/components/description-list/description-list.d.ts.map +1 -1
- package/components/description-list/description-list.js +14 -4
- package/components/description-list/description-list.js.map +1 -1
- package/package.json +2 -2
- package/styles/fuse.css +1 -0
- package/styles/inner-corner/card.d.ts +14 -1
- package/styles/inner-corner/card.d.ts.map +1 -1
- package/styles/inner-corner/card.js +16 -3
- package/styles/inner-corner/card.js.map +1 -1
- package/styles.css +94 -0
- package/themes.css +18 -0
package/README.md
CHANGED
|
@@ -66,6 +66,8 @@ A `Card` and a `card` Accordion item draw their edge in `--card-border`. Without
|
|
|
66
66
|
}
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
The line between a card's stacked `Card.Section` and `Card.SectionButton` parts is `--card-section-divider`. Without it, it takes your `--border`. External themes draw it in the page tint, `var(--background)`.
|
|
70
|
+
|
|
69
71
|
A `RadioItem` or `CheckboxItem` row draws its edge in `--selection-border`, and a checked row in `--selection-checked-border`. The line between stacked rows reads `--selection-divider`, and above and below a checked row `--selection-checked-divider`. Without them the row and its dividers take your `--border` and a checked row your `--primary`, as internal themes do. For the external themes' look, where stacked rows keep a grey separator but no outer edge and the control alone shows the selection, set the edge to a transparent colour, point the checked edge at it, and draw both dividers in `--border`. The border keeps its 1px width, so rows join and inset as before, but a row on a `--card`-coloured surface has no outline:
|
|
70
72
|
|
|
71
73
|
```css
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
3
|
+
//#region src/components/card/card-section-button.d.ts
|
|
4
|
+
export type CardSectionButtonProps = useRender.ComponentProps<"button">;
|
|
5
|
+
/**
|
|
6
|
+
* A whole stacked section of a vertical card as one button, such as "No thanks, continue
|
|
7
|
+
* without" with a trailing caret. It stacks, divides and rounds like a `Card.Section`, and adds
|
|
8
|
+
* a hover fill, a pointer cursor, the state face and a focus ring drawn inside its own edges, so
|
|
9
|
+
* the sections around it cannot cover it. It renders `<button type="button">`, the type
|
|
10
|
+
* `useRender` gives its default button, so it never submits a form it sits in.
|
|
11
|
+
*
|
|
12
|
+
* `render={<a href="/terms" />}` makes it a link, which keeps its link semantics and takes no
|
|
13
|
+
* `type`. A trigger composes it as it composes `Button`:
|
|
14
|
+
* `<Dialog.Trigger render={<Card.SectionButton />}>Change plan</Dialog.Trigger>`. Hold phrasing
|
|
15
|
+
* content only, such as text, an icon and a `Card.SectionMedia`, and no other control. Client
|
|
16
|
+
* only because polymorphism is `useRender`; the rest of the Card compound stays server.
|
|
17
|
+
*/
|
|
18
|
+
export declare function CardSectionButton({ className, render, ...props }: CardSectionButtonProps): ReactElement;
|
|
19
|
+
export declare namespace CardSectionButton {
|
|
20
|
+
var displayName: string;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//# sourceMappingURL=card-section-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card-section-button.d.ts","names":[],"sources":["../../../src/components/card/card-section-button.tsx"],"mappings":";;;YAWY,yBAAyB,UAAU;;;;;;;;;;;;;;wBAe/B,oBAAoB,WAAW,WAAW,SAAS,yBAAyB;yBAA5E;MAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../styles/cn.js";
|
|
3
|
+
import { definedProps } from "../../internal/defined-props.js";
|
|
4
|
+
import { cardSectionVariants } from "./card-variants.js";
|
|
5
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
6
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
7
|
+
//#region src/components/card/card-section-button.tsx
|
|
8
|
+
/**
|
|
9
|
+
* A whole stacked section of a vertical card as one button, such as "No thanks, continue
|
|
10
|
+
* without" with a trailing caret. It stacks, divides and rounds like a `Card.Section`, and adds
|
|
11
|
+
* a hover fill, a pointer cursor, the state face and a focus ring drawn inside its own edges, so
|
|
12
|
+
* the sections around it cannot cover it. It renders `<button type="button">`, the type
|
|
13
|
+
* `useRender` gives its default button, so it never submits a form it sits in.
|
|
14
|
+
*
|
|
15
|
+
* `render={<a href="/terms" />}` makes it a link, which keeps its link semantics and takes no
|
|
16
|
+
* `type`. A trigger composes it as it composes `Button`:
|
|
17
|
+
* `<Dialog.Trigger render={<Card.SectionButton />}>Change plan</Dialog.Trigger>`. Hold phrasing
|
|
18
|
+
* content only, such as text, an icon and a `Card.SectionMedia`, and no other control. Client
|
|
19
|
+
* only because polymorphism is `useRender`; the rest of the Card compound stays server.
|
|
20
|
+
*/
|
|
21
|
+
function CardSectionButton({ className, render, ...props }) {
|
|
22
|
+
return useRender({
|
|
23
|
+
defaultTagName: "button",
|
|
24
|
+
props: {
|
|
25
|
+
"data-slot": "card-section-button",
|
|
26
|
+
...mergeProps({ className: cn(cardSectionVariants().button(), className) }, definedProps(props))
|
|
27
|
+
},
|
|
28
|
+
render
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
CardSectionButton.displayName = "Card.SectionButton";
|
|
32
|
+
//#endregion
|
|
33
|
+
export { CardSectionButton };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=card-section-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card-section-button.js","names":[],"sources":["../../../src/components/card/card-section-button.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactElement } from \"react\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\n\nimport { definedProps } from \"../../internal/defined-props\";\nimport { cn } from \"../../styles/cn\";\nimport { cardSectionVariants } from \"./card-variants\";\n\nexport type CardSectionButtonProps = useRender.ComponentProps<\"button\">;\n\n/**\n * A whole stacked section of a vertical card as one button, such as \"No thanks, continue\n * without\" with a trailing caret. It stacks, divides and rounds like a `Card.Section`, and adds\n * a hover fill, a pointer cursor, the state face and a focus ring drawn inside its own edges, so\n * the sections around it cannot cover it. It renders `<button type=\"button\">`, the type\n * `useRender` gives its default button, so it never submits a form it sits in.\n *\n * `render={<a href=\"/terms\" />}` makes it a link, which keeps its link semantics and takes no\n * `type`. A trigger composes it as it composes `Button`:\n * `<Dialog.Trigger render={<Card.SectionButton />}>Change plan</Dialog.Trigger>`. Hold phrasing\n * content only, such as text, an icon and a `Card.SectionMedia`, and no other control. Client\n * only because polymorphism is `useRender`; the rest of the Card compound stays server.\n */\nexport function CardSectionButton({ className, render, ...props }: CardSectionButtonProps): ReactElement {\n return useRender({\n defaultTagName: \"button\",\n props: {\n \"data-slot\": \"card-section-button\",\n // Filtered, as Button filters, so a forwarded `type={undefined}` cannot erase the default\n // button's `type=\"button\"`.\n ...mergeProps<\"button\">(\n { className: cn(cardSectionVariants().button(), className) },\n definedProps(props)\n ),\n },\n render,\n });\n}\n\nCardSectionButton.displayName = \"Card.SectionButton\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,kBAAkB,EAAE,WAAW,QAAQ,GAAG,SAA+C;CACvG,OAAO,UAAU;EACf,gBAAgB;EAChB,OAAO;GACL,aAAa;GAGb,GAAG,WACD,EAAE,WAAW,GAAG,oBAAoB,CAAC,CAAC,OAAO,GAAG,SAAS,EAAE,GAC3D,aAAa,KAAK,CACpB;EACF;EACA;CACF,CAAC;AACH;AAEA,kBAAkB,cAAc"}
|
|
@@ -112,6 +112,53 @@ export declare const cardVariants: import("tailwind-variants").TVReturnType<{
|
|
|
112
112
|
cardContent: string;
|
|
113
113
|
cardFooter: string;
|
|
114
114
|
}>>;
|
|
115
|
+
/**
|
|
116
|
+
* Module-private recipe for the stacked section parts, kept off the public `cardVariants`.
|
|
117
|
+
* `section` is the static `Card.Section` and `button` the interactive `Card.SectionButton`; both
|
|
118
|
+
* take the stacked shell, and a `Card.SectionMedia` child makes either a two-column grid.
|
|
119
|
+
* Fuse ships no preflight, so `button` resets a native button's face, font and alignment itself.
|
|
120
|
+
* The typed `*-[…:inherit]` font utilities, as on Button's `icon-inline`, let tailwind-merge
|
|
121
|
+
* replace them with a consumer's `text-*`, `font-*` or `leading-*` class. The button takes Item's
|
|
122
|
+
* anchor hover fill, a pointer cursor, the state face and the self focus ring drawn inset, which
|
|
123
|
+
* the sections around it cannot paint over.
|
|
124
|
+
*/
|
|
125
|
+
export declare const cardSectionVariants: import("tailwind-variants").TVReturnType<{
|
|
126
|
+
[key: string]: {
|
|
127
|
+
[key: string]: {
|
|
128
|
+
button?: import("tailwind-variants").ClassValue;
|
|
129
|
+
media?: import("tailwind-variants").ClassValue;
|
|
130
|
+
section?: import("tailwind-variants").ClassValue;
|
|
131
|
+
} | import("tailwind-variants").ClassValue;
|
|
132
|
+
};
|
|
133
|
+
} | {
|
|
134
|
+
[x: string]: {
|
|
135
|
+
[x: string]: {
|
|
136
|
+
button?: import("tailwind-variants").ClassValue;
|
|
137
|
+
media?: import("tailwind-variants").ClassValue;
|
|
138
|
+
section?: import("tailwind-variants").ClassValue;
|
|
139
|
+
} | import("tailwind-variants").ClassValue;
|
|
140
|
+
};
|
|
141
|
+
} | {}, {
|
|
142
|
+
section: string[];
|
|
143
|
+
button: string[];
|
|
144
|
+
media: string;
|
|
145
|
+
}, undefined, {
|
|
146
|
+
[key: string]: {
|
|
147
|
+
[key: string]: {
|
|
148
|
+
button?: import("tailwind-variants").ClassValue;
|
|
149
|
+
media?: import("tailwind-variants").ClassValue;
|
|
150
|
+
section?: import("tailwind-variants").ClassValue;
|
|
151
|
+
} | import("tailwind-variants").ClassValue;
|
|
152
|
+
};
|
|
153
|
+
} | {}, {
|
|
154
|
+
section: string[];
|
|
155
|
+
button: string[];
|
|
156
|
+
media: string;
|
|
157
|
+
}, import("tailwind-variants").TVReturnTypeLike<unknown, {
|
|
158
|
+
section: string[];
|
|
159
|
+
button: string[];
|
|
160
|
+
media: string;
|
|
161
|
+
}>>;
|
|
115
162
|
/**
|
|
116
163
|
* Module-private type-scale recipes for `Card.Title` / `Card.Description`.
|
|
117
164
|
* Not exported from `@elmeragroup/fuse/card` — there is no borrow
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card-variants.d.ts","names":[],"sources":["../../../src/components/card/card-variants.ts"],"mappings":";;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"card-variants.d.ts","names":[],"sources":["../../../src/components/card/card-variants.ts"],"mappings":";;;;;;;;;;;;;;;;;qBA6Ba,0CAAY;;IAcnB;MACE;MAGA;MACA;;IAEF;MACE;MAIA;MACA;MACA;MACA;;;;IAIF;MAAW;;IACX;MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAwBC,iDAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA0BnB,+CAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAmBjB,qDAAuB"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { cn } from "../../styles/cn.js";
|
|
1
2
|
import { tv } from "../../styles/tv.js";
|
|
2
|
-
import {
|
|
3
|
+
import { selfFocusRingClass } from "../../styles/utils.js";
|
|
4
|
+
import { nativeStateFaceClass } from "../../styles/state-face.js";
|
|
5
|
+
import { cardDefaultTierClass, cardHorizontalShellClass, cardLargeTierClass, cardSectionShellClass, cardShellClass, cardStackedSectionShellClass } from "../../styles/inner-corner/card.js";
|
|
3
6
|
//#region src/components/card/card-variants.ts
|
|
4
7
|
/**
|
|
5
8
|
* PUBLIC slot recipe. `text-field`'s `card` variant and
|
|
@@ -32,7 +35,11 @@ const cardVariants = tv({
|
|
|
32
35
|
direction: {
|
|
33
36
|
vertical: {
|
|
34
37
|
cardHeader: cardSectionShellClass,
|
|
35
|
-
cardContent: [
|
|
38
|
+
cardContent: [
|
|
39
|
+
cardSectionShellClass,
|
|
40
|
+
"not-first:pt-0",
|
|
41
|
+
"[:where([data-slot=card-section])>&]:p-0"
|
|
42
|
+
],
|
|
36
43
|
cardFooter: [cardSectionShellClass, "not-first:pt-0"]
|
|
37
44
|
},
|
|
38
45
|
horizontal: {
|
|
@@ -53,6 +60,29 @@ const cardVariants = tv({
|
|
|
53
60
|
size: "default"
|
|
54
61
|
}
|
|
55
62
|
});
|
|
63
|
+
const sectionMediaGridClass = cn("has-[>[data-slot=card-section-media]]:grid has-[>[data-slot=card-section-media]]:grid-cols-[auto_minmax(0,1fr)] has-[>[data-slot=card-section-media]]:items-center has-[>[data-slot=card-section-media]]:gap-x-(--surface-gap-md)");
|
|
64
|
+
/**
|
|
65
|
+
* Module-private recipe for the stacked section parts, kept off the public `cardVariants`.
|
|
66
|
+
* `section` is the static `Card.Section` and `button` the interactive `Card.SectionButton`; both
|
|
67
|
+
* take the stacked shell, and a `Card.SectionMedia` child makes either a two-column grid.
|
|
68
|
+
* Fuse ships no preflight, so `button` resets a native button's face, font and alignment itself.
|
|
69
|
+
* The typed `*-[…:inherit]` font utilities, as on Button's `icon-inline`, let tailwind-merge
|
|
70
|
+
* replace them with a consumer's `text-*`, `font-*` or `leading-*` class. The button takes Item's
|
|
71
|
+
* anchor hover fill, a pointer cursor, the state face and the self focus ring drawn inset, which
|
|
72
|
+
* the sections around it cannot paint over.
|
|
73
|
+
*/
|
|
74
|
+
const cardSectionVariants = tv({ slots: {
|
|
75
|
+
section: [cardStackedSectionShellClass, sectionMediaGridClass],
|
|
76
|
+
button: [
|
|
77
|
+
cardStackedSectionShellClass,
|
|
78
|
+
sectionMediaGridClass,
|
|
79
|
+
"box-border block w-full cursor-pointer bg-transparent text-start text-inherit no-underline transition-colors duration-100 enabled-hover:bg-muted",
|
|
80
|
+
"font-[family-name:inherit] text-[length:inherit] leading-[inherit] font-[weight:inherit]",
|
|
81
|
+
cn(selfFocusRingClass, "focus-visible:ring-inset"),
|
|
82
|
+
nativeStateFaceClass
|
|
83
|
+
],
|
|
84
|
+
media: "flex shrink-0 items-center justify-center [&>svg]:size-5 [&[hidden]:not([hidden=until-found])]:hidden"
|
|
85
|
+
} });
|
|
56
86
|
/**
|
|
57
87
|
* Module-private type-scale recipes for `Card.Title` / `Card.Description`.
|
|
58
88
|
* Not exported from `@elmeragroup/fuse/card` — there is no borrow
|
|
@@ -87,6 +117,6 @@ const cardDescriptionVariants = tv({
|
|
|
87
117
|
defaultVariants: { size: "sm" }
|
|
88
118
|
});
|
|
89
119
|
//#endregion
|
|
90
|
-
export { cardDescriptionVariants, cardTitleVariants, cardVariants };
|
|
120
|
+
export { cardDescriptionVariants, cardSectionVariants, cardTitleVariants, cardVariants };
|
|
91
121
|
|
|
92
122
|
//# sourceMappingURL=card-variants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card-variants.js","names":[],"sources":["../../../src/components/card/card-variants.ts"],"sourcesContent":["import {\n cardDefaultTierClass,\n cardHorizontalShellClass,\n cardLargeTierClass,\n cardSectionShellClass,\n cardShellClass,\n} from \"../../styles/inner-corner/card\";\nimport { tv } from \"../../styles/tv\";\n\n/**\n * PUBLIC slot recipe. `text-field`'s `card` variant and\n * `CheckboxCard` compose it, so it ships from `@elmeragroup/fuse/card`.\n * The base draws its edge in `--card-border`, which external themes make transparent; both\n * composers pin `border-border` over it, since a field box and a control keep a visible edge.\n * Horizontal cards keep their header text in a grid and wrap whole sections when\n * the container cannot fit them side by side.\n * The external ref's surface/padding axes are decomposed away into `direction` and `size`.\n * `size` sets the card's surface tier on the base as `--card-pad`: the medium tier,\n * `--surface-pad-md`, by default and the large tier, `--surface-pad-lg`, at `lg`. Sections pad\n * with it, and a content or footer below another section drops its top padding, so the tier is\n * also the gap between sections. A content or footer that opens the card keeps it. A horizontal\n * card pads and gaps its sections with the same tier.\n * The title is `leading-snug` in both directions, as `Heading` and `Item.Title` are, so a title\n * that wraps keeps space between its lines.\n */\nexport const cardVariants = tv({\n slots: {\n base: [cardShellClass, \"shadow-xs flex flex-col border-card-border bg-card text-card-foreground\"],\n cardHeader:\n \"@container/card-header grid auto-rows-min items-start gap-1.5 has-data-[slot=card-action]:grid-cols-[1fr_auto]\",\n cardTag: \"text-sm font-semibold text-muted-foreground\",\n cardTitle: \"font-semibold leading-snug\",\n cardDescription: \"text-muted-foreground\",\n cardAction: \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n cardContent: \"\",\n cardFooter: \"flex items-center\",\n },\n variants: {\n direction: {\n vertical: {\n cardHeader: cardSectionShellClass,\n cardContent: [cardSectionShellClass, \"not-first:pt-0\"],\n cardFooter: [cardSectionShellClass, \"not-first:pt-0\"],\n },\n horizontal: {\n base: [\n cardHorizontalShellClass,\n \"flex-row flex-wrap items-start gap-[var(--card-pad,var(--surface-pad-md))]\",\n ],\n cardHeader: \"min-w-0 flex-[2_1_16rem] wrap-anywhere\",\n cardContent: \"min-w-0 flex-[1_1_12rem] wrap-anywhere\",\n cardFooter: \"min-w-0 flex-[1_1_8rem] wrap-anywhere\",\n cardTitle: \"text-xl/snug\",\n },\n },\n size: {\n default: { base: cardDefaultTierClass },\n lg: { base: cardLargeTierClass },\n },\n },\n defaultVariants: {\n direction: \"vertical\",\n size: \"default\",\n },\n});\n\n/**\n * Module-private type-scale recipes for `Card.Title` / `Card.Description`.\n * Not exported from `@elmeragroup/fuse/card` — there is no borrow\n * pattern. Kept off `cardVariants` because `direction=\"horizontal\"` already\n * sets `cardTitle: \"text-xl/snug\"`; a second `size` axis on that slot would fight\n * through twMerge. `size` is a type-scale axis, not a density control-box rung:\n * it does not read `--control-*`.\n */\nexport const cardTitleVariants = tv({\n variants: {\n size: {\n default: \"text-base\",\n sm: \"text-sm\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n \"2xl\": \"text-2xl\",\n \"3xl\": \"text-3xl\",\n \"4xl\": \"text-4xl\",\n \"5xl\": \"text-5xl\",\n \"6xl\": \"text-6xl\",\n },\n },\n defaultVariants: {\n size: \"2xl\",\n },\n});\n\nexport const cardDescriptionVariants = tv({\n variants: {\n size: {\n xs: \"text-xs\",\n sm: \"text-sm\",\n default: \"text-base\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n \"2xl\": \"text-2xl\",\n },\n },\n defaultVariants: {\n size: \"sm\",\n },\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"card-variants.js","names":[],"sources":["../../../src/components/card/card-variants.ts"],"sourcesContent":["import { cn } from \"../../styles/cn\";\nimport {\n cardDefaultTierClass,\n cardHorizontalShellClass,\n cardLargeTierClass,\n cardSectionShellClass,\n cardShellClass,\n cardStackedSectionShellClass,\n} from \"../../styles/inner-corner/card\";\nimport { nativeStateFaceClass } from \"../../styles/state-face\";\nimport { tv } from \"../../styles/tv\";\nimport { selfFocusRingClass } from \"../../styles/utils\";\n\n/**\n * PUBLIC slot recipe. `text-field`'s `card` variant and\n * `CheckboxCard` compose it, so it ships from `@elmeragroup/fuse/card`.\n * The base draws its edge in `--card-border`, which external themes make transparent; both\n * composers pin `border-border` over it, since a field box and a control keep a visible edge.\n * Horizontal cards keep their header text in a grid and wrap whole sections when\n * the container cannot fit them side by side.\n * The external ref's surface/padding axes are decomposed away into `direction` and `size`.\n * `size` sets the card's surface tier on the base as `--card-pad`: the medium tier,\n * `--surface-pad-md`, by default and the large tier, `--surface-pad-lg`, at `lg`. Sections pad\n * with it, and a content or footer below another section drops its top padding, so the tier is\n * also the gap between sections. A content or footer that opens the card keeps it. A horizontal\n * card pads and gaps its sections with the same tier.\n * The title is `leading-snug` in both directions, as `Heading` and `Item.Title` are, so a title\n * that wraps keeps space between its lines.\n */\nexport const cardVariants = tv({\n slots: {\n base: [cardShellClass, \"shadow-xs flex flex-col border-card-border bg-card text-card-foreground\"],\n cardHeader:\n \"@container/card-header grid auto-rows-min items-start gap-1.5 has-data-[slot=card-action]:grid-cols-[1fr_auto]\",\n cardTag: \"text-sm font-semibold text-muted-foreground\",\n cardTitle: \"font-semibold leading-snug\",\n cardDescription: \"text-muted-foreground\",\n cardAction: \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n cardContent: \"\",\n cardFooter: \"flex items-center\",\n },\n variants: {\n direction: {\n vertical: {\n cardHeader: cardSectionShellClass,\n // Inside a `Card.Section` the content is the section's column and the section pads, so\n // the content drops its own tier there.\n cardContent: [cardSectionShellClass, \"not-first:pt-0\", \"[:where([data-slot=card-section])>&]:p-0\"],\n cardFooter: [cardSectionShellClass, \"not-first:pt-0\"],\n },\n horizontal: {\n base: [\n cardHorizontalShellClass,\n \"flex-row flex-wrap items-start gap-[var(--card-pad,var(--surface-pad-md))]\",\n ],\n cardHeader: \"min-w-0 flex-[2_1_16rem] wrap-anywhere\",\n cardContent: \"min-w-0 flex-[1_1_12rem] wrap-anywhere\",\n cardFooter: \"min-w-0 flex-[1_1_8rem] wrap-anywhere\",\n cardTitle: \"text-xl/snug\",\n },\n },\n size: {\n default: { base: cardDefaultTierClass },\n lg: { base: cardLargeTierClass },\n },\n },\n defaultVariants: {\n direction: \"vertical\",\n size: \"default\",\n },\n});\n\n// A `Card.SectionMedia` child makes a section a two-column grid, the media centred beside the content.\nconst sectionMediaGridClass = cn(\n \"has-[>[data-slot=card-section-media]]:grid has-[>[data-slot=card-section-media]]:grid-cols-[auto_minmax(0,1fr)] has-[>[data-slot=card-section-media]]:items-center has-[>[data-slot=card-section-media]]:gap-x-(--surface-gap-md)\"\n);\n\n/**\n * Module-private recipe for the stacked section parts, kept off the public `cardVariants`.\n * `section` is the static `Card.Section` and `button` the interactive `Card.SectionButton`; both\n * take the stacked shell, and a `Card.SectionMedia` child makes either a two-column grid.\n * Fuse ships no preflight, so `button` resets a native button's face, font and alignment itself.\n * The typed `*-[…:inherit]` font utilities, as on Button's `icon-inline`, let tailwind-merge\n * replace them with a consumer's `text-*`, `font-*` or `leading-*` class. The button takes Item's\n * anchor hover fill, a pointer cursor, the state face and the self focus ring drawn inset, which\n * the sections around it cannot paint over.\n */\nexport const cardSectionVariants = tv({\n slots: {\n section: [cardStackedSectionShellClass, sectionMediaGridClass],\n button: [\n cardStackedSectionShellClass,\n sectionMediaGridClass,\n \"box-border block w-full cursor-pointer bg-transparent text-start text-inherit no-underline transition-colors duration-100 enabled-hover:bg-muted\",\n \"font-[family-name:inherit] text-[length:inherit] leading-[inherit] font-[weight:inherit]\",\n // oxlint-disable-next-line elmera/no-local-focus-ring -- the shared self ring, drawn inset\n cn(selfFocusRingClass, \"focus-visible:ring-inset\"),\n nativeStateFaceClass,\n ],\n // Without preflight the media's own `flex` beats the user-agent `[hidden]` rule.\n media:\n \"flex shrink-0 items-center justify-center [&>svg]:size-5 [&[hidden]:not([hidden=until-found])]:hidden\",\n },\n});\n\n/**\n * Module-private type-scale recipes for `Card.Title` / `Card.Description`.\n * Not exported from `@elmeragroup/fuse/card` — there is no borrow\n * pattern. Kept off `cardVariants` because `direction=\"horizontal\"` already\n * sets `cardTitle: \"text-xl/snug\"`; a second `size` axis on that slot would fight\n * through twMerge. `size` is a type-scale axis, not a density control-box rung:\n * it does not read `--control-*`.\n */\nexport const cardTitleVariants = tv({\n variants: {\n size: {\n default: \"text-base\",\n sm: \"text-sm\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n \"2xl\": \"text-2xl\",\n \"3xl\": \"text-3xl\",\n \"4xl\": \"text-4xl\",\n \"5xl\": \"text-5xl\",\n \"6xl\": \"text-6xl\",\n },\n },\n defaultVariants: {\n size: \"2xl\",\n },\n});\n\nexport const cardDescriptionVariants = tv({\n variants: {\n size: {\n xs: \"text-xs\",\n sm: \"text-sm\",\n default: \"text-base\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n \"2xl\": \"text-2xl\",\n },\n },\n defaultVariants: {\n size: \"sm\",\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,eAAe,GAAG;CAC7B,OAAO;EACL,MAAM,CAAC,gBAAgB,yEAAyE;EAChG,YACE;EACF,SAAS;EACT,WAAW;EACX,iBAAiB;EACjB,YAAY;EACZ,aAAa;EACb,YAAY;CACd;CACA,UAAU;EACR,WAAW;GACT,UAAU;IACR,YAAY;IAGZ,aAAa;KAAC;KAAuB;KAAkB;IAA0C;IACjG,YAAY,CAAC,uBAAuB,gBAAgB;GACtD;GACA,YAAY;IACV,MAAM,CACJ,0BACA,4EACF;IACA,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,WAAW;GACb;EACF;EACA,MAAM;GACJ,SAAS,EAAE,MAAM,qBAAqB;GACtC,IAAI,EAAE,MAAM,mBAAmB;EACjC;CACF;CACA,iBAAiB;EACf,WAAW;EACX,MAAM;CACR;AACF,CAAC;AAGD,MAAM,wBAAwB,GAC5B,mOACF;;;;;;;;;;;AAYA,MAAa,sBAAsB,GAAG,EACpC,OAAO;CACL,SAAS,CAAC,8BAA8B,qBAAqB;CAC7D,QAAQ;EACN;EACA;EACA;EACA;EAEA,GAAG,oBAAoB,0BAA0B;EACjD;CACF;CAEA,OACE;AACJ,EACF,CAAC;;;;;;;;;AAUD,MAAa,oBAAoB,GAAG;CAClC,UAAU,EACR,MAAM;EACJ,SAAS;EACT,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;CACT,EACF;CACA,iBAAiB,EACf,MAAM,MACR;AACF,CAAC;AAED,MAAa,0BAA0B,GAAG;CACxC,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,SAAS;EACT,IAAI;EACJ,IAAI;EACJ,OAAO;CACT,EACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CardSectionButton } from "./card-section-button.js";
|
|
1
2
|
import { cardDescriptionVariants, cardTitleVariants, cardVariants } from "./card-variants.js";
|
|
2
3
|
import { HTMLAttributes, ReactElement, ReactNode } from "react";
|
|
3
4
|
import { VariantProps } from "tailwind-variants";
|
|
@@ -46,8 +47,29 @@ declare function CardTag({ className, direction, ...props }: CardDivProps): Reac
|
|
|
46
47
|
declare function CardTitle({ children, className, direction, level, size, icon, ...props }: CardTitleProps): ReactElement;
|
|
47
48
|
declare function CardDescription({ className, direction, size, ...props }: CardDescriptionProps): ReactElement;
|
|
48
49
|
declare function CardAction({ className, direction, ...props }: CardDivProps): ReactElement;
|
|
50
|
+
/**
|
|
51
|
+
* A card's body. Inside a `Card.Section` it is the section's content column, beside a
|
|
52
|
+
* `Card.SectionMedia`, and drops its own padding, since the section pads.
|
|
53
|
+
*/
|
|
49
54
|
declare function CardContent({ className, direction, ...props }: CardDivProps): ReactElement;
|
|
50
55
|
declare function CardFooter({ className, direction, ...props }: CardDivProps): ReactElement;
|
|
56
|
+
/**
|
|
57
|
+
* One of a vertical card's stacked sections of equal weight. Sections form the card's body under
|
|
58
|
+
* one optional `Card.Header`: a `Card.Content` or `Card.Footer` beside them takes no divider, so
|
|
59
|
+
* put that content in a section instead. A section pads every side with the card's tier, a 1px
|
|
60
|
+
* `--card-section-divider` line separates it from the part above, and the first and last
|
|
61
|
+
* sections round with the card's corners. A `Card.SectionMedia` as its first child makes it a
|
|
62
|
+
* two-column grid with the media centred beside a `Card.Content`, the unpadded content column.
|
|
63
|
+
* A horizontal card pads itself, so sections take no `direction` and belong in a vertical card.
|
|
64
|
+
* A whole section that acts is a `Card.SectionButton`.
|
|
65
|
+
*/
|
|
66
|
+
declare function CardSection({ className, ...props }: HTMLAttributes<HTMLDivElement>): ReactElement;
|
|
67
|
+
/**
|
|
68
|
+
* The icon column of a `Card.Section` or `Card.SectionButton`. The section becomes a two-column
|
|
69
|
+
* grid, this column and the content, with the icon centred on the section's height. An `svg` is
|
|
70
|
+
* sized to `5`. It is a `span`, so it is phrasing content inside a section button.
|
|
71
|
+
*/
|
|
72
|
+
declare function CardSectionMedia({ className, ...props }: HTMLAttributes<HTMLSpanElement>): ReactElement;
|
|
51
73
|
export declare const Card: {
|
|
52
74
|
Root: typeof CardRoot;
|
|
53
75
|
Header: typeof CardHeader;
|
|
@@ -57,6 +79,9 @@ export declare const Card: {
|
|
|
57
79
|
Action: typeof CardAction;
|
|
58
80
|
Content: typeof CardContent;
|
|
59
81
|
Footer: typeof CardFooter;
|
|
82
|
+
Section: typeof CardSection;
|
|
83
|
+
SectionButton: typeof CardSectionButton;
|
|
84
|
+
SectionMedia: typeof CardSectionMedia;
|
|
60
85
|
};
|
|
61
86
|
//#endregion
|
|
62
87
|
//# sourceMappingURL=card.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.d.ts","names":[],"sources":["../../../src/components/card/card.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"card.d.ts","names":[],"sources":["../../../src/components/card/card.tsx"],"mappings":";;;;;KAeK,mBAAmB,KAAK,oBAAoB;KAE5C,eAAe,eAAe,kBAAkB;KAEhD,gBAAgB;;;;;;;EAOnB,oBAAoB,aAAa,SAAS;;KAGvC;KAEA,iBAAiB,eAAe,sBACnC;;;;;EAKE,QAAQ;;EAER,OAAO,YAAY,oBAAoB;;;;;EAKvC,OAAO;;KAGN,uBAAuB,eAAe,wBACzC;;EAEE,OAAO,YAAY,oBAAoB;;;;;;;;;;iBAWlC,WAAW,WAAW,WAAW,SAAqB,SAAS,gBAAgB;iBAc/E,aAAa,WAAW,cAAc,SAAS,eAAe;iBAa9D,UAAU,WAAW,cAAc,SAAS,eAAe;iBAM3D,YACP,UACA,WACA,WACA,OACA,MACA,SACG,SACF,iBAAiB;iBAuBX,kBACP,WACA,WACA,SACG,SACF,uBAAuB;iBAYjB,aAAa,WAAW,cAAc,SAAS,eAAe;;;;;iBAU9D,cAAc,WAAW,cAAc,SAAS,eAAe;iBAa/D,aAAa,WAAW,cAAc,SAAS,eAAe;;;;;;;;;;;iBAuB9D,cAAc,cAAc,SAAS,eAAe,kBAAkB;;;;;;iBAWtE,mBAAmB,cAAc,SAAS,eAAe,mBAAmB;qBAiBxE;EACX,aAAI;EACJ,eAAM;EACN,YAAG;EACH,cAAK;EACL,oBAAW;EACX,eAAM;EACN,gBAAO;EACP,eAAM;EACN,gBAAO;EACP,sBAAa;EACb,qBAAY"}
|
package/components/card/card.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cn } from "../../styles/cn.js";
|
|
2
|
-
import { cardDescriptionVariants, cardTitleVariants, cardVariants } from "./card-variants.js";
|
|
2
|
+
import { cardDescriptionVariants, cardSectionVariants, cardTitleVariants, cardVariants } from "./card-variants.js";
|
|
3
|
+
import { CardSectionButton } from "./card-section-button.js";
|
|
3
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
5
|
//#region src/components/card/card.tsx
|
|
5
6
|
/**
|
|
@@ -66,6 +67,10 @@ function CardAction({ className, direction, ...props }) {
|
|
|
66
67
|
...props
|
|
67
68
|
});
|
|
68
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* A card's body. Inside a `Card.Section` it is the section's content column, beside a
|
|
72
|
+
* `Card.SectionMedia`, and drops its own padding, since the section pads.
|
|
73
|
+
*/
|
|
69
74
|
function CardContent({ className, direction, ...props }) {
|
|
70
75
|
const { cardContent } = cardVariants({ direction });
|
|
71
76
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -84,6 +89,37 @@ function CardFooter({ className, direction, ...props }) {
|
|
|
84
89
|
...props
|
|
85
90
|
});
|
|
86
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* One of a vertical card's stacked sections of equal weight. Sections form the card's body under
|
|
94
|
+
* one optional `Card.Header`: a `Card.Content` or `Card.Footer` beside them takes no divider, so
|
|
95
|
+
* put that content in a section instead. A section pads every side with the card's tier, a 1px
|
|
96
|
+
* `--card-section-divider` line separates it from the part above, and the first and last
|
|
97
|
+
* sections round with the card's corners. A `Card.SectionMedia` as its first child makes it a
|
|
98
|
+
* two-column grid with the media centred beside a `Card.Content`, the unpadded content column.
|
|
99
|
+
* A horizontal card pads itself, so sections take no `direction` and belong in a vertical card.
|
|
100
|
+
* A whole section that acts is a `Card.SectionButton`.
|
|
101
|
+
*/
|
|
102
|
+
function CardSection({ className, ...props }) {
|
|
103
|
+
const { section } = cardSectionVariants();
|
|
104
|
+
return /* @__PURE__ */ jsx("div", {
|
|
105
|
+
"data-slot": "card-section",
|
|
106
|
+
className: cn(section(), className),
|
|
107
|
+
...props
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The icon column of a `Card.Section` or `Card.SectionButton`. The section becomes a two-column
|
|
112
|
+
* grid, this column and the content, with the icon centred on the section's height. An `svg` is
|
|
113
|
+
* sized to `5`. It is a `span`, so it is phrasing content inside a section button.
|
|
114
|
+
*/
|
|
115
|
+
function CardSectionMedia({ className, ...props }) {
|
|
116
|
+
const { media } = cardSectionVariants();
|
|
117
|
+
return /* @__PURE__ */ jsx("span", {
|
|
118
|
+
"data-slot": "card-section-media",
|
|
119
|
+
className: cn(media(), className),
|
|
120
|
+
...props
|
|
121
|
+
});
|
|
122
|
+
}
|
|
87
123
|
CardRoot.displayName = "Card.Root";
|
|
88
124
|
CardHeader.displayName = "Card.Header";
|
|
89
125
|
CardTag.displayName = "Card.Tag";
|
|
@@ -92,6 +128,8 @@ CardDescription.displayName = "Card.Description";
|
|
|
92
128
|
CardAction.displayName = "Card.Action";
|
|
93
129
|
CardContent.displayName = "Card.Content";
|
|
94
130
|
CardFooter.displayName = "Card.Footer";
|
|
131
|
+
CardSection.displayName = "Card.Section";
|
|
132
|
+
CardSectionMedia.displayName = "Card.SectionMedia";
|
|
95
133
|
const Card = {
|
|
96
134
|
Root: CardRoot,
|
|
97
135
|
Header: CardHeader,
|
|
@@ -100,7 +138,10 @@ const Card = {
|
|
|
100
138
|
Description: CardDescription,
|
|
101
139
|
Action: CardAction,
|
|
102
140
|
Content: CardContent,
|
|
103
|
-
Footer: CardFooter
|
|
141
|
+
Footer: CardFooter,
|
|
142
|
+
Section: CardSection,
|
|
143
|
+
SectionButton: CardSectionButton,
|
|
144
|
+
SectionMedia: CardSectionMedia
|
|
104
145
|
};
|
|
105
146
|
//#endregion
|
|
106
147
|
export { Card };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","names":[],"sources":["../../../src/components/card/card.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactElement, ReactNode } from \"react\";\n\nimport type { VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../../styles/cn\";\nimport { cardDescriptionVariants, cardTitleVariants, cardVariants } from \"./card-variants\";\n\n// Every part takes `direction`; only the root takes the card's `size`, so the typography `size`\n// of `Card.Title` and `Card.Description` stays their own.\ntype CardVariantProps = Pick<VariantProps<typeof cardVariants>, \"direction\">;\n\ntype CardDivProps = HTMLAttributes<HTMLDivElement> & CardVariantProps;\n\ntype CardRootProps = CardDivProps & {\n /**\n * The card's surface tier, which pads its sections, gaps them and sets their inner corner.\n * `default` takes the medium tier, `--surface-pad-md`, which Items and Accordion items pad with\n * too, so the card's text starts on their edge. `lg` takes the large\n * tier, `--surface-pad-lg`, for a card that holds long prose or acts as a page's main panel.\n */\n size?: keyof typeof cardVariants.variants.size;\n};\n\ntype CardTitleLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\ntype CardTitleProps = HTMLAttributes<HTMLHeadingElement> &\n CardVariantProps & {\n /**\n * Heading element level — `1`–`6` picks the rendered `h1`–`h6`. Defaults to `3`, so\n * a card titles itself without assuming its place in the document outline.\n */\n level?: CardTitleLevel;\n /** Typography size for the title, mapped to a `text-{size}` class. Defaults to `2xl`. */\n size?: NonNullable<VariantProps<typeof cardTitleVariants>[\"size\"]>;\n /**\n * Rendered before `children` — the title becomes a flex row (`items-center gap-x-1.5`)\n * and any `svg` is sized to `5`.\n */\n icon?: ReactNode;\n };\n\ntype CardDescriptionProps = HTMLAttributes<HTMLParagraphElement> &\n CardVariantProps & {\n /** Typography size for the description, mapped to a `text-{size}` class. Defaults to `sm`. */\n size?: NonNullable<VariantProps<typeof cardDescriptionVariants>[\"size\"]>;\n };\n\n/**\n * The Card surface. It publishes `--inner-corner`, its corner less its border, and its header,\n * content and footer publish it less their padding too. The root and its sections write their\n * `direction` as `data-direction`: a vertical card pads its sections, a horizontal one pads itself.\n * The root writes its `size` as `data-size` and publishes its tier to the sections it holds.\n * Its 1px edge is the theme's `--card-border`: `--border` in internal themes and a zero-alpha\n * colour in external ones. A border colour class still wins.\n */\nfunction CardRoot({ className, direction, size = \"default\", ...props }: CardRootProps): ReactElement {\n const { base } = cardVariants({ direction, size });\n\n return (\n <div\n data-slot=\"card\"\n data-direction={direction ?? \"vertical\"}\n data-size={size}\n className={cn(base(), className)}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardHeader } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-header\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardHeader(), className)}\n {...props}\n />\n );\n}\n\nfunction CardTag({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardTag } = cardVariants({ direction });\n\n return <div data-slot=\"card-tag\" className={cn(cardTag(), className)} {...props} />;\n}\n\nfunction CardTitle({\n children,\n className,\n direction,\n level = 3,\n size = \"2xl\",\n icon,\n ...props\n}: CardTitleProps): ReactElement {\n const { cardTitle } = cardVariants({ direction });\n const Heading = `h${level}` as const;\n\n return (\n <Heading\n data-slot=\"card-title\"\n className={cn(\n cardTitleVariants({ size }),\n cardTitle({\n // `direction=\"horizontal\"` pins `text-xl/snug` here, so the size class must come first,\n // and the slot's leading must follow it: a font size drops a line height before it.\n className: icon ? \"flex items-center gap-x-1.5 [&>svg]:size-5\" : undefined,\n }),\n className\n )}\n {...props}>\n {icon ?? null}\n {children}\n </Heading>\n );\n}\n\nfunction CardDescription({\n className,\n direction,\n size = \"sm\",\n ...props\n}: CardDescriptionProps): ReactElement {\n const { cardDescription } = cardVariants({ direction });\n\n return (\n <p\n data-slot=\"card-description\"\n className={cn(cardDescriptionVariants({ size }), cardDescription(), className)}\n {...props}\n />\n );\n}\n\nfunction CardAction({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardAction } = cardVariants({ direction });\n\n return <div data-slot=\"card-action\" className={cn(cardAction(), className)} {...props} />;\n}\n\nfunction CardContent({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardContent } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-content\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardContent(), className)}\n {...props}\n />\n );\n}\n\nfunction CardFooter({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardFooter } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-footer\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardFooter(), className)}\n {...props}\n />\n );\n}\n\nCardRoot.displayName = \"Card.Root\";\nCardHeader.displayName = \"Card.Header\";\nCardTag.displayName = \"Card.Tag\";\nCardTitle.displayName = \"Card.Title\";\nCardDescription.displayName = \"Card.Description\";\nCardAction.displayName = \"Card.Action\";\nCardContent.displayName = \"Card.Content\";\nCardFooter.displayName = \"Card.Footer\";\n\nexport const Card = {\n Root: CardRoot,\n Header: CardHeader,\n Tag: CardTag,\n Title: CardTitle,\n Description: CardDescription,\n Action: CardAction,\n Content: CardContent,\n Footer: CardFooter,\n};\n"],"mappings":";;;;;;;;;;;;AAuDA,SAAS,SAAS,EAAE,WAAW,WAAW,OAAO,WAAW,GAAG,SAAsC;CACnG,MAAM,EAAE,SAAS,aAAa;EAAE;EAAW;CAAK,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,aAAW;EACX,WAAW,GAAG,KAAK,GAAG,SAAS;EAC/B,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,WAAW,GAAG,SAAS;EACrC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,QAAQ,EAAE,WAAW,WAAW,GAAG,SAAqC;CAC/E,MAAM,EAAE,YAAY,aAAa,EAAE,UAAU,CAAC;CAE9C,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAW,WAAW,GAAG,QAAQ,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AACpF;AAEA,SAAS,UAAU,EACjB,UACA,WACA,WACA,QAAQ,GACR,OAAO,OACP,MACA,GAAG,SAC4B;CAC/B,MAAM,EAAE,cAAc,aAAa,EAAE,UAAU,CAAC;CAChD,MAAM,UAAU,IAAI;CAEpB,OACE,qBAAC,SAAD;EACE,aAAU;EACV,WAAW,GACT,kBAAkB,EAAE,KAAK,CAAC,GAC1B,UAAU,EAGR,WAAW,OAAO,+CAA+C,KAAA,EACnE,CAAC,GACD,SACF;EACA,GAAI;EAXN,UAAA,CAYG,QAAQ,MACR,QACM;;AAEb;AAEA,SAAS,gBAAgB,EACvB,WACA,WACA,OAAO,MACP,GAAG,SACkC;CACrC,MAAM,EAAE,oBAAoB,aAAa,EAAE,UAAU,CAAC;CAEtD,OACE,oBAAC,KAAD;EACE,aAAU;EACV,WAAW,GAAG,wBAAwB,EAAE,KAAK,CAAC,GAAG,gBAAgB,GAAG,SAAS;EAC7E,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAc,WAAW,GAAG,WAAW,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AAC1F;AAEA,SAAS,YAAY,EAAE,WAAW,WAAW,GAAG,SAAqC;CACnF,MAAM,EAAE,gBAAgB,aAAa,EAAE,UAAU,CAAC;CAElD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,YAAY,GAAG,SAAS;EACtC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,WAAW,GAAG,SAAS;EACrC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,cAAc;AACvB,WAAW,cAAc;AACzB,QAAQ,cAAc;AACtB,UAAU,cAAc;AACxB,gBAAgB,cAAc;AAC9B,WAAW,cAAc;AACzB,YAAY,cAAc;AAC1B,WAAW,cAAc;AAEzB,MAAa,OAAO;CAClB,MAAM;CACN,QAAQ;CACR,KAAK;CACL,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;CACT,QAAQ;AACV"}
|
|
1
|
+
{"version":3,"file":"card.js","names":[],"sources":["../../../src/components/card/card.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactElement, ReactNode } from \"react\";\n\nimport type { VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../../styles/cn\";\nimport { CardSectionButton } from \"./card-section-button\";\nimport {\n cardDescriptionVariants,\n cardSectionVariants,\n cardTitleVariants,\n cardVariants,\n} from \"./card-variants\";\n\n// Every part takes `direction`; only the root takes the card's `size`, so the typography `size`\n// of `Card.Title` and `Card.Description` stays their own.\ntype CardVariantProps = Pick<VariantProps<typeof cardVariants>, \"direction\">;\n\ntype CardDivProps = HTMLAttributes<HTMLDivElement> & CardVariantProps;\n\ntype CardRootProps = CardDivProps & {\n /**\n * The card's surface tier, which pads its sections, gaps them and sets their inner corner.\n * `default` takes the medium tier, `--surface-pad-md`, which Items and Accordion items pad with\n * too, so the card's text starts on their edge. `lg` takes the large\n * tier, `--surface-pad-lg`, for a card that holds long prose or acts as a page's main panel.\n */\n size?: keyof typeof cardVariants.variants.size;\n};\n\ntype CardTitleLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\ntype CardTitleProps = HTMLAttributes<HTMLHeadingElement> &\n CardVariantProps & {\n /**\n * Heading element level — `1`–`6` picks the rendered `h1`–`h6`. Defaults to `3`, so\n * a card titles itself without assuming its place in the document outline.\n */\n level?: CardTitleLevel;\n /** Typography size for the title, mapped to a `text-{size}` class. Defaults to `2xl`. */\n size?: NonNullable<VariantProps<typeof cardTitleVariants>[\"size\"]>;\n /**\n * Rendered before `children` — the title becomes a flex row (`items-center gap-x-1.5`)\n * and any `svg` is sized to `5`.\n */\n icon?: ReactNode;\n };\n\ntype CardDescriptionProps = HTMLAttributes<HTMLParagraphElement> &\n CardVariantProps & {\n /** Typography size for the description, mapped to a `text-{size}` class. Defaults to `sm`. */\n size?: NonNullable<VariantProps<typeof cardDescriptionVariants>[\"size\"]>;\n };\n\n/**\n * The Card surface. It publishes `--inner-corner`, its corner less its border, and its header,\n * content and footer publish it less their padding too. The root and its sections write their\n * `direction` as `data-direction`: a vertical card pads its sections, a horizontal one pads itself.\n * The root writes its `size` as `data-size` and publishes its tier to the sections it holds.\n * Its 1px edge is the theme's `--card-border`: `--border` in internal themes and a zero-alpha\n * colour in external ones. A border colour class still wins.\n */\nfunction CardRoot({ className, direction, size = \"default\", ...props }: CardRootProps): ReactElement {\n const { base } = cardVariants({ direction, size });\n\n return (\n <div\n data-slot=\"card\"\n data-direction={direction ?? \"vertical\"}\n data-size={size}\n className={cn(base(), className)}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardHeader } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-header\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardHeader(), className)}\n {...props}\n />\n );\n}\n\nfunction CardTag({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardTag } = cardVariants({ direction });\n\n return <div data-slot=\"card-tag\" className={cn(cardTag(), className)} {...props} />;\n}\n\nfunction CardTitle({\n children,\n className,\n direction,\n level = 3,\n size = \"2xl\",\n icon,\n ...props\n}: CardTitleProps): ReactElement {\n const { cardTitle } = cardVariants({ direction });\n const Heading = `h${level}` as const;\n\n return (\n <Heading\n data-slot=\"card-title\"\n className={cn(\n cardTitleVariants({ size }),\n cardTitle({\n // `direction=\"horizontal\"` pins `text-xl/snug` here, so the size class must come first,\n // and the slot's leading must follow it: a font size drops a line height before it.\n className: icon ? \"flex items-center gap-x-1.5 [&>svg]:size-5\" : undefined,\n }),\n className\n )}\n {...props}>\n {icon ?? null}\n {children}\n </Heading>\n );\n}\n\nfunction CardDescription({\n className,\n direction,\n size = \"sm\",\n ...props\n}: CardDescriptionProps): ReactElement {\n const { cardDescription } = cardVariants({ direction });\n\n return (\n <p\n data-slot=\"card-description\"\n className={cn(cardDescriptionVariants({ size }), cardDescription(), className)}\n {...props}\n />\n );\n}\n\nfunction CardAction({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardAction } = cardVariants({ direction });\n\n return <div data-slot=\"card-action\" className={cn(cardAction(), className)} {...props} />;\n}\n\n/**\n * A card's body. Inside a `Card.Section` it is the section's content column, beside a\n * `Card.SectionMedia`, and drops its own padding, since the section pads.\n */\nfunction CardContent({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardContent } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-content\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardContent(), className)}\n {...props}\n />\n );\n}\n\nfunction CardFooter({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardFooter } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-footer\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardFooter(), className)}\n {...props}\n />\n );\n}\n\n/**\n * One of a vertical card's stacked sections of equal weight. Sections form the card's body under\n * one optional `Card.Header`: a `Card.Content` or `Card.Footer` beside them takes no divider, so\n * put that content in a section instead. A section pads every side with the card's tier, a 1px\n * `--card-section-divider` line separates it from the part above, and the first and last\n * sections round with the card's corners. A `Card.SectionMedia` as its first child makes it a\n * two-column grid with the media centred beside a `Card.Content`, the unpadded content column.\n * A horizontal card pads itself, so sections take no `direction` and belong in a vertical card.\n * A whole section that acts is a `Card.SectionButton`.\n */\nfunction CardSection({ className, ...props }: HTMLAttributes<HTMLDivElement>): ReactElement {\n const { section } = cardSectionVariants();\n\n return <div data-slot=\"card-section\" className={cn(section(), className)} {...props} />;\n}\n\n/**\n * The icon column of a `Card.Section` or `Card.SectionButton`. The section becomes a two-column\n * grid, this column and the content, with the icon centred on the section's height. An `svg` is\n * sized to `5`. It is a `span`, so it is phrasing content inside a section button.\n */\nfunction CardSectionMedia({ className, ...props }: HTMLAttributes<HTMLSpanElement>): ReactElement {\n const { media } = cardSectionVariants();\n\n return <span data-slot=\"card-section-media\" className={cn(media(), className)} {...props} />;\n}\n\nCardRoot.displayName = \"Card.Root\";\nCardHeader.displayName = \"Card.Header\";\nCardTag.displayName = \"Card.Tag\";\nCardTitle.displayName = \"Card.Title\";\nCardDescription.displayName = \"Card.Description\";\nCardAction.displayName = \"Card.Action\";\nCardContent.displayName = \"Card.Content\";\nCardFooter.displayName = \"Card.Footer\";\nCardSection.displayName = \"Card.Section\";\nCardSectionMedia.displayName = \"Card.SectionMedia\";\n\nexport const Card = {\n Root: CardRoot,\n Header: CardHeader,\n Tag: CardTag,\n Title: CardTitle,\n Description: CardDescription,\n Action: CardAction,\n Content: CardContent,\n Footer: CardFooter,\n Section: CardSection,\n SectionButton: CardSectionButton,\n SectionMedia: CardSectionMedia,\n};\n"],"mappings":";;;;;;;;;;;;;AA6DA,SAAS,SAAS,EAAE,WAAW,WAAW,OAAO,WAAW,GAAG,SAAsC;CACnG,MAAM,EAAE,SAAS,aAAa;EAAE;EAAW;CAAK,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,aAAW;EACX,WAAW,GAAG,KAAK,GAAG,SAAS;EAC/B,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,WAAW,GAAG,SAAS;EACrC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,QAAQ,EAAE,WAAW,WAAW,GAAG,SAAqC;CAC/E,MAAM,EAAE,YAAY,aAAa,EAAE,UAAU,CAAC;CAE9C,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAW,WAAW,GAAG,QAAQ,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AACpF;AAEA,SAAS,UAAU,EACjB,UACA,WACA,WACA,QAAQ,GACR,OAAO,OACP,MACA,GAAG,SAC4B;CAC/B,MAAM,EAAE,cAAc,aAAa,EAAE,UAAU,CAAC;CAChD,MAAM,UAAU,IAAI;CAEpB,OACE,qBAAC,SAAD;EACE,aAAU;EACV,WAAW,GACT,kBAAkB,EAAE,KAAK,CAAC,GAC1B,UAAU,EAGR,WAAW,OAAO,+CAA+C,KAAA,EACnE,CAAC,GACD,SACF;EACA,GAAI;EAXN,UAAA,CAYG,QAAQ,MACR,QACM;;AAEb;AAEA,SAAS,gBAAgB,EACvB,WACA,WACA,OAAO,MACP,GAAG,SACkC;CACrC,MAAM,EAAE,oBAAoB,aAAa,EAAE,UAAU,CAAC;CAEtD,OACE,oBAAC,KAAD;EACE,aAAU;EACV,WAAW,GAAG,wBAAwB,EAAE,KAAK,CAAC,GAAG,gBAAgB,GAAG,SAAS;EAC7E,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAc,WAAW,GAAG,WAAW,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AAC1F;;;;;AAMA,SAAS,YAAY,EAAE,WAAW,WAAW,GAAG,SAAqC;CACnF,MAAM,EAAE,gBAAgB,aAAa,EAAE,UAAU,CAAC;CAElD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,YAAY,GAAG,SAAS;EACtC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,WAAW,GAAG,SAAS;EACrC,GAAI;CACL,CAAA;AAEL;;;;;;;;;;;AAYA,SAAS,YAAY,EAAE,WAAW,GAAG,SAAuD;CAC1F,MAAM,EAAE,YAAY,oBAAoB;CAExC,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAe,WAAW,GAAG,QAAQ,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AACxF;;;;;;AAOA,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAwD;CAChG,MAAM,EAAE,UAAU,oBAAoB;CAEtC,OAAO,oBAAC,QAAD;EAAM,aAAU;EAAqB,WAAW,GAAG,MAAM,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AAC7F;AAEA,SAAS,cAAc;AACvB,WAAW,cAAc;AACzB,QAAQ,cAAc;AACtB,UAAU,cAAc;AACxB,gBAAgB,cAAc;AAC9B,WAAW,cAAc;AACzB,YAAY,cAAc;AAC1B,WAAW,cAAc;AACzB,YAAY,cAAc;AAC1B,iBAAiB,cAAc;AAE/B,MAAa,OAAO;CAClB,MAAM;CACN,QAAQ;CACR,KAAK;CACL,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CACT,eAAe;CACf,cAAc;AAChB"}
|
|
@@ -2,7 +2,19 @@ import { DescriptionListHeading, DescriptionListHeadingProps } from "./descripti
|
|
|
2
2
|
import { ComponentProps, ReactElement } from "react";
|
|
3
3
|
//#region src/components/description-list/description-list.d.ts
|
|
4
4
|
export type DescriptionListRootProps = ComponentProps<"div">;
|
|
5
|
-
export type DescriptionListContentProps = ComponentProps<"dl"
|
|
5
|
+
export type DescriptionListContentProps = ComponentProps<"dl"> & {
|
|
6
|
+
/**
|
|
7
|
+
* How terms and details sit. `responsive` stacks each details under its term on phones and
|
|
8
|
+
* sets them in two columns, with a rule between rows, from `sm` up. `inline` keeps each term
|
|
9
|
+
* and its details on one row at every width, for label/value rows in cards and summaries: the
|
|
10
|
+
* details align to the end, a short one never wraps and a long one wraps within 60% of the
|
|
11
|
+
* row. Inline rows take the label type, have no rules and space with the small surface gap,
|
|
12
|
+
* and the term is not muted. A colour class on a cell wins in both layouts. The inline cells'
|
|
13
|
+
* padding, rules, column and alignment come from the list, so override them with a
|
|
14
|
+
* `[:where([data-layout=inline])>&]:` class or a CSS rule. Defaults to `responsive`.
|
|
15
|
+
*/
|
|
16
|
+
layout?: "responsive" | "inline";
|
|
17
|
+
};
|
|
6
18
|
export type DescriptionListTermProps = ComponentProps<"dt">;
|
|
7
19
|
export type DescriptionListDetailsProps = ComponentProps<"dd">;
|
|
8
20
|
/**
|
|
@@ -11,7 +23,7 @@ export type DescriptionListDetailsProps = ComponentProps<"dd">;
|
|
|
11
23
|
* possible without making this module a client boundary.
|
|
12
24
|
*/
|
|
13
25
|
declare function DescriptionListRoot(props: DescriptionListRootProps): ReactElement;
|
|
14
|
-
declare function DescriptionListContent({ className, ...props }: DescriptionListContentProps): ReactElement;
|
|
26
|
+
declare function DescriptionListContent({ className, layout, ...props }: DescriptionListContentProps): ReactElement;
|
|
15
27
|
declare function DescriptionListTerm({ className, ...props }: DescriptionListTermProps): ReactElement;
|
|
16
28
|
declare function DescriptionListDetails({ className, ...props }: DescriptionListDetailsProps): ReactElement;
|
|
17
29
|
export declare const DescriptionList: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"description-list.d.ts","names":[],"sources":["../../../src/components/description-list/description-list.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"description-list.d.ts","names":[],"sources":["../../../src/components/description-list/description-list.tsx"],"mappings":";;;YAMY,2BAA2B;YAC3B,8BAA8B;;;;;;;;;;;EAWxC;;YAEU,2BAA2B;YAC3B,8BAA8B;;;;;;iBAQjC,oBAAoB,OAAO,2BAA2B;iBA8BtD,yBACP,WACA,WACG,SACF,8BAA8B;iBAWxB,sBAAsB,cAAc,SAAS,2BAA2B;iBAcxE,yBAAyB,cAAc,SAAS,8BAA8B;qBAmB1E;EACX,aAAI;EACJ,gBAAO;EACP,gBAAO;EACP,aAAI;EACJ,gBAAO"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cn } from "../../styles/cn.js";
|
|
2
|
+
import { labelTypeClass } from "../../styles/label-type.js";
|
|
2
3
|
import { DescriptionListHeading } from "./description-list-heading.js";
|
|
3
4
|
import { jsx } from "react/jsx-runtime";
|
|
4
5
|
//#region src/components/description-list/description-list.tsx
|
|
@@ -13,24 +14,33 @@ function DescriptionListRoot(props) {
|
|
|
13
14
|
...props
|
|
14
15
|
});
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
+
/** The responsive list: one column on phones, then a term column capped at min(50%, 20rem). */
|
|
18
|
+
const responsiveContentClass = cn("text-base/6 sm:grid-cols-[min(50%,calc(var(--spacing)*80))_auto] sm:text-sm/6 grid grid-cols-1 [--description-list-details:initial] [--description-list-term:initial]");
|
|
19
|
+
/**
|
|
20
|
+
* The inline list: `minmax(0,1fr)` for the terms and `fit-content(60%)` for the details, rows
|
|
21
|
+
* spaced by the small surface gap, the label type set here for the cells to inherit, and
|
|
22
|
+
* consecutive inline lists spaced by the large surface gap.
|
|
23
|
+
*/
|
|
24
|
+
const inlineContentClass = cn("grid grid-cols-[minmax(0,1fr)_fit-content(60%)] gap-x-(--surface-gap-md) gap-y-(--surface-gap-sm)", labelTypeClass, "[--description-list-details:currentColor] [--description-list-term:currentColor]", "[&+&]:mt-(--surface-gap-lg)");
|
|
25
|
+
function DescriptionListContent({ className, layout = "responsive", ...props }) {
|
|
17
26
|
return /* @__PURE__ */ jsx("dl", {
|
|
18
27
|
"data-slot": "description-list-content",
|
|
19
|
-
|
|
28
|
+
"data-layout": layout,
|
|
29
|
+
className: cn(layout === "inline" ? inlineContentClass : responsiveContentClass, className),
|
|
20
30
|
...props
|
|
21
31
|
});
|
|
22
32
|
}
|
|
23
33
|
function DescriptionListTerm({ className, ...props }) {
|
|
24
34
|
return /* @__PURE__ */ jsx("dt", {
|
|
25
35
|
"data-slot": "description-list-term",
|
|
26
|
-
className: cn("col-start-1 border-t py-(--row-py) pr-(--row-px) text-muted-foreground first-of-type:border-none", className),
|
|
36
|
+
className: cn("col-start-1 border-t py-(--row-py) pr-(--row-px) text-[color:var(--description-list-term,var(--muted-foreground))] first-of-type:border-none", "[:where([data-layout=inline])>&]:min-w-0 [:where([data-layout=inline])>&]:border-none [:where([data-layout=inline])>&]:p-0 [:where([data-layout=inline])>&]:wrap-anywhere", className),
|
|
27
37
|
...props
|
|
28
38
|
});
|
|
29
39
|
}
|
|
30
40
|
function DescriptionListDetails({ className, ...props }) {
|
|
31
41
|
return /* @__PURE__ */ jsx("dd", {
|
|
32
42
|
"data-slot": "description-list-details",
|
|
33
|
-
className: cn("sm:border-t py-(--row-py) text-foreground first-of-type:border-none", className),
|
|
43
|
+
className: cn("sm:border-t py-(--row-py) text-[color:var(--description-list-details,var(--foreground))] first-of-type:border-none", "[:where([data-layout=inline])>&]:col-start-2 [:where([data-layout=inline])>&]:min-w-0 [:where([data-layout=inline])>&]:border-none [:where([data-layout=inline])>&]:py-0 [:where([data-layout=inline])>&]:text-end [:where([data-layout=inline])>&]:wrap-anywhere", className),
|
|
34
44
|
...props
|
|
35
45
|
});
|
|
36
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"description-list.js","names":[],"sources":["../../../src/components/description-list/description-list.tsx"],"sourcesContent":["import type { ComponentProps, ReactElement } from \"react\";\n\nimport { cn } from \"../../styles/cn\";\nimport { DescriptionListHeading } from \"./description-list-heading\";\n\nexport type DescriptionListRootProps = ComponentProps<\"div\">;\nexport type DescriptionListContentProps = ComponentProps<\"dl\"
|
|
1
|
+
{"version":3,"file":"description-list.js","names":[],"sources":["../../../src/components/description-list/description-list.tsx"],"sourcesContent":["import type { ComponentProps, ReactElement } from \"react\";\n\nimport { cn } from \"../../styles/cn\";\nimport { labelTypeClass } from \"../../styles/label-type\";\nimport { DescriptionListHeading } from \"./description-list-heading\";\n\nexport type DescriptionListRootProps = ComponentProps<\"div\">;\nexport type DescriptionListContentProps = ComponentProps<\"dl\"> & {\n /**\n * How terms and details sit. `responsive` stacks each details under its term on phones and\n * sets them in two columns, with a rule between rows, from `sm` up. `inline` keeps each term\n * and its details on one row at every width, for label/value rows in cards and summaries: the\n * details align to the end, a short one never wraps and a long one wraps within 60% of the\n * row. Inline rows take the label type, have no rules and space with the small surface gap,\n * and the term is not muted. A colour class on a cell wins in both layouts. The inline cells'\n * padding, rules, column and alignment come from the list, so override them with a\n * `[:where([data-layout=inline])>&]:` class or a CSS rule. Defaults to `responsive`.\n */\n layout?: \"responsive\" | \"inline\";\n};\nexport type DescriptionListTermProps = ComponentProps<\"dt\">;\nexport type DescriptionListDetailsProps = ComponentProps<\"dd\">;\nexport type { DescriptionListHeadingProps } from \"./description-list-heading\";\n\n/**\n * Semantic `<dl>/<dt>/<dd>` composite. A server compound: it owns no state, handlers or\n * browser APIs. `Heading` is a client `useRender` island, so other outline levels stay\n * possible without making this module a client boundary.\n */\nfunction DescriptionListRoot(props: DescriptionListRootProps): ReactElement {\n return <div data-slot=\"description-list\" {...props} />;\n}\n\n// The inline layout publishes the term and details colours as the private `--description-list-term`\n// and `--description-list-details`, and the responsive one resets them, so its cells fall back to\n// `--muted-foreground` and `--foreground` read in their own theme scope. A nested list resets them\n// too, and a consumer colour class on a cell still wins in both layouts. Inline cells take the\n// surrounding text colour, such as a card's. The term and details style the rest of the inline\n// layout from their own list's `data-layout`, as its direct children, so a responsive list nested\n// in an inline one keeps its own layout. Plain `cn` constants rather than a `tv` recipe keep\n// tailwind-variants out of this entry's size budget.\n\n/** The responsive list: one column on phones, then a term column capped at min(50%, 20rem). */\nconst responsiveContentClass = cn(\n \"text-base/6 sm:grid-cols-[min(50%,calc(var(--spacing)*80))_auto] sm:text-sm/6 grid grid-cols-1 [--description-list-details:initial] [--description-list-term:initial]\"\n);\n\n/**\n * The inline list: `minmax(0,1fr)` for the terms and `fit-content(60%)` for the details, rows\n * spaced by the small surface gap, the label type set here for the cells to inherit, and\n * consecutive inline lists spaced by the large surface gap.\n */\nconst inlineContentClass = cn(\n \"grid grid-cols-[minmax(0,1fr)_fit-content(60%)] gap-x-(--surface-gap-md) gap-y-(--surface-gap-sm)\",\n labelTypeClass,\n \"[--description-list-details:currentColor] [--description-list-term:currentColor]\",\n \"[&+&]:mt-(--surface-gap-lg)\"\n);\n\nfunction DescriptionListContent({\n className,\n layout = \"responsive\",\n ...props\n}: DescriptionListContentProps): ReactElement {\n return (\n <dl\n data-slot=\"description-list-content\"\n data-layout={layout}\n className={cn(layout === \"inline\" ? inlineContentClass : responsiveContentClass, className)}\n {...props}\n />\n );\n}\n\nfunction DescriptionListTerm({ className, ...props }: DescriptionListTermProps): ReactElement {\n return (\n <dt\n data-slot=\"description-list-term\"\n className={cn(\n \"col-start-1 border-t py-(--row-py) pr-(--row-px) text-[color:var(--description-list-term,var(--muted-foreground))] first-of-type:border-none\",\n \"[:where([data-layout=inline])>&]:min-w-0 [:where([data-layout=inline])>&]:border-none [:where([data-layout=inline])>&]:p-0 [:where([data-layout=inline])>&]:wrap-anywhere\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction DescriptionListDetails({ className, ...props }: DescriptionListDetailsProps): ReactElement {\n return (\n <dd\n data-slot=\"description-list-details\"\n className={cn(\n \"sm:border-t py-(--row-py) text-[color:var(--description-list-details,var(--foreground))] first-of-type:border-none\",\n \"[:where([data-layout=inline])>&]:col-start-2 [:where([data-layout=inline])>&]:min-w-0 [:where([data-layout=inline])>&]:border-none [:where([data-layout=inline])>&]:py-0 [:where([data-layout=inline])>&]:text-end [:where([data-layout=inline])>&]:wrap-anywhere\",\n className\n )}\n {...props}\n />\n );\n}\n\nDescriptionListRoot.displayName = \"DescriptionList.Root\";\nDescriptionListContent.displayName = \"DescriptionList.Content\";\nDescriptionListTerm.displayName = \"DescriptionList.Term\";\nDescriptionListDetails.displayName = \"DescriptionList.Details\";\n\nexport const DescriptionList = {\n Root: DescriptionListRoot,\n Heading: DescriptionListHeading,\n Content: DescriptionListContent,\n Term: DescriptionListTerm,\n Details: DescriptionListDetails,\n};\n"],"mappings":";;;;;;;;;;AA6BA,SAAS,oBAAoB,OAA+C;CAC1E,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAmB,GAAI;CAAQ,CAAA;AACvD;;AAYA,MAAM,yBAAyB,GAC7B,uKACF;;;;;;AAOA,MAAM,qBAAqB,GACzB,qGACA,gBACA,oFACA,6BACF;AAEA,SAAS,uBAAuB,EAC9B,WACA,SAAS,cACT,GAAG,SACyC;CAC5C,OACE,oBAAC,MAAD;EACE,aAAU;EACV,eAAa;EACb,WAAW,GAAG,WAAW,WAAW,qBAAqB,wBAAwB,SAAS;EAC1F,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,oBAAoB,EAAE,WAAW,GAAG,SAAiD;CAC5F,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,gJACA,6KACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,uBAAuB,EAAE,WAAW,GAAG,SAAoD;CAClG,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,sHACA,qQACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,oBAAoB,cAAc;AAClC,uBAAuB,cAAc;AACrC,oBAAoB,cAAc;AAClC,uBAAuB,cAAc;AAErC,MAAa,kBAAkB;CAC7B,MAAM;CACN,SAAS;CACT,SAAS;CACT,MAAM;CACN,SAAS;AACX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elmeragroup/fuse",
|
|
3
|
-
"version": "0.1.0-canary.
|
|
3
|
+
"version": "0.1.0-canary.115",
|
|
4
4
|
"description": "Fuse — whitelabel React components for Elmera Group's energy brands. One package, twenty theme permutations, ESM-only.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -391,7 +391,7 @@
|
|
|
391
391
|
"access": "public"
|
|
392
392
|
},
|
|
393
393
|
"elmeraRelease": {
|
|
394
|
-
"commit": "
|
|
394
|
+
"commit": "41bf4f22a1422017b8b35588da5c3acfc285e646",
|
|
395
395
|
"channel": "canary"
|
|
396
396
|
}
|
|
397
397
|
}
|
package/styles/fuse.css
CHANGED
|
@@ -146,6 +146,7 @@
|
|
|
146
146
|
--color-input: var(--input);
|
|
147
147
|
--color-ring: var(--ring);
|
|
148
148
|
--color-card-border: var(--card-border, var(--border));
|
|
149
|
+
--color-card-section-divider: var(--card-section-divider, var(--border));
|
|
149
150
|
--color-button-outline: var(--button-outline, var(--border));
|
|
150
151
|
--color-selection-border: var(--selection-border, var(--border));
|
|
151
152
|
--color-selection-checked-border: var(--selection-checked-border, var(--primary));
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
//#region src/styles/inner-corner/card.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* The Card root: `rounded-lg` behind a 1px border.
|
|
3
|
+
* The Card root: `rounded-lg` behind a 1px border. It hands every direct child the corner a
|
|
4
|
+
* stacked section rounds with, its own less the border, as the private `--card-section-corner`,
|
|
5
|
+
* as Frame does with `--frame-corner`. It keys on no slot, because a `Card.SectionButton` a
|
|
6
|
+
* trigger renders carries the trigger's `data-slot`. Every section resets the property, and the
|
|
7
|
+
* root's child rule comes later in the sheet at the same specificity, so only a card's direct
|
|
8
|
+
* section holds a value and one nested deeper is square.
|
|
4
9
|
*/
|
|
5
10
|
export declare const cardShellClass: string;
|
|
6
11
|
/**
|
|
@@ -33,5 +38,13 @@ export declare const textFieldCardShellClass: string;
|
|
|
33
38
|
* block axis.
|
|
34
39
|
*/
|
|
35
40
|
export declare const checkboxCardContentShellClass: string;
|
|
41
|
+
/**
|
|
42
|
+
* A stacked `Card.Section` or `Card.SectionButton`: it pads every side with the card's tier,
|
|
43
|
+
* `--card-pad`, and publishes the same inner corner as the other sections. A 1px
|
|
44
|
+
* `--card-section-divider` line runs above every section but the first. The first and last sections round their outer corners with the corner the
|
|
45
|
+
* card hands them, so a fill or a hover fill follows the card's corners. Both skip `hidden`
|
|
46
|
+
* siblings, and middle sections stay square. Outside a card the section is square.
|
|
47
|
+
*/
|
|
48
|
+
export declare const cardStackedSectionShellClass: string;
|
|
36
49
|
//#endregion
|
|
37
50
|
//# sourceMappingURL=card.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.d.ts","names":[],"sources":["../../../src/styles/inner-corner/card.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"card.d.ts","names":[],"sources":["../../../src/styles/inner-corner/card.ts"],"mappings":";;;;;;;;;qBAca;;;;;;qBAUA;;;;;qBAMA;;;;qBAgBA;;;;;qBASA;;;;;qBAMA;;;;;qBASA;;;;;;;;qBAYA"}
|
|
@@ -2,9 +2,14 @@ import { cn } from "../cn.js";
|
|
|
2
2
|
import { publishShellBoundary } from "../corner-radius.js";
|
|
3
3
|
//#region src/styles/inner-corner/card.ts
|
|
4
4
|
/**
|
|
5
|
-
* The Card root: `rounded-lg` behind a 1px border.
|
|
5
|
+
* The Card root: `rounded-lg` behind a 1px border. It hands every direct child the corner a
|
|
6
|
+
* stacked section rounds with, its own less the border, as the private `--card-section-corner`,
|
|
7
|
+
* as Frame does with `--frame-corner`. It keys on no slot, because a `Card.SectionButton` a
|
|
8
|
+
* trigger renders carries the trigger's `data-slot`. Every section resets the property, and the
|
|
9
|
+
* root's child rule comes later in the sheet at the same specificity, so only a card's direct
|
|
10
|
+
* section holds a value and one nested deeper is square.
|
|
6
11
|
*/
|
|
7
|
-
const cardShellClass = cn("rounded-lg border [--shell-inner:max(0px,--theme(--radius-lg)-1px)]", publishShellBoundary);
|
|
12
|
+
const cardShellClass = cn("rounded-lg border [--shell-inner:max(0px,--theme(--radius-lg)-1px)] *:[--card-section-corner:max(0px,--theme(--radius-lg)-1px)]", publishShellBoundary);
|
|
8
13
|
/**
|
|
9
14
|
* A default Card's tier, published on the root as the private `--card-pad`: the medium surface
|
|
10
15
|
* tier, `--surface-pad-md`, which Items and Accordion items pad with too, so a card's text starts
|
|
@@ -42,7 +47,15 @@ const textFieldCardShellClass = cn("px-[var(--card-pad,var(--surface-pad-md))] p
|
|
|
42
47
|
* block axis.
|
|
43
48
|
*/
|
|
44
49
|
const checkboxCardContentShellClass = cn("px-[var(--card-pad,var(--surface-pad-md))] py-3", cardTierBoundaryClass);
|
|
50
|
+
/**
|
|
51
|
+
* A stacked `Card.Section` or `Card.SectionButton`: it pads every side with the card's tier,
|
|
52
|
+
* `--card-pad`, and publishes the same inner corner as the other sections. A 1px
|
|
53
|
+
* `--card-section-divider` line runs above every section but the first. The first and last sections round their outer corners with the corner the
|
|
54
|
+
* card hands them, so a fill or a hover fill follows the card's corners. Both skip `hidden`
|
|
55
|
+
* siblings, and middle sections stay square. Outside a card the section is square.
|
|
56
|
+
*/
|
|
57
|
+
const cardStackedSectionShellClass = cn("border-0 border-t border-card-section-divider p-[var(--card-pad,var(--surface-pad-md))] [--card-section-corner:initial] [&:nth-child(1_of_:not([hidden]))]:rounded-t-[var(--card-section-corner,0px)] [&:nth-child(1_of_:not([hidden]))]:border-t-0 [&:nth-last-child(1_of_:not([hidden]))]:rounded-b-[var(--card-section-corner,0px)]", "[&[hidden]:not([hidden=until-found])]:hidden", cardTierBoundaryClass);
|
|
45
58
|
//#endregion
|
|
46
|
-
export { cardDefaultTierClass, cardHorizontalShellClass, cardLargeTierClass, cardSectionShellClass, cardShellClass, checkboxCardContentShellClass, textFieldCardShellClass };
|
|
59
|
+
export { cardDefaultTierClass, cardHorizontalShellClass, cardLargeTierClass, cardSectionShellClass, cardShellClass, cardStackedSectionShellClass, checkboxCardContentShellClass, textFieldCardShellClass };
|
|
47
60
|
|
|
48
61
|
//# sourceMappingURL=card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","names":[],"sources":["../../../src/styles/inner-corner/card.ts"],"sourcesContent":["import { cn } from \"../cn\";\nimport { publishShellBoundary } from \"../corner-radius\";\n\n// The inner-corner shells of Card and the parts built on it. The rules every shell follows are in\n// `corner-radius.ts`. Each constant pairs a part's rung or padding with the corner it publishes.\n\n/**\n * The Card root: `rounded-lg` behind a 1px border.\n */\nexport const cardShellClass = cn(\n \"rounded-lg border [--shell-inner:max(0px,--theme(--radius-lg)-1px)]\",\n publishShellBoundary\n);\n\n/**\n * A default Card's tier, published on the root as the private `--card-pad`: the medium surface\n * tier, `--surface-pad-md`, which Items and Accordion items pad with too, so a card's text starts\n * on their edge. Every root sets it, so a nested card resets it.\n */\nexport const cardDefaultTierClass = cn(\"[--card-pad:var(--surface-pad-md)]\");\n\n/**\n * A large Card's tier: the large surface tier, `--surface-pad-lg`, for a card that holds long\n * prose or acts as a page's main panel.\n */\nexport const cardLargeTierClass = cn(\"[--card-pad:var(--surface-pad-lg)]\");\n\n/**\n * The boundary every padded part inside a Card's border publishes: the card's `rounded-lg` less\n * its 1px border and the card's tier, `--card-pad`, its inline padding. Each padded part falls\n * back to the default tier outside a card root, so a section recipe used on its own pads as one\n * inside a default card.\n */\nconst cardTierBoundaryClass = cn(\n \"[--shell-inner:max(0px,--theme(--radius-lg)-1px-var(--card-pad,var(--surface-pad-md)))]\",\n publishShellBoundary\n);\n\n/**\n * A horizontal Card root, which pads its sections itself with the card's tier, `--card-pad`.\n */\nexport const cardHorizontalShellClass = cn(\n \"p-[var(--card-pad,var(--surface-pad-md))]\",\n cardTierBoundaryClass\n);\n\n/**\n * A vertical Card's header, content or footer, which pads with the card's tier, `--card-pad`,\n * inside the card.\n */\nexport const cardSectionShellClass = cn(\"p-[var(--card-pad,var(--surface-pad-md))]\", cardTierBoundaryClass);\n\n/**\n * The TextField `card` box: a default Card root that pads inline with its tier and 16px on the\n * block axis.\n */\nexport const textFieldCardShellClass = cn(\n \"px-[var(--card-pad,var(--surface-pad-md))] py-4\",\n cardTierBoundaryClass\n);\n\n/**\n * The CheckboxCard content: a default Card's section that pads inline with its tier and 12px on the\n * block axis.\n */\nexport const checkboxCardContentShellClass = cn(\n \"px-[var(--card-pad,var(--surface-pad-md))] py-3\",\n cardTierBoundaryClass\n);\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"card.js","names":[],"sources":["../../../src/styles/inner-corner/card.ts"],"sourcesContent":["import { cn } from \"../cn\";\nimport { publishShellBoundary } from \"../corner-radius\";\n\n// The inner-corner shells of Card and the parts built on it. The rules every shell follows are in\n// `corner-radius.ts`. Each constant pairs a part's rung or padding with the corner it publishes.\n\n/**\n * The Card root: `rounded-lg` behind a 1px border. It hands every direct child the corner a\n * stacked section rounds with, its own less the border, as the private `--card-section-corner`,\n * as Frame does with `--frame-corner`. It keys on no slot, because a `Card.SectionButton` a\n * trigger renders carries the trigger's `data-slot`. Every section resets the property, and the\n * root's child rule comes later in the sheet at the same specificity, so only a card's direct\n * section holds a value and one nested deeper is square.\n */\nexport const cardShellClass = cn(\n \"rounded-lg border [--shell-inner:max(0px,--theme(--radius-lg)-1px)] *:[--card-section-corner:max(0px,--theme(--radius-lg)-1px)]\",\n publishShellBoundary\n);\n\n/**\n * A default Card's tier, published on the root as the private `--card-pad`: the medium surface\n * tier, `--surface-pad-md`, which Items and Accordion items pad with too, so a card's text starts\n * on their edge. Every root sets it, so a nested card resets it.\n */\nexport const cardDefaultTierClass = cn(\"[--card-pad:var(--surface-pad-md)]\");\n\n/**\n * A large Card's tier: the large surface tier, `--surface-pad-lg`, for a card that holds long\n * prose or acts as a page's main panel.\n */\nexport const cardLargeTierClass = cn(\"[--card-pad:var(--surface-pad-lg)]\");\n\n/**\n * The boundary every padded part inside a Card's border publishes: the card's `rounded-lg` less\n * its 1px border and the card's tier, `--card-pad`, its inline padding. Each padded part falls\n * back to the default tier outside a card root, so a section recipe used on its own pads as one\n * inside a default card.\n */\nconst cardTierBoundaryClass = cn(\n \"[--shell-inner:max(0px,--theme(--radius-lg)-1px-var(--card-pad,var(--surface-pad-md)))]\",\n publishShellBoundary\n);\n\n/**\n * A horizontal Card root, which pads its sections itself with the card's tier, `--card-pad`.\n */\nexport const cardHorizontalShellClass = cn(\n \"p-[var(--card-pad,var(--surface-pad-md))]\",\n cardTierBoundaryClass\n);\n\n/**\n * A vertical Card's header, content or footer, which pads with the card's tier, `--card-pad`,\n * inside the card.\n */\nexport const cardSectionShellClass = cn(\"p-[var(--card-pad,var(--surface-pad-md))]\", cardTierBoundaryClass);\n\n/**\n * The TextField `card` box: a default Card root that pads inline with its tier and 16px on the\n * block axis.\n */\nexport const textFieldCardShellClass = cn(\n \"px-[var(--card-pad,var(--surface-pad-md))] py-4\",\n cardTierBoundaryClass\n);\n\n/**\n * The CheckboxCard content: a default Card's section that pads inline with its tier and 12px on the\n * block axis.\n */\nexport const checkboxCardContentShellClass = cn(\n \"px-[var(--card-pad,var(--surface-pad-md))] py-3\",\n cardTierBoundaryClass\n);\n\n/**\n * A stacked `Card.Section` or `Card.SectionButton`: it pads every side with the card's tier,\n * `--card-pad`, and publishes the same inner corner as the other sections. A 1px\n * `--card-section-divider` line runs above every section but the first. The first and last sections round their outer corners with the corner the\n * card hands them, so a fill or a hover fill follows the card's corners. Both skip `hidden`\n * siblings, and middle sections stay square. Outside a card the section is square.\n */\nexport const cardStackedSectionShellClass = cn(\n \"border-0 border-t border-card-section-divider p-[var(--card-pad,var(--surface-pad-md))] [--card-section-corner:initial] [&:nth-child(1_of_:not([hidden]))]:rounded-t-[var(--card-section-corner,0px)] [&:nth-child(1_of_:not([hidden]))]:border-t-0 [&:nth-last-child(1_of_:not([hidden]))]:rounded-b-[var(--card-section-corner,0px)]\",\n // Without preflight a section's own `block` or `grid` beats the user-agent `[hidden]` rule.\n \"[&[hidden]:not([hidden=until-found])]:hidden\",\n cardTierBoundaryClass\n);\n"],"mappings":";;;;;;;;;;;AAcA,MAAa,iBAAiB,GAC5B,mIACA,oBACF;;;;;;AAOA,MAAa,uBAAuB,GAAG,oCAAoC;;;;;AAM3E,MAAa,qBAAqB,GAAG,oCAAoC;;;;;;;AAQzE,MAAM,wBAAwB,GAC5B,2FACA,oBACF;;;;AAKA,MAAa,2BAA2B,GACtC,6CACA,qBACF;;;;;AAMA,MAAa,wBAAwB,GAAG,6CAA6C,qBAAqB;;;;;AAM1G,MAAa,0BAA0B,GACrC,mDACA,qBACF;;;;;AAMA,MAAa,gCAAgC,GAC3C,mDACA,qBACF;;;;;;;;AASA,MAAa,+BAA+B,GAC1C,0UAEA,gDACA,qBACF"}
|
package/styles.css
CHANGED
|
@@ -964,6 +964,9 @@
|
|
|
964
964
|
.grid-cols-\[minmax\(0\,1fr\)_auto\] {
|
|
965
965
|
grid-template-columns: minmax(0,1fr) auto;
|
|
966
966
|
}
|
|
967
|
+
.grid-cols-\[minmax\(0\,1fr\)_fit-content\(60\%\)\] {
|
|
968
|
+
grid-template-columns: minmax(0,1fr) fit-content(60%);
|
|
969
|
+
}
|
|
967
970
|
.grid-cols-subgrid {
|
|
968
971
|
grid-template-columns: subgrid;
|
|
969
972
|
}
|
|
@@ -1081,6 +1084,9 @@
|
|
|
1081
1084
|
margin-block-start: calc(calc(0.25rem * 4) * var(--tw-space-y-reverse));
|
|
1082
1085
|
margin-block-end: calc(calc(0.25rem * 4) * calc(1 - var(--tw-space-y-reverse)));
|
|
1083
1086
|
}
|
|
1087
|
+
.gap-x-\(--surface-gap-md\) {
|
|
1088
|
+
column-gap: var(--surface-gap-md);
|
|
1089
|
+
}
|
|
1084
1090
|
.gap-x-1\.5 {
|
|
1085
1091
|
column-gap: calc(0.25rem * 1.5);
|
|
1086
1092
|
}
|
|
@@ -1101,6 +1107,9 @@
|
|
|
1101
1107
|
margin-inline-start: calc(calc(0.25rem * -2) * var(--tw-space-x-reverse));
|
|
1102
1108
|
margin-inline-end: calc(calc(0.25rem * -2) * calc(1 - var(--tw-space-x-reverse)));
|
|
1103
1109
|
}
|
|
1110
|
+
.gap-y-\(--surface-gap-sm\) {
|
|
1111
|
+
row-gap: var(--surface-gap-sm);
|
|
1112
|
+
}
|
|
1104
1113
|
.gap-y-1 {
|
|
1105
1114
|
row-gap: 0.25rem;
|
|
1106
1115
|
}
|
|
@@ -1258,6 +1267,9 @@
|
|
|
1258
1267
|
.border-card-border {
|
|
1259
1268
|
border-color: var(--card-border, var(--border));
|
|
1260
1269
|
}
|
|
1270
|
+
.border-card-section-divider {
|
|
1271
|
+
border-color: var(--card-section-divider, var(--border));
|
|
1272
|
+
}
|
|
1261
1273
|
.border-error {
|
|
1262
1274
|
border-color: var(--error);
|
|
1263
1275
|
}
|
|
@@ -1899,6 +1911,12 @@
|
|
|
1899
1911
|
.whitespace-nowrap {
|
|
1900
1912
|
white-space: nowrap;
|
|
1901
1913
|
}
|
|
1914
|
+
.text-\[color\:var\(--description-list-details\,var\(--foreground\)\)\] {
|
|
1915
|
+
color: var(--description-list-details,var(--foreground));
|
|
1916
|
+
}
|
|
1917
|
+
.text-\[color\:var\(--description-list-term\,var\(--muted-foreground\)\)\] {
|
|
1918
|
+
color: var(--description-list-term,var(--muted-foreground));
|
|
1919
|
+
}
|
|
1902
1920
|
.text-\[var\(--toast-copy\,var\(--muted-foreground\)\)\] {
|
|
1903
1921
|
color: var(--toast-copy,var(--muted-foreground));
|
|
1904
1922
|
}
|
|
@@ -2364,6 +2382,9 @@
|
|
|
2364
2382
|
.\[--card-pad\:var\(--surface-pad-md\)\] {
|
|
2365
2383
|
--card-pad: var(--surface-pad-md);
|
|
2366
2384
|
}
|
|
2385
|
+
.\[--card-section-corner\:initial\] {
|
|
2386
|
+
--card-section-corner: initial;
|
|
2387
|
+
}
|
|
2367
2388
|
.\[--checkbox-color\:var\(--border\)\] {
|
|
2368
2389
|
--checkbox-color: var(--border);
|
|
2369
2390
|
}
|
|
@@ -2376,6 +2397,18 @@
|
|
|
2376
2397
|
.\[--checkbox-color\:var\(--primary\)\] {
|
|
2377
2398
|
--checkbox-color: var(--primary);
|
|
2378
2399
|
}
|
|
2400
|
+
.\[--description-list-details\:currentColor\] {
|
|
2401
|
+
--description-list-details: currentColor;
|
|
2402
|
+
}
|
|
2403
|
+
.\[--description-list-details\:initial\] {
|
|
2404
|
+
--description-list-details: initial;
|
|
2405
|
+
}
|
|
2406
|
+
.\[--description-list-term\:currentColor\] {
|
|
2407
|
+
--description-list-term: currentColor;
|
|
2408
|
+
}
|
|
2409
|
+
.\[--description-list-term\:initial\] {
|
|
2410
|
+
--description-list-term: initial;
|
|
2411
|
+
}
|
|
2379
2412
|
.\[--field-corner\:clamp\(var\(--radius\)-1000\*var\(--radius-step\,0px\)\,var\(--radius-field\,var\(--radius\)\)\,var\(--radius\)\+1000\*var\(--radius-step\,0px\)\)\] {
|
|
2380
2413
|
--field-corner: clamp(var(--radius) - 1000 * var(--radius-step,0px), var(--radius-field,var(--radius)), var(--radius) + 1000 * var(--radius-step,0px));
|
|
2381
2414
|
}
|
|
@@ -2616,6 +2649,9 @@
|
|
|
2616
2649
|
font-size: var(--text-xs);
|
|
2617
2650
|
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
2618
2651
|
}
|
|
2652
|
+
:is(.\*\:\[--card-section-corner\:max\(0px\,--theme\(--radius-lg\)-1px\)\] > *) {
|
|
2653
|
+
--card-section-corner: max(0px, var(--radius) - 1px);
|
|
2654
|
+
}
|
|
2619
2655
|
:is(.\*\*\:text-2xl *) {
|
|
2620
2656
|
font-size: var(--text-2xl);
|
|
2621
2657
|
line-height: var(--tw-leading, var(--text-2xl--line-height));
|
|
@@ -3318,6 +3354,9 @@
|
|
|
3318
3354
|
--tw-outline-style: none;
|
|
3319
3355
|
outline-style: none;
|
|
3320
3356
|
}
|
|
3357
|
+
.focus-visible\:ring-inset:is(:where([data-rac])[data-focus-visible], :where(:not([data-rac])):focus-visible) {
|
|
3358
|
+
--tw-ring-inset: inset;
|
|
3359
|
+
}
|
|
3321
3360
|
:is(.\*\:focus-visible\:relative > *):is(:where([data-rac])[data-focus-visible], :where(:not([data-rac])):focus-visible) {
|
|
3322
3361
|
position: relative;
|
|
3323
3362
|
}
|
|
@@ -3625,6 +3664,18 @@
|
|
|
3625
3664
|
.has-\[\>\[data-slot\=button-group\]\]\:gap-2:has( > [data-slot=button-group]) {
|
|
3626
3665
|
gap: calc(0.25rem * 2);
|
|
3627
3666
|
}
|
|
3667
|
+
.has-\[\>\[data-slot\=card-section-media\]\]\:grid:has( > [data-slot=card-section-media]) {
|
|
3668
|
+
display: grid;
|
|
3669
|
+
}
|
|
3670
|
+
.has-\[\>\[data-slot\=card-section-media\]\]\:grid-cols-\[auto_minmax\(0\,1fr\)\]:has( > [data-slot=card-section-media]) {
|
|
3671
|
+
grid-template-columns: auto minmax(0,1fr);
|
|
3672
|
+
}
|
|
3673
|
+
.has-\[\>\[data-slot\=card-section-media\]\]\:items-center:has( > [data-slot=card-section-media]) {
|
|
3674
|
+
align-items: center;
|
|
3675
|
+
}
|
|
3676
|
+
.has-\[\>\[data-slot\=card-section-media\]\]\:gap-x-\(--surface-gap-md\):has( > [data-slot=card-section-media]) {
|
|
3677
|
+
column-gap: var(--surface-gap-md);
|
|
3678
|
+
}
|
|
3628
3679
|
.has-\[\>\[data-slot\=checkbox-group\]\]\:gap-\(--surface-gap-md\):has( > [data-slot=checkbox-group]) {
|
|
3629
3680
|
gap: var(--surface-gap-md);
|
|
3630
3681
|
}
|
|
@@ -5034,6 +5085,9 @@
|
|
|
5034
5085
|
border-style: var(--tw-border-style);
|
|
5035
5086
|
border-width: 0px;
|
|
5036
5087
|
}
|
|
5088
|
+
.\[\&\+\&\]\:mt-\(--surface-gap-lg\) + .\[\&\+\&\]\:mt-\(--surface-gap-lg\) {
|
|
5089
|
+
margin-top: var(--surface-gap-lg);
|
|
5090
|
+
}
|
|
5037
5091
|
.\[\&\+\[data-slot\=item-content\]\]\:flex-none + [data-slot=item-content] {
|
|
5038
5092
|
flex: none;
|
|
5039
5093
|
}
|
|
@@ -5155,6 +5209,18 @@
|
|
|
5155
5209
|
background-color: color-mix(in oklab, var(--muted) 72%, transparent);
|
|
5156
5210
|
}
|
|
5157
5211
|
}
|
|
5212
|
+
.\[\&\:nth-child\(1_of_\:not\(\[hidden\]\)\)\]\:rounded-t-\[var\(--card-section-corner\,0px\)\]:nth-child(1 of :not([hidden])) {
|
|
5213
|
+
border-top-left-radius: var(--card-section-corner,0px);
|
|
5214
|
+
border-top-right-radius: var(--card-section-corner,0px);
|
|
5215
|
+
}
|
|
5216
|
+
.\[\&\:nth-child\(1_of_\:not\(\[hidden\]\)\)\]\:border-t-0:nth-child(1 of :not([hidden])) {
|
|
5217
|
+
border-top-style: var(--tw-border-style);
|
|
5218
|
+
border-top-width: 0px;
|
|
5219
|
+
}
|
|
5220
|
+
.\[\&\:nth-last-child\(1_of_\:not\(\[hidden\]\)\)\]\:rounded-b-\[var\(--card-section-corner\,0px\)\]:nth-last-child(1 of :not([hidden])) {
|
|
5221
|
+
border-bottom-right-radius: var(--card-section-corner,0px);
|
|
5222
|
+
border-bottom-left-radius: var(--card-section-corner,0px);
|
|
5223
|
+
}
|
|
5158
5224
|
.\[\&\>\.sr-only\]\:w-auto > .sr-only {
|
|
5159
5225
|
width: auto;
|
|
5160
5226
|
}
|
|
@@ -5316,6 +5382,9 @@
|
|
|
5316
5382
|
.\[\&\[data-ending-style\]\:not\(\[data-limited\]\)\:not\(\[data-swipe-direction\]\)\]\:\[transform\:translateY\(calc\(var\(--side\)\*150\%\)\)\][data-ending-style]:not([data-limited]):not([data-swipe-direction]) {
|
|
5317
5383
|
transform: translateY(calc(var(--side) * 150%));
|
|
5318
5384
|
}
|
|
5385
|
+
.\[\&\[hidden\]\:not\(\[hidden\=until-found\]\)\]\:hidden[hidden]:not([hidden=until-found]) {
|
|
5386
|
+
display: none;
|
|
5387
|
+
}
|
|
5319
5388
|
.\[\&\[readonly\]\:not\(\:disabled\)\]\:bg-muted[readonly]:not(:disabled) {
|
|
5320
5389
|
background-color: var(--muted);
|
|
5321
5390
|
}
|
|
@@ -5365,6 +5434,31 @@
|
|
|
5365
5434
|
:where(.\[\:where\(\&\>\*\)\]\:ring-background > *) {
|
|
5366
5435
|
--tw-ring-color: var(--background);
|
|
5367
5436
|
}
|
|
5437
|
+
:where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:col-start-2 {
|
|
5438
|
+
grid-column-start: 2;
|
|
5439
|
+
}
|
|
5440
|
+
:where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:min-w-0 {
|
|
5441
|
+
min-width: 0px;
|
|
5442
|
+
}
|
|
5443
|
+
:where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:border-none {
|
|
5444
|
+
--tw-border-style: none;
|
|
5445
|
+
border-style: none;
|
|
5446
|
+
}
|
|
5447
|
+
:where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:p-0 {
|
|
5448
|
+
padding: 0px;
|
|
5449
|
+
}
|
|
5450
|
+
:where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:py-0 {
|
|
5451
|
+
padding-block: 0px;
|
|
5452
|
+
}
|
|
5453
|
+
:where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:text-end {
|
|
5454
|
+
text-align: end;
|
|
5455
|
+
}
|
|
5456
|
+
:where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:wrap-anywhere {
|
|
5457
|
+
overflow-wrap: anywhere;
|
|
5458
|
+
}
|
|
5459
|
+
:where([data-slot=card-section]) > .\[\:where\(\[data-slot\=card-section\]\)\>\&\]\:p-0 {
|
|
5460
|
+
padding: 0px;
|
|
5461
|
+
}
|
|
5368
5462
|
[data-placement] > .\[\[data-placement\]\>\&\]\:p-0 {
|
|
5369
5463
|
padding: 0px;
|
|
5370
5464
|
}
|
package/themes.css
CHANGED
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
--input: oklch(0.9219 0 0);
|
|
81
81
|
--ring: oklch(0.6 0 0);
|
|
82
82
|
--card-border: var(--border);
|
|
83
|
+
--card-section-divider: var(--border);
|
|
83
84
|
--button-outline: var(--border);
|
|
84
85
|
--selection-border: var(--border);
|
|
85
86
|
--selection-checked-border: var(--primary);
|
|
@@ -201,6 +202,7 @@
|
|
|
201
202
|
--input: oklch(0.9219 0 0);
|
|
202
203
|
--ring: oklch(0.6 0 0);
|
|
203
204
|
--card-border: var(--border);
|
|
205
|
+
--card-section-divider: var(--border);
|
|
204
206
|
--button-outline: var(--border);
|
|
205
207
|
--selection-border: var(--border);
|
|
206
208
|
--selection-checked-border: var(--primary);
|
|
@@ -247,6 +249,7 @@
|
|
|
247
249
|
--input: oklch(0.9232 0.0026 48.72);
|
|
248
250
|
--ring: oklch(0.6 0 0);
|
|
249
251
|
--card-border: oklch(0 0 0 / 0);
|
|
252
|
+
--card-section-divider: var(--background);
|
|
250
253
|
--button-outline: var(--foreground);
|
|
251
254
|
--selection-border: oklch(0 0 0 / 0);
|
|
252
255
|
--selection-checked-border: var(--selection-border);
|
|
@@ -313,6 +316,7 @@
|
|
|
313
316
|
--input: oklch(0.929 0.0126 255.53);
|
|
314
317
|
--ring: oklch(0.6 0 0);
|
|
315
318
|
--card-border: oklch(0 0 0 / 0);
|
|
319
|
+
--card-section-divider: var(--background);
|
|
316
320
|
--button-outline: var(--foreground);
|
|
317
321
|
--selection-border: oklch(0 0 0 / 0);
|
|
318
322
|
--selection-checked-border: var(--selection-border);
|
|
@@ -359,6 +363,7 @@
|
|
|
359
363
|
--input: oklch(0.929 0.0126 255.53);
|
|
360
364
|
--ring: oklch(0.6 0 0);
|
|
361
365
|
--card-border: oklch(0 0 0 / 0);
|
|
366
|
+
--card-section-divider: var(--background);
|
|
362
367
|
--button-outline: var(--foreground);
|
|
363
368
|
--selection-border: oklch(0 0 0 / 0);
|
|
364
369
|
--selection-checked-border: var(--selection-border);
|
|
@@ -405,6 +410,7 @@
|
|
|
405
410
|
--input: oklch(0.9232 0.0026 48.72);
|
|
406
411
|
--ring: oklch(0.6 0 0);
|
|
407
412
|
--card-border: oklch(0 0 0 / 0);
|
|
413
|
+
--card-section-divider: var(--background);
|
|
408
414
|
--button-outline: var(--foreground);
|
|
409
415
|
--selection-border: oklch(0 0 0 / 0);
|
|
410
416
|
--selection-checked-border: var(--selection-border);
|
|
@@ -451,6 +457,7 @@
|
|
|
451
457
|
--input: oklch(0.9232 0.0026 48.72);
|
|
452
458
|
--ring: oklch(0.6 0 0);
|
|
453
459
|
--card-border: oklch(0 0 0 / 0);
|
|
460
|
+
--card-section-divider: var(--background);
|
|
454
461
|
--button-outline: var(--foreground);
|
|
455
462
|
--selection-border: oklch(0 0 0 / 0);
|
|
456
463
|
--selection-checked-border: var(--selection-border);
|
|
@@ -497,6 +504,7 @@
|
|
|
497
504
|
--input: oklch(0.9219 0 0);
|
|
498
505
|
--ring: oklch(0.6 0 0);
|
|
499
506
|
--card-border: oklch(0 0 0 / 0);
|
|
507
|
+
--card-section-divider: var(--background);
|
|
500
508
|
--button-outline: var(--foreground);
|
|
501
509
|
--selection-border: oklch(0 0 0 / 0);
|
|
502
510
|
--selection-checked-border: var(--selection-border);
|
|
@@ -543,6 +551,7 @@
|
|
|
543
551
|
--input: oklch(0.8256644 0.0145962 162.3965393);
|
|
544
552
|
--ring: oklch(0.6 0 0);
|
|
545
553
|
--card-border: oklch(0 0 0 / 0);
|
|
554
|
+
--card-section-divider: var(--background);
|
|
546
555
|
--button-outline: var(--foreground);
|
|
547
556
|
--selection-border: oklch(0 0 0 / 0);
|
|
548
557
|
--selection-checked-border: var(--selection-border);
|
|
@@ -612,6 +621,7 @@
|
|
|
612
621
|
--input: oklch(1 0 0 / 40%);
|
|
613
622
|
--ring: oklch(0.6 0 0);
|
|
614
623
|
--card-border: var(--border);
|
|
624
|
+
--card-section-divider: var(--border);
|
|
615
625
|
--button-outline: var(--border);
|
|
616
626
|
--selection-border: var(--border);
|
|
617
627
|
--selection-checked-border: var(--primary);
|
|
@@ -747,6 +757,7 @@
|
|
|
747
757
|
--input: oklch(0.6543689 0.0037291 145.5328);
|
|
748
758
|
--ring: oklch(0.6 0 0);
|
|
749
759
|
--card-border: oklch(0 0 0 / 0);
|
|
760
|
+
--card-section-divider: var(--background);
|
|
750
761
|
--button-outline: var(--foreground);
|
|
751
762
|
--selection-border: oklch(0 0 0 / 0);
|
|
752
763
|
--selection-checked-border: var(--selection-border);
|
|
@@ -846,6 +857,7 @@
|
|
|
846
857
|
--input: oklch(0.6543689 0.0037291 145.5328);
|
|
847
858
|
--ring: oklch(0.6 0 0);
|
|
848
859
|
--card-border: oklch(0 0 0 / 0);
|
|
860
|
+
--card-section-divider: var(--background);
|
|
849
861
|
--button-outline: var(--foreground);
|
|
850
862
|
--selection-border: oklch(0 0 0 / 0);
|
|
851
863
|
--selection-checked-border: var(--selection-border);
|
|
@@ -945,6 +957,7 @@
|
|
|
945
957
|
--input: oklch(0.6543689 0.0037291 145.5328);
|
|
946
958
|
--ring: oklch(0.6 0 0);
|
|
947
959
|
--card-border: oklch(0 0 0 / 0);
|
|
960
|
+
--card-section-divider: var(--background);
|
|
948
961
|
--button-outline: var(--foreground);
|
|
949
962
|
--selection-border: oklch(0 0 0 / 0);
|
|
950
963
|
--selection-checked-border: var(--selection-border);
|
|
@@ -1044,6 +1057,7 @@
|
|
|
1044
1057
|
--input: oklch(0.6543689 0.0037291 145.5328);
|
|
1045
1058
|
--ring: oklch(0.6 0 0);
|
|
1046
1059
|
--card-border: oklch(0 0 0 / 0);
|
|
1060
|
+
--card-section-divider: var(--background);
|
|
1047
1061
|
--button-outline: var(--foreground);
|
|
1048
1062
|
--selection-border: oklch(0 0 0 / 0);
|
|
1049
1063
|
--selection-checked-border: var(--selection-border);
|
|
@@ -1143,6 +1157,7 @@
|
|
|
1143
1157
|
--input: oklch(0.6543689 0.0037291 145.5328);
|
|
1144
1158
|
--ring: oklch(0.6 0 0);
|
|
1145
1159
|
--card-border: oklch(0 0 0 / 0);
|
|
1160
|
+
--card-section-divider: var(--background);
|
|
1146
1161
|
--button-outline: var(--foreground);
|
|
1147
1162
|
--selection-border: oklch(0 0 0 / 0);
|
|
1148
1163
|
--selection-checked-border: var(--selection-border);
|
|
@@ -1242,6 +1257,7 @@
|
|
|
1242
1257
|
--input: oklch(0.6543689 0.0037291 145.5328);
|
|
1243
1258
|
--ring: oklch(0.6 0 0);
|
|
1244
1259
|
--card-border: oklch(0 0 0 / 0);
|
|
1260
|
+
--card-section-divider: var(--background);
|
|
1245
1261
|
--button-outline: var(--foreground);
|
|
1246
1262
|
--selection-border: oklch(0 0 0 / 0);
|
|
1247
1263
|
--selection-checked-border: var(--selection-border);
|
|
@@ -1341,6 +1357,7 @@
|
|
|
1341
1357
|
--input: oklch(0.6543689 0.0037291 145.5328);
|
|
1342
1358
|
--ring: oklch(0.6 0 0);
|
|
1343
1359
|
--card-border: oklch(0 0 0 / 0);
|
|
1360
|
+
--card-section-divider: var(--background);
|
|
1344
1361
|
--button-outline: var(--foreground);
|
|
1345
1362
|
--selection-border: oklch(0 0 0 / 0);
|
|
1346
1363
|
--selection-checked-border: var(--selection-border);
|
|
@@ -1440,6 +1457,7 @@
|
|
|
1440
1457
|
--input: oklch(0.6543689 0.0037291 145.5328);
|
|
1441
1458
|
--ring: oklch(0.6 0 0);
|
|
1442
1459
|
--card-border: oklch(0 0 0 / 0);
|
|
1460
|
+
--card-section-divider: var(--background);
|
|
1443
1461
|
--button-outline: var(--foreground);
|
|
1444
1462
|
--selection-border: oklch(0 0 0 / 0);
|
|
1445
1463
|
--selection-checked-border: var(--selection-border);
|