@hackcove/ui-react 0.8.1 → 0.8.2

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.
@@ -5,7 +5,7 @@ export type PageHeaderProps = {
5
5
  breadcrumbs?: ReactNode;
6
6
  /** The page's `h1`. */
7
7
  title: ReactNode;
8
- /** A muted line under the title. */
8
+ /** The lede under the title: a `Lead`, so it outranks the body text after it. */
9
9
  subtitle?: ReactNode;
10
10
  /** Right of the title on `sm` and up, below it on a phone. */
11
11
  actions?: ReactNode;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { HeaderText, PageHeading } from "./typography.js";
2
+ import { Lead, PageHeading } from "./typography.js";
3
3
  /** The header block without its bottom margin; PageHeader adds the margin (a `Stack` child drops it). */
4
4
  export function PageHeaderContent({ breadcrumbs, title, subtitle, actions, tabs, className, ...rest }) {
5
- return (_jsxs("div", { ...rest, "data-page-header": "", className: className, children: [breadcrumbs && _jsx("div", { className: "mb-2", children: breadcrumbs }), _jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { className: "min-w-0", children: [_jsx(PageHeading, { children: title }), subtitle && (_jsx("div", { className: "mt-1", children: _jsx(HeaderText, { children: subtitle }) }))] }), actions && _jsx("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: actions })] }), tabs && _jsx("div", { className: "mt-4", children: tabs })] }));
5
+ return (_jsxs("div", { ...rest, "data-page-header": "", className: className, children: [breadcrumbs && _jsx("div", { className: "mb-2", children: breadcrumbs }), _jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { className: "min-w-0", children: [_jsx(PageHeading, { children: title }), subtitle && (_jsx("div", { className: "mt-2 max-w-[60ch]", children: _jsx(Lead, { children: subtitle }) }))] }), actions && _jsx("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: actions })] }), tabs && _jsx("div", { className: "mt-4", children: tabs })] }));
6
6
  }
7
7
  /**
8
8
  * The top of a page: breadcrumbs, title, subtitle, actions and tabs. Its fixed bottom margin puts
@@ -25,17 +25,25 @@ export declare function FormLayout({ actions, children, breadcrumbs, title, subt
25
25
  children: ReactNode;
26
26
  } & Unstyled<Omit<ComponentPropsWithoutRef<"form">, "title">>): ReactElement;
27
27
  /**
28
- * A text page: header, then `children` stacked `gap` apart (`md` by default), all in one `narrow`
29
- * (`max-w-3xl`) reading column that starts at the Container's left edge (it is not re-centred, so
30
- * the title does not jump). Unlike `FormLayout` the header sits inside the column, so its `actions`
31
- * stay beside the text instead of at the Container's far edge.
28
+ * A text page: header, then `children` stacked `gap` apart (`md` by default), all in one column that
29
+ * starts at the Container's left edge (it is not re-centred, so the title does not jump). `width`
30
+ * sets the column: `narrow` (`max-w-3xl`, the default) is a reading measure; `wide` (`max-w-5xl`) and
31
+ * `full` (the Container's whole width) suit a page that is not long prose, such as a pricing page.
32
+ * Paragraphs (`Text`) and the header's lede keep their own reading measure whatever the width.
33
+ * Unlike `FormLayout` the header sits inside the column, so its `actions` stay beside the text
34
+ * instead of at the Container's far edge.
32
35
  */
33
- export declare function ProseLayout({ gap, children, breadcrumbs, title, subtitle, actions, tabs, ...rest }: PageHeaderProps & {
36
+ export declare function ProseLayout({ width, gap, children, breadcrumbs, title, subtitle, actions, tabs, ...rest }: PageHeaderProps & {
34
37
  /**
35
38
  * The space between blocks: `xs` gap-2, `sm` gap-4, `md` gap-6, `lg` gap-8, `xl` gap-12 (gap-16 from `sm`).
36
39
  * @default md
37
40
  */
38
41
  gap?: StackGap | undefined;
42
+ /**
43
+ * The column's width: `narrow` max-w-3xl, `wide` max-w-5xl, `full` the Container's width.
44
+ * @default narrow
45
+ */
46
+ width?: "narrow" | "wide" | "full" | undefined;
39
47
  children?: ReactNode;
40
48
  } & Passthrough): ReactElement;
41
49
  declare const COLUMNS: {
@@ -20,13 +20,16 @@ export function FormLayout({ actions, children, breadcrumbs, title, subtitle, ta
20
20
  return (_jsxs(_Fragment, { children: [_jsx(PageHeader, { breadcrumbs: breadcrumbs, title: title, subtitle: subtitle, tabs: tabs }), _jsx("form", { ...form, className: "max-w-3xl", children: _jsxs(Stack, { children: [children, actions && _jsx("div", { className: "flex flex-wrap items-center gap-2", children: actions })] }) })] }));
21
21
  }
22
22
  /**
23
- * A text page: header, then `children` stacked `gap` apart (`md` by default), all in one `narrow`
24
- * (`max-w-3xl`) reading column that starts at the Container's left edge (it is not re-centred, so
25
- * the title does not jump). Unlike `FormLayout` the header sits inside the column, so its `actions`
26
- * stay beside the text instead of at the Container's far edge.
23
+ * A text page: header, then `children` stacked `gap` apart (`md` by default), all in one column that
24
+ * starts at the Container's left edge (it is not re-centred, so the title does not jump). `width`
25
+ * sets the column: `narrow` (`max-w-3xl`, the default) is a reading measure; `wide` (`max-w-5xl`) and
26
+ * `full` (the Container's whole width) suit a page that is not long prose, such as a pricing page.
27
+ * Paragraphs (`Text`) and the header's lede keep their own reading measure whatever the width.
28
+ * Unlike `FormLayout` the header sits inside the column, so its `actions` stay beside the text
29
+ * instead of at the Container's far edge.
27
30
  */
28
- export function ProseLayout({ gap = "md", children, breadcrumbs, title, subtitle, actions, tabs, ...rest }) {
29
- return (_jsxs("div", { ...rest, className: STACK_WIDTH.narrow, children: [_jsx(PageHeader, { breadcrumbs: breadcrumbs, title: title, subtitle: subtitle, actions: actions, tabs: tabs }), _jsx(Stack, { gap: gap, children: children })] }));
31
+ export function ProseLayout({ width = "narrow", gap = "md", children, breadcrumbs, title, subtitle, actions, tabs, ...rest }) {
32
+ return (_jsxs("div", { ...rest, className: STACK_WIDTH[width], children: [_jsx(PageHeader, { breadcrumbs: breadcrumbs, title: title, subtitle: subtitle, actions: actions, tabs: tabs }), _jsx(Stack, { gap: gap, children: children })] }));
30
33
  }
31
34
  const COLUMNS = {
32
35
  2: "lg:grid-cols-2",
@@ -43,9 +43,8 @@ export type InlineTypographyProps<E extends ElementType> = Own & {
43
43
  /**
44
44
  * Marketing-scale headline — the one line at the top of a public page. `h1`,
45
45
  * text-4xl/tight semibold, primary text, growing to text-6xl on wider screens.
46
- * `PageHeading`'s scale is deliberately dev-tool sized; a brochure
47
- * hero needs a display scale, so it gets its own pinned role rather than callers
48
- * overriding PageHeading's size.
46
+ * `PageHeading` is the title of an ordinary page, a step below; a brochure hero needs a display
47
+ * scale, so it gets its own pinned role rather than callers overriding PageHeading's size.
49
48
  */
50
49
  export declare const Display: {
51
50
  <E extends ElementType = "h1">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -56,7 +55,10 @@ export declare const Lead: {
56
55
  <E extends ElementType = "p">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
57
56
  displayName: string;
58
57
  };
59
- /** Page title. `h1`, text-2xl/8 semibold, primary text. */
58
+ /**
59
+ * Page title. `h1`, text-3xl/9 bold (text-4xl/10 from `sm`), tight, primary text: well above the
60
+ * `Lead` under it and the body text after it, so the page's title reads first.
61
+ */
60
62
  export declare const PageHeading: {
61
63
  <E extends ElementType = "h1">(props: TypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
62
64
  displayName: string;
@@ -109,8 +111,8 @@ export declare function Text<E extends ElementType = "span">({ strong, preserveN
109
111
  preserveNewlines?: boolean;
110
112
  }): ReactElement;
111
113
  /**
112
- * The supporting line under a `PageHeader` or `Dialog` title: `Text as="p"` without the measure, so
113
- * it runs the width of its header. Internal; not exported from the package.
114
+ * The supporting line under a `Dialog` title: `Text as="p"` without the measure, so
115
+ * it runs the width of its dialog. Internal; not exported from the package.
114
116
  */
115
117
  export declare function HeaderText({ children }: {
116
118
  children: ReactNode;
@@ -57,15 +57,17 @@ function plainText(children) {
57
57
  /**
58
58
  * Marketing-scale headline — the one line at the top of a public page. `h1`,
59
59
  * text-4xl/tight semibold, primary text, growing to text-6xl on wider screens.
60
- * `PageHeading`'s scale is deliberately dev-tool sized; a brochure
61
- * hero needs a display scale, so it gets its own pinned role rather than callers
62
- * overriding PageHeading's size.
60
+ * `PageHeading` is the title of an ordinary page, a step below; a brochure hero needs a display
61
+ * scale, so it gets its own pinned role rather than callers overriding PageHeading's size.
63
62
  */
64
63
  export const Display = typography("Display", "h1", "text-4xl/[1.1] font-semibold tracking-tight sm:text-5xl/[1.05] lg:text-6xl/[1.05]", "default");
65
64
  /** The supporting sentence under a `Display`. `p`, text-lg/7 normal, secondary. */
66
65
  export const Lead = typography("Lead", "p", "text-lg/7 font-normal sm:text-xl/8", "secondary");
67
- /** Page title. `h1`, text-2xl/8 semibold, primary text. */
68
- export const PageHeading = typography("PageHeading", "h1", "text-2xl/8 font-semibold tracking-tight", "default");
66
+ /**
67
+ * Page title. `h1`, text-3xl/9 bold (text-4xl/10 from `sm`), tight, primary text: well above the
68
+ * `Lead` under it and the body text after it, so the page's title reads first.
69
+ */
70
+ export const PageHeading = typography("PageHeading", "h1", "text-3xl/9 font-bold tracking-tight sm:text-4xl/10", "default");
69
71
  /**
70
72
  * Top-level section header. `h2`, text-base/6 semibold, primary text. `rule` sets
71
73
  * a hairline under it (the `Divider` line colour) with the space either side of
@@ -107,8 +109,8 @@ export function Text({ strong, preserveNewlines, ...props }) {
107
109
  return pinned("span", textVariant(strong, preserveNewlines, true), strong ? "default" : "secondary", props);
108
110
  }
109
111
  /**
110
- * The supporting line under a `PageHeader` or `Dialog` title: `Text as="p"` without the measure, so
111
- * it runs the width of its header. Internal; not exported from the package.
112
+ * The supporting line under a `Dialog` title: `Text as="p"` without the measure, so
113
+ * it runs the width of its dialog. Internal; not exported from the package.
112
114
  */
113
115
  export function HeaderText({ children }) {
114
116
  return pinned("p", textVariant(false, false, false), "secondary", { children });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hackcove/ui-react",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "description": "Hack Cove React components: primitives, typography roles and a safe Markdown renderer, written against Tailwind v4 utilities. Pair with a @hackcove/theme-* package.",
5
5
  "keywords": [
6
6
  "components",