@supertype.ai/foundations 0.1.31 → 0.1.32
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 +1 -1
- package/dist/blocks/button.js +1 -1
- package/dist/blocks/callout.js +6 -2
- package/dist/typography/paragraph.d.ts +9 -2
- package/dist/typography/paragraph.js +9 -2
- package/package.json +1 -1
- package/src/type.css +30 -0
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ untagged git dependency resolves to a different commit on a fresh install.
|
|
|
66
66
|
|
|
67
67
|
```jsonc
|
|
68
68
|
// package.json
|
|
69
|
-
"@supertype.ai/foundations": "https://github.com/supertypeai/foundations.git#v0.1.
|
|
69
|
+
"@supertype.ai/foundations": "https://github.com/supertypeai/foundations.git#v0.1.32"
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
</details>
|
package/dist/blocks/button.js
CHANGED
|
@@ -62,7 +62,7 @@ cn(FOCUS_RING, "focus-visible:border-ring"), "active:not-aria-[haspopup]:transla
|
|
|
62
62
|
variant: {
|
|
63
63
|
solid: `bg-(--tone-fill) text-(color:--tone-ink) hover:bg-(--tone-fill-hover) ${INK_ON_FILL}`,
|
|
64
64
|
soft: "bg-(--tone-wash) text-(color:--tone-hue) hover:bg-(--tone-wash-hover)",
|
|
65
|
-
outline: "border-(color:--tone-line)
|
|
65
|
+
outline: "border-(color:--tone-line) text-(color:--tone-hue) hover:bg-(--tone-wash)",
|
|
66
66
|
ghost: "text-(color:--tone-hue) hover:bg-(--tone-wash)",
|
|
67
67
|
// No box of its own: a button that reads as a link has to sit on the
|
|
68
68
|
// text baseline, not on a 32px control's centre line.
|
package/dist/blocks/callout.js
CHANGED
|
@@ -12,6 +12,10 @@ import { TypographyCaption, TypographyLabel, TypographyMuted, TypographySmall, }
|
|
|
12
12
|
// already drifted on the radius. Hand-rolled type styles are also exactly what the project's own
|
|
13
13
|
// guidance forbids, and six copies is how a rule like that gets broken without anyone deciding to.
|
|
14
14
|
//
|
|
15
|
+
// The body is a slot, so it renders as a div in both densities. A caller passes a list, a
|
|
16
|
+
// pair of paragraphs or a mono block of delivery errors, none of which may sit inside a <p>:
|
|
17
|
+
// the parser closes it early and React reports a hydration error on a callout that looks fine.
|
|
18
|
+
//
|
|
15
19
|
// Deliberately not a shadcn Alert. Alert is a page-level, role="alert" affordance for something
|
|
16
20
|
// that just happened; these are quiet, permanent explanations sitting inside a panel, and they
|
|
17
21
|
// must not announce themselves to a screen reader every time a sheet opens.
|
|
@@ -30,7 +34,7 @@ const BOX = "border-(color:--tone-line) bg-(--tone-veil)";
|
|
|
30
34
|
export function Callout({ icon: Icon, title, tone = "muted", density = "compact", bodyClassName, action, children, className, }) {
|
|
31
35
|
const toned = toneClass(tone);
|
|
32
36
|
if (density === "editorial") {
|
|
33
|
-
return (_jsxs("div", { className: cn("relative overflow-hidden rounded-lg border py-3.5 pl-5 pr-4", toned, BOX, className), children: [_jsx("span", { "aria-hidden": true, className: "absolute inset-y-0 left-0 w-[3px] bg-(--tone-line)" }), _jsxs("div", { className: "flex items-start gap-2.5", children: [Icon && (_jsx(Icon, { className: "mt-0.5 size-4 shrink-0 text-(color:--tone-hue)" })), _jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [title && (_jsx(TypographyLabel, { className: "text-(color:--tone-hue)", children: title })), _jsx(TypographyMuted, { className: cn("leading-relaxed", bodyClassName), children: children }), action && (_jsx("div", { className: "mt-1 flex items-center gap-1", children: action }))] })] })] }));
|
|
37
|
+
return (_jsxs("div", { className: cn("relative overflow-hidden rounded-lg border py-3.5 pl-5 pr-4", toned, BOX, className), children: [_jsx("span", { "aria-hidden": true, className: "absolute inset-y-0 left-0 w-[3px] bg-(--tone-line)" }), _jsxs("div", { className: "flex items-start gap-2.5", children: [Icon && (_jsx(Icon, { className: "mt-0.5 size-4 shrink-0 text-(color:--tone-hue)" })), _jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [title && (_jsx(TypographyLabel, { className: "text-(color:--tone-hue)", children: title })), _jsx(TypographyMuted, { as: "div", className: cn("leading-relaxed", bodyClassName), children: children }), action && (_jsx("div", { className: "mt-1 flex items-center gap-1", children: action }))] })] })] }));
|
|
34
38
|
}
|
|
35
|
-
return (_jsxs("div", { className: cn("rounded-md border p-3", toned, BOX, className), children: [title && (_jsxs(TypographySmall, { className: "flex items-center gap-1.5 font-medium text-(color:--tone-hue)", children: [Icon && _jsx(Icon, { className: "size-3.5 shrink-0" }), title] })), _jsx(TypographyCaption, { className: cn("mt-1
|
|
39
|
+
return (_jsxs("div", { className: cn("rounded-md border p-3", toned, BOX, className), children: [title && (_jsxs(TypographySmall, { className: "flex items-center gap-1.5 font-medium text-(color:--tone-hue)", children: [Icon && _jsx(Icon, { className: "size-3.5 shrink-0" }), title] })), _jsx(TypographyCaption, { as: "div", className: cn("mt-1 leading-relaxed", bodyClassName), children: children }), action && _jsx("div", { className: "mt-2 flex items-center gap-1", children: action })] }));
|
|
36
40
|
}
|
|
@@ -11,12 +11,19 @@ declare const pVariants: (props?: ({
|
|
|
11
11
|
tone?: "muted" | "default" | null | undefined;
|
|
12
12
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
13
|
export type ParagraphVariants = VariantProps<typeof pVariants>;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* `as` is here for the reason the caption has it, one step further on: a
|
|
16
|
+
* component that hands its body to a caller cannot know whether what arrives is
|
|
17
|
+
* a sentence or a list, and a paragraph may hold neither a list nor a div. The
|
|
18
|
+
* HTML parser closes the `<p>` early and React reports a hydration error, so
|
|
19
|
+
* every wrapper of that shape (`Callout` was the one) renders `as="div"`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function TypographyP({ className, variant, tone, as, children, ...props }: WithAs<ParagraphVariants>): import("react").JSX.Element;
|
|
15
22
|
/** A preset's props: its base's, minus the axes it has decided. `keyof Pins` reads
|
|
16
23
|
* the exclusion off the pinned object the preset also spreads, so the two cannot
|
|
17
24
|
* drift — `<TypographyMuted tone="default">` used to compile and un-mute it. */
|
|
18
25
|
type Preset<Base, Pins> = Omit<Base, keyof Pins>;
|
|
19
|
-
type ParagraphProps =
|
|
26
|
+
type ParagraphProps = WithAs<ParagraphVariants>;
|
|
20
27
|
/** The UI rung in the secondary ink. */
|
|
21
28
|
declare const MUTED: {
|
|
22
29
|
readonly tone: "muted";
|
|
@@ -25,8 +25,15 @@ const pVariants = cva("", {
|
|
|
25
25
|
},
|
|
26
26
|
defaultVariants: { variant: "ui", tone: "default" },
|
|
27
27
|
});
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* `as` is here for the reason the caption has it, one step further on: a
|
|
30
|
+
* component that hands its body to a caller cannot know whether what arrives is
|
|
31
|
+
* a sentence or a list, and a paragraph may hold neither a list nor a div. The
|
|
32
|
+
* HTML parser closes the `<p>` early and React reports a hydration error, so
|
|
33
|
+
* every wrapper of that shape (`Callout` was the one) renders `as="div"`.
|
|
34
|
+
*/
|
|
35
|
+
export function TypographyP({ className, variant, tone, as = "p", children, ...props }) {
|
|
36
|
+
return (_jsx(TextAs, { as: as, className: cn(pVariants({ variant, tone }), className), ...props, children: children }));
|
|
30
37
|
}
|
|
31
38
|
/** The UI rung in the secondary ink. */
|
|
32
39
|
const MUTED = { tone: "muted" };
|
package/package.json
CHANGED
package/src/type.css
CHANGED
|
@@ -71,3 +71,33 @@
|
|
|
71
71
|
.editorial.font-heading {
|
|
72
72
|
font-weight: var(--heading-weight);
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
/* A glyph set beside words, sized and seated so it belongs to the line.
|
|
76
|
+
|
|
77
|
+
Two numbers, both read off the font rather than chosen. Lucide draws its ink
|
|
78
|
+
across 22 of its 24 grid units, so a 0.8em box puts that ink at 1.02 times the
|
|
79
|
+
cap height of whatever rung it sits beside.
|
|
80
|
+
|
|
81
|
+
The seat corrects a bias the browser introduces. Centring aligns a glyph on the
|
|
82
|
+
middle of the line box, and the line box is built from the font's ascent and
|
|
83
|
+
descent rounded to whole pixels, which lands its middle below the middle of the
|
|
84
|
+
capitals: 0.31px low at the 11px rung, 0.46px at the 10px, 0.50px at the 13px.
|
|
85
|
+
So a centred glyph is always seated slightly low, by an amount that changes with
|
|
86
|
+
the rung, which is why hand nudges get written one place at a time and never
|
|
87
|
+
generalise. Lifting by 0.035em takes it back onto the cap band across the ramp.
|
|
88
|
+
|
|
89
|
+
A box pinned in pixels cannot hold the first number either, because the band it
|
|
90
|
+
has to match moves with the rung. Twelve pixels is 1.39 times the cap height at
|
|
91
|
+
the 11px rung and 1.53 at the 10px one, so the glyph climbs over the ascenders
|
|
92
|
+
and hangs well under the baseline while every letter beside it rests on it.
|
|
93
|
+
|
|
94
|
+
For a glyph inline with words. A glyph that stands alone, in a button, a nav
|
|
95
|
+
rail or an avatar slot, has no band to answer to and keeps a fixed size.
|
|
96
|
+
|
|
97
|
+
The 22-of-24 figure is lucide's grid. An app on a different icon set wants a
|
|
98
|
+
different box for the same ratio. */
|
|
99
|
+
@utility icon-inline {
|
|
100
|
+
width: 0.8em;
|
|
101
|
+
height: 0.8em;
|
|
102
|
+
translate: 0 -0.035em;
|
|
103
|
+
}
|