@recursica/adapter-mui-v7 1.3.0 → 1.3.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.
- package/CHANGELOG.md +12 -0
- package/dist/adapter-mui-v7.cjs +60 -60
- package/dist/adapter-mui-v7.cjs.map +1 -1
- package/dist/adapter-mui-v7.css +1 -1
- package/dist/adapter-mui-v7.js +2879 -2855
- package/dist/adapter-mui-v7.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Card/Card.stories.tsx +2 -1
- package/src/components/Slider/Slider.module.css +11 -0
- package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +10 -0
- package/src/components/Text/Text.stories.tsx +16 -17
- package/src/components/Text/Text.tsx +9 -0
- package/src/components/Typography/Typography.module.css +8 -0
- package/src/utils/typographyClass.ts +38 -0
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"type": "git",
|
|
13
13
|
"url": "git+https://github.com/borderux/recursica-adapter-mui-v7.git"
|
|
14
14
|
},
|
|
15
|
-
"version": "1.3.
|
|
15
|
+
"version": "1.3.2",
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"vitest": "^3.2.4"
|
|
123
123
|
},
|
|
124
124
|
"dependencies": {
|
|
125
|
-
"@recursica/adapter-common": "^1.
|
|
125
|
+
"@recursica/adapter-common": "^1.2.0",
|
|
126
126
|
"@recursica/official-release": "^2.8.0",
|
|
127
127
|
"dayjs": "^1.11.21"
|
|
128
128
|
},
|
|
@@ -3,6 +3,7 @@ import { Card } from "./Card";
|
|
|
3
3
|
import { Layer } from "@recursica/adapter-common";
|
|
4
4
|
import { Button } from "../Button/Button";
|
|
5
5
|
import { Group } from "../Group/Group";
|
|
6
|
+
import { Heading } from "../Heading/Heading";
|
|
6
7
|
import { Text } from "../Text/Text";
|
|
7
8
|
|
|
8
9
|
const meta: Meta<typeof Card> = {
|
|
@@ -78,7 +79,7 @@ export const HeaderlessAndFooterless: Story = {
|
|
|
78
79
|
<Layer layer={0}>
|
|
79
80
|
<Card {...args}>
|
|
80
81
|
<Card.Content>
|
|
81
|
-
<
|
|
82
|
+
<Heading order={6}>Notice</Heading>
|
|
82
83
|
<Text>
|
|
83
84
|
This is a completely generic card payload dropping the Header
|
|
84
85
|
and Footer specific elements, simply acting as a padded
|
|
@@ -74,6 +74,8 @@
|
|
|
74
74
|
|
|
75
75
|
.sliderRoot {
|
|
76
76
|
width: 100%;
|
|
77
|
+
/* MUI defaults the root to 4px, so the thumb overflows and the block collapses; match the thumb height. */
|
|
78
|
+
height: var(--recursica_ui-kit_components_slider_properties_thumb-size);
|
|
77
79
|
box-sizing: border-box;
|
|
78
80
|
color: inherit;
|
|
79
81
|
font-family: inherit;
|
|
@@ -84,6 +86,7 @@
|
|
|
84
86
|
|
|
85
87
|
.sliderTrack {
|
|
86
88
|
height: var(--recursica_ui-kit_components_slider_properties_track-height);
|
|
89
|
+
opacity: 1; /* MUI fades the rail to 0.38 by default, which washes out the token color */
|
|
87
90
|
border-radius: var(
|
|
88
91
|
--recursica_ui-kit_components_slider_properties_track-border-radius
|
|
89
92
|
);
|
|
@@ -249,6 +252,14 @@
|
|
|
249
252
|
display: flex !important;
|
|
250
253
|
align-items: center !important;
|
|
251
254
|
justify-content: center !important;
|
|
255
|
+
|
|
256
|
+
/* The transform override above defeats MUI's scale(0) hiding, so hide until MUI marks it open. */
|
|
257
|
+
opacity: 0;
|
|
258
|
+
pointer-events: none;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.sliderTooltip:global(.MuiSlider-valueLabelOpen) {
|
|
262
|
+
opacity: 1;
|
|
252
263
|
}
|
|
253
264
|
|
|
254
265
|
.sliderTooltip * {
|
|
@@ -8,3 +8,13 @@ visibly more vertical space between each item in mui's render. Not a component b
|
|
|
8
8
|
itself has no opinion on inter-item spacing; the gap is entirely owned by each story's own
|
|
9
9
|
`<div style={{ display: "flex", flexDirection: "column", gap }}>` wrapper. Fixed by changing the
|
|
10
10
|
story's `gap` to `"16px"` to match mantine's.
|
|
11
|
+
|
|
12
|
+
## Removed `body-small`, `subtitle`, `subtitle-small` variants; dev-only missing-style check
|
|
13
|
+
|
|
14
|
+
Forge only exports `h1`-`h6`, `body`, `caption` and `overline`; the three removed variants produced
|
|
15
|
+
a class matching no CSS rule. Any style under `brand.typography` still works by name (`TextVariant`
|
|
16
|
+
accepts any string since `@recursica/adapter-common` 1.2.0). In development, `Text` checks
|
|
17
|
+
`document.styleSheets` (`src/utils/typographyClass.ts`) for `.recursica_brand_typography_<variant>`;
|
|
18
|
+
if absent it logs one `console.error` per name and sets `data-typography-missing`, which
|
|
19
|
+
`Typography.module.css` hides with `visibility: hidden`. The attribute is never set when
|
|
20
|
+
`NODE_ENV === "production"`.
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
2
|
import { Text } from "./Text";
|
|
3
|
+
import brand from "../../../recursica_brand.json";
|
|
4
|
+
|
|
5
|
+
const BUILT_IN_VARIANTS = ["body", "caption", "overline"];
|
|
6
|
+
|
|
7
|
+
// Custom styles defined under `brand.typography` (beyond h1-h6 and the built-ins above); each has
|
|
8
|
+
// an exported `recursica_brand_typography_<name>` class, so `Text` renders it by name.
|
|
9
|
+
// Sorted so the render order is stable across exports (the visual diff depends on it).
|
|
10
|
+
const customVariants = Object.keys(brand.brand.typography)
|
|
11
|
+
.filter((name) => !/^h[1-6]$/.test(name) && !BUILT_IN_VARIANTS.includes(name))
|
|
12
|
+
.sort();
|
|
3
13
|
|
|
4
14
|
const meta: Meta<typeof Text> = {
|
|
5
15
|
title: "UI-Kit/Text",
|
|
@@ -16,14 +26,7 @@ const meta: Meta<typeof Text> = {
|
|
|
16
26
|
argTypes: {
|
|
17
27
|
variant: {
|
|
18
28
|
control: "select",
|
|
19
|
-
options: [
|
|
20
|
-
"body",
|
|
21
|
-
"body-small",
|
|
22
|
-
"caption",
|
|
23
|
-
"overline",
|
|
24
|
-
"subtitle",
|
|
25
|
-
"subtitle-small",
|
|
26
|
-
],
|
|
29
|
+
options: [...BUILT_IN_VARIANTS, ...customVariants],
|
|
27
30
|
description:
|
|
28
31
|
"Controls the standard logical boundary definitions natively extracted from Figma.",
|
|
29
32
|
},
|
|
@@ -62,21 +65,17 @@ export const StaticVariations: Story = {
|
|
|
62
65
|
<Text variant="body">
|
|
63
66
|
Body (Base paragraph and generic information flow)
|
|
64
67
|
</Text>
|
|
65
|
-
<Text variant="body-small">
|
|
66
|
-
Body Small (Compacted list items and helper blocks)
|
|
67
|
-
</Text>
|
|
68
68
|
<Text variant="caption">
|
|
69
69
|
Caption (Data table descriptions or micro-labels)
|
|
70
70
|
</Text>
|
|
71
71
|
<Text variant="overline">
|
|
72
72
|
Overline (Card contextual pre-headers and categorical tags)
|
|
73
73
|
</Text>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
</Text>
|
|
74
|
+
{customVariants.map((name) => (
|
|
75
|
+
<Text key={name} variant={name}>
|
|
76
|
+
{name} (Custom style from brand.typography)
|
|
77
|
+
</Text>
|
|
78
|
+
))}
|
|
80
79
|
</div>
|
|
81
80
|
),
|
|
82
81
|
};
|
|
@@ -3,6 +3,7 @@ import { type TypographyProps as MuiTypographyProps } from "@mui/material";
|
|
|
3
3
|
import { Typography } from "../Typography/Typography";
|
|
4
4
|
import { type RecursicaOverStyled } from "../../utils/filterStylingProps";
|
|
5
5
|
import { type RecursicaTextProps } from "@recursica/adapter-common";
|
|
6
|
+
import { isTypographyStyleDefined } from "../../utils/typographyClass";
|
|
6
7
|
|
|
7
8
|
export type TextProps = RecursicaOverStyled<
|
|
8
9
|
Omit<MuiTypographyProps, "variant" | "classes" | "color"> &
|
|
@@ -14,6 +15,13 @@ export const Text = forwardRef<HTMLElement, TextProps>(function Text(
|
|
|
14
15
|
{ variant = "body", emphasis = "high", color = "default", ...rest },
|
|
15
16
|
ref,
|
|
16
17
|
) {
|
|
18
|
+
// Dev only: an unknown variant hides the text (and logs) instead of silently rendering with the
|
|
19
|
+
// UI kit's default styling.
|
|
20
|
+
const typographyMissing =
|
|
21
|
+
process.env.NODE_ENV !== "production" &&
|
|
22
|
+
typeof document !== "undefined" &&
|
|
23
|
+
!isTypographyStyleDefined(variant);
|
|
24
|
+
|
|
17
25
|
const typographyClass = `recursica_brand_typography_${variant}`;
|
|
18
26
|
return (
|
|
19
27
|
<Typography
|
|
@@ -21,6 +29,7 @@ export const Text = forwardRef<HTMLElement, TextProps>(function Text(
|
|
|
21
29
|
typographyClass={typographyClass}
|
|
22
30
|
data-color={color}
|
|
23
31
|
data-emphasis={emphasis}
|
|
32
|
+
data-typography-missing={typographyMissing || undefined}
|
|
24
33
|
{...rest}
|
|
25
34
|
/>
|
|
26
35
|
);
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* HARDCODED VALUES
|
|
3
3
|
* - `.root` `text-wrap: balance` — not a design token; a layout algorithm choice requested by
|
|
4
4
|
* UX (Matt Massey, 2026-08-28) to even out wrapped line lengths. See TEXT_IMPLEMENTATION_NOTES.md.
|
|
5
|
+
* - `.root[data-typography-missing]` `visibility: hidden` — dev-only (the attribute is never set in
|
|
6
|
+
* production); hides text whose typography variant has no exported style. Not a design token.
|
|
5
7
|
*
|
|
6
8
|
* Brand-layer exemptions (recursica-allow-brand) — see recursica-token-analyzer README.md.
|
|
7
9
|
* Semantic text color and emphasis are layer/theme-level concerns with no per-component UI-kit
|
|
@@ -50,3 +52,9 @@
|
|
|
50
52
|
.root[data-emphasis="low"] {
|
|
51
53
|
opacity: var(--recursica_brand_text-emphasis_low);
|
|
52
54
|
}
|
|
55
|
+
|
|
56
|
+
/* Dev only (the attribute is never set in production): hides text whose typography variant has no
|
|
57
|
+
exported style, so a typo is obvious instead of rendering with the UI kit's defaults. */
|
|
58
|
+
.root[data-typography-missing] {
|
|
59
|
+
visibility: hidden;
|
|
60
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const found = new Set<string>();
|
|
2
|
+
const reported = new Set<string>();
|
|
3
|
+
|
|
4
|
+
function ruleListDefines(rules: CSSRuleList, selector: string): boolean {
|
|
5
|
+
return Array.from(rules).some((rule) => {
|
|
6
|
+
if (rule instanceof CSSStyleRule) {
|
|
7
|
+
return rule.selectorText.split(",").some((s) => s.trim() === selector);
|
|
8
|
+
}
|
|
9
|
+
const nested = (rule as CSSGroupingRule).cssRules;
|
|
10
|
+
return nested ? ruleListDefines(nested, selector) : false;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Dev-only: whether a `.recursica_brand_typography_<name>` rule exists in any readable stylesheet.
|
|
16
|
+
* Logs a console error once per missing name. Cross-origin stylesheets can't be read and are
|
|
17
|
+
* skipped, so they never count as defining the class.
|
|
18
|
+
*/
|
|
19
|
+
export function isTypographyStyleDefined(name: string): boolean {
|
|
20
|
+
const selector = `.recursica_brand_typography_${name}`;
|
|
21
|
+
if (found.has(selector)) return true;
|
|
22
|
+
const defined = Array.from(document.styleSheets).some((sheet) => {
|
|
23
|
+
try {
|
|
24
|
+
return ruleListDefines(sheet.cssRules, selector);
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
if (defined) {
|
|
30
|
+
found.add(selector);
|
|
31
|
+
} else if (!reported.has(selector)) {
|
|
32
|
+
reported.add(selector);
|
|
33
|
+
console.error(
|
|
34
|
+
`Text: no "${selector}" rule found. "${name}" is not defined under brand.typography in the exported Recursica CSS, so the text is hidden.`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return defined;
|
|
38
|
+
}
|