@mindvalley/design-system 4.0.1 → 4.1.1
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 +95 -55
- package/README.md +11 -17
- package/dist/tailwind/plugins/tokens/b2b/typography.d.ts +4 -1
- package/dist/tailwind/plugins/tokens/b2b/typography.d.ts.map +1 -1
- package/dist/tailwind/plugins/tokens/b2b/typography.js +25 -25
- package/dist/tailwind/plugins/tokens/mindvalley/typography-gsf.d.ts +15 -0
- package/dist/tailwind/plugins/tokens/mindvalley/typography-gsf.d.ts.map +1 -0
- package/dist/tailwind/plugins/tokens/mindvalley/typography-gsf.js +77 -0
- package/dist/tailwind/plugins/tokens/mindvalley/typography.d.ts.map +1 -1
- package/dist/tailwind/plugins/tokens/mindvalley/typography.js +420 -60
- package/dist/tailwind/plugins/typography-gsf.d.ts +31 -0
- package/dist/tailwind/plugins/typography-gsf.d.ts.map +1 -0
- package/dist/tailwind/plugins/typography-gsf.js +130 -0
- package/docs/README.md +25 -0
- package/docs/agents/code-style.md +84 -0
- package/docs/agents/git-workflow.md +79 -0
- package/docs/agents/testing.md +65 -0
- package/docs/agents/token-system.md +83 -0
- package/docs/{RELEASING.md → releasing.md} +9 -9
- package/docs/token-validation.md +298 -0
- package/docs/typography/README.md +58 -0
- package/docs/typography/migration.md +166 -0
- package/docs/typography/setup.md +366 -0
- package/docs/{USAGE.md → usage.md} +129 -131
- package/package.json +10 -3
- package/docs/CONTRIBUTION.md +0 -262
- package/docs/typography-fonts.md +0 -552
- package/docs/typography-token-pipeline-b2b.md +0 -156
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface TypographyToken {
|
|
2
|
+
fontFamily: string;
|
|
3
|
+
fontSize: string;
|
|
4
|
+
lineHeight: string;
|
|
5
|
+
letterSpacing: string;
|
|
6
|
+
fontWeight?: number;
|
|
7
|
+
[key: string]: string | number | undefined;
|
|
8
|
+
}
|
|
9
|
+
export interface TypographySet {
|
|
10
|
+
[key: string]: TypographyToken;
|
|
11
|
+
}
|
|
12
|
+
export interface BreakpointsConfig {
|
|
13
|
+
tablet?: string;
|
|
14
|
+
desktop?: string;
|
|
15
|
+
[key: string]: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
export interface TypographyPluginOptions {
|
|
18
|
+
casing?: 'snakeCase' | 'camelCase' | 'pascalCase' | 'kebabCase' | 'noCase';
|
|
19
|
+
breakpoints?: BreakpointsConfig;
|
|
20
|
+
prefix?: string;
|
|
21
|
+
brands?: string[];
|
|
22
|
+
}
|
|
23
|
+
declare const _default: {
|
|
24
|
+
(options: TypographyPluginOptions | undefined): {
|
|
25
|
+
handler: import("tailwindcss/types/config").PluginCreator;
|
|
26
|
+
config?: Partial<import("tailwindcss/types/config").Config>;
|
|
27
|
+
};
|
|
28
|
+
__isOptionsFunction: true;
|
|
29
|
+
};
|
|
30
|
+
export default _default;
|
|
31
|
+
//# sourceMappingURL=typography-gsf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typography-gsf.d.ts","sourceRoot":"","sources":["../../../src/tailwind/plugins/typography-gsf.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAC3C;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;CAC/B;AAeD,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAA;IAC1E,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;;;;cAzCE,CAAC;;;;AAgPJ,wBAAmD"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const plugin_1 = __importDefault(require("tailwindcss/plugin"));
|
|
7
|
+
const casing_1 = require("../../helpers/casing");
|
|
8
|
+
const dimens_1 = require("../../helpers/dimens");
|
|
9
|
+
const typography_1 = __importDefault(require("./tokens/b2b/typography"));
|
|
10
|
+
const typography_gsf_1 = __importDefault(require("./tokens/mindvalley/typography-gsf"));
|
|
11
|
+
const brandMapping = {
|
|
12
|
+
mindvalley: typography_gsf_1.default,
|
|
13
|
+
b2b: typography_1.default,
|
|
14
|
+
};
|
|
15
|
+
function typographyPlugin(options = {}) {
|
|
16
|
+
return ({ addUtilities, theme }) => {
|
|
17
|
+
const { casing = casing_1.CASINGS.kebabCase, breakpoints = {}, prefix = '', brands = ['mindvalley'], } = options;
|
|
18
|
+
const tabletBreakpoint = breakpoints.tablet ?? theme('screens.md', '768px');
|
|
19
|
+
const desktopBreakpoint = breakpoints.desktop ?? theme('screens.lg', '1024px');
|
|
20
|
+
const typographyClassDeclarations = {};
|
|
21
|
+
for (const brand of brands) {
|
|
22
|
+
const brandTypography = brandMapping[brand];
|
|
23
|
+
if (!brandTypography) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const processedTypography = processTypography(brandTypography, tabletBreakpoint, desktopBreakpoint);
|
|
27
|
+
const casedTypography = convertObjectKeysToCasedClassNames(processedTypography, casing, prefix);
|
|
28
|
+
Object.assign(typographyClassDeclarations, casedTypography);
|
|
29
|
+
}
|
|
30
|
+
addUtilities(typographyClassDeclarations);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function processTypography(typography, tabletBreakpoint, desktopBreakpoint) {
|
|
34
|
+
const result = {};
|
|
35
|
+
for (const key of Object.keys(typography)) {
|
|
36
|
+
const isDesktop = key.endsWith('-desktop');
|
|
37
|
+
const isTablet = key.endsWith('-tablet');
|
|
38
|
+
const isMobile = key.endsWith('-mobile');
|
|
39
|
+
const baseTypography = typography[key];
|
|
40
|
+
const baseKey = isDesktop || isTablet || isMobile
|
|
41
|
+
? (0, casing_1.toCamelCase)(key.replace(/-desktop$|-tablet$|-mobile$/g, ''))
|
|
42
|
+
: key;
|
|
43
|
+
if (isDesktop) {
|
|
44
|
+
const existing = result[baseKey] || {};
|
|
45
|
+
result[baseKey] = {
|
|
46
|
+
...existing,
|
|
47
|
+
[`@media (min-width: ${desktopBreakpoint})`]: { ...baseTypography },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
else if (isTablet) {
|
|
51
|
+
const existing = result[baseKey] || {};
|
|
52
|
+
result[baseKey] = {
|
|
53
|
+
...existing,
|
|
54
|
+
[`@media (min-width: ${tabletBreakpoint})`]: { ...baseTypography },
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
else if (isMobile) {
|
|
58
|
+
const existing = result[baseKey] || {};
|
|
59
|
+
result[baseKey] = { ...baseTypography, ...existing };
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
result[baseKey] = baseTypography;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
function convertObjectKeysToCasedClassNames(typography, casing = casing_1.CASINGS.kebabCase, prefix = '') {
|
|
68
|
+
const mapKey = (key) => {
|
|
69
|
+
let className;
|
|
70
|
+
switch (casing) {
|
|
71
|
+
case casing_1.CASINGS.snakeCase:
|
|
72
|
+
className = (0, casing_1.toSnakeCase)(key);
|
|
73
|
+
break;
|
|
74
|
+
case casing_1.CASINGS.camelCase:
|
|
75
|
+
className = (0, casing_1.toCamelCase)(key);
|
|
76
|
+
break;
|
|
77
|
+
case casing_1.CASINGS.pascalCase:
|
|
78
|
+
className = (0, casing_1.toPascalCase)(key);
|
|
79
|
+
break;
|
|
80
|
+
case casing_1.CASINGS.kebabCase:
|
|
81
|
+
className = (0, casing_1.toKebabCase)(key);
|
|
82
|
+
break;
|
|
83
|
+
case casing_1.CASINGS.noCase:
|
|
84
|
+
className = (0, casing_1.toNoCase)(key);
|
|
85
|
+
break;
|
|
86
|
+
default:
|
|
87
|
+
console.error(`${casing} is currently not supported in this function, reverting to default ${casing_1.CASINGS.kebabCase}. Please raise an issue ticket here[https://github.com/mindvalley/mv-design-system]`);
|
|
88
|
+
className = (0, casing_1.toKebabCase)(key);
|
|
89
|
+
}
|
|
90
|
+
return prefix ? `.${prefix}${className}` : `.${className}`;
|
|
91
|
+
};
|
|
92
|
+
function mapVal(value) {
|
|
93
|
+
const res = {};
|
|
94
|
+
const variationSettings = [];
|
|
95
|
+
Object.keys(value).forEach((key) => {
|
|
96
|
+
const propValue = value[key];
|
|
97
|
+
if (key === 'lineHeight' && typeof propValue === 'string') {
|
|
98
|
+
res[key] = (0, dimens_1.lineHeightToRem)(propValue);
|
|
99
|
+
}
|
|
100
|
+
else if (['fontSize', 'letterSpacing'].includes(key) && typeof propValue === 'string') {
|
|
101
|
+
res[key] = (0, dimens_1.strPxToRemStr)(propValue);
|
|
102
|
+
}
|
|
103
|
+
else if (key === 'fontWidth' && typeof propValue === 'number') {
|
|
104
|
+
variationSettings.push(`"wdth" ${propValue}`);
|
|
105
|
+
}
|
|
106
|
+
else if (key === 'slant' && typeof propValue === 'number') {
|
|
107
|
+
variationSettings.push(`"slnt" ${propValue}`);
|
|
108
|
+
}
|
|
109
|
+
else if (typeof propValue === 'object' && propValue !== null) {
|
|
110
|
+
res[key] = mapVal(propValue);
|
|
111
|
+
}
|
|
112
|
+
else if (propValue !== undefined) {
|
|
113
|
+
res[key] = propValue;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
if (variationSettings.length > 0) {
|
|
117
|
+
res.fontVariationSettings = variationSettings.join(', ');
|
|
118
|
+
}
|
|
119
|
+
return res;
|
|
120
|
+
}
|
|
121
|
+
return mapObj(typography, mapKey, mapVal);
|
|
122
|
+
}
|
|
123
|
+
function mapObj(obj, keyMapFn, valueMapFn) {
|
|
124
|
+
const result = {};
|
|
125
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
126
|
+
result[keyMapFn(key)] = valueMapFn(value);
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
exports.default = plugin_1.default.withOptions(typographyPlugin);
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
These guides cover how to use the Mindvalley Design System in your projects - from installing tokens to configuring Tailwind plugins for typography, colors, icons, and wordmarks.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
New here? Start with the [Usage Guide](usage.md) for installation and basic setup.
|
|
8
|
+
|
|
9
|
+
## Guides
|
|
10
|
+
|
|
11
|
+
| Topic | Guide | What You'll Learn |
|
|
12
|
+
|-------|-------|-------------------|
|
|
13
|
+
| Colors | [Usage → Colors](usage.md#-colors) | Tailwind config, multi-brand setup, gradients |
|
|
14
|
+
| Typography | [Typography Guide](typography/README.md) | Font setup, class reference, plugin options |
|
|
15
|
+
| Icons | [Usage → Icons](usage.md#-icons) | Brand, UI, and category icons with sprites |
|
|
16
|
+
| Wordmarks | [Usage → Wordmarks](usage.md#-wordmarks) | Trainer and topic wordmarks |
|
|
17
|
+
|
|
18
|
+
## Migration
|
|
19
|
+
|
|
20
|
+
- [Sharp Grotesk → Google Sans Flex](typography/migration.md) - Migrate to the new variable font system
|
|
21
|
+
|
|
22
|
+
## Contributing
|
|
23
|
+
|
|
24
|
+
- [Development Guide](../CONTRIBUTING.md) - Setup, commits, build process
|
|
25
|
+
- [Release Process](releasing.md) - Semantic versioning and publishing
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Code Style
|
|
2
|
+
|
|
3
|
+
This project uses [Biome](https://biomejs.dev/) for formatting and linting.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run format # Format files
|
|
9
|
+
npm run lint # Lint files
|
|
10
|
+
npm run check # Format + lint + organize imports
|
|
11
|
+
npm run check:ci # CI check (no auto-fix)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Formatting Rules
|
|
15
|
+
|
|
16
|
+
| Setting | Value |
|
|
17
|
+
|---------|-------|
|
|
18
|
+
| Indent | 2 spaces |
|
|
19
|
+
| Line width | 100 |
|
|
20
|
+
| Line ending | LF |
|
|
21
|
+
| Quotes | Single |
|
|
22
|
+
| JSX quotes | Double |
|
|
23
|
+
| Semicolons | As needed (omit when possible) |
|
|
24
|
+
| Trailing commas | ES5 |
|
|
25
|
+
| Arrow parens | Always |
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// ✅ Correct
|
|
29
|
+
const example = (value: string) => {
|
|
30
|
+
return `Hello, ${value}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ❌ Wrong
|
|
34
|
+
const example = value => {
|
|
35
|
+
return "Hello, " + value;
|
|
36
|
+
};
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Linting Rules
|
|
40
|
+
|
|
41
|
+
### Enforced
|
|
42
|
+
|
|
43
|
+
- `useConst` - Use `const` over `let` when variable is never reassigned
|
|
44
|
+
- `useTemplate` - Prefer template literals over string concatenation
|
|
45
|
+
|
|
46
|
+
### Warnings
|
|
47
|
+
|
|
48
|
+
- `noExplicitAny` - Avoid `any` type
|
|
49
|
+
- `noNonNullAssertion` - Avoid `!` assertions
|
|
50
|
+
- `noConsole` - Avoid console statements
|
|
51
|
+
|
|
52
|
+
### Allowed
|
|
53
|
+
|
|
54
|
+
- `forEach` - Array forEach is permitted
|
|
55
|
+
|
|
56
|
+
## TypeScript
|
|
57
|
+
|
|
58
|
+
- **Strict mode** enabled
|
|
59
|
+
- Target: ES2022
|
|
60
|
+
- Module: Node16
|
|
61
|
+
|
|
62
|
+
## Markdown
|
|
63
|
+
|
|
64
|
+
Linted with markdownlint. Run `npm run lint:md` to check.
|
|
65
|
+
|
|
66
|
+
- Max line length: 500
|
|
67
|
+
- Inline HTML allowed
|
|
68
|
+
- First line doesn't need to be h1
|
|
69
|
+
|
|
70
|
+
## Helper Utilities
|
|
71
|
+
|
|
72
|
+
Available in `src/helpers/`:
|
|
73
|
+
|
|
74
|
+
| Function | Description |
|
|
75
|
+
|----------|-------------|
|
|
76
|
+
| `toKebabCase()` | Convert string to kebab-case |
|
|
77
|
+
| `toSnakeCase()` | Convert string to snake_case |
|
|
78
|
+
| `toCamelCase()` | Convert string to camelCase |
|
|
79
|
+
| `toPascalCase()` | Convert string to PascalCase |
|
|
80
|
+
| `toNoCase()` | Convert string to lowercase no separators |
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { toKebabCase } from '@mindvalley/design-system/helpers/casing'
|
|
84
|
+
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Git Workflow
|
|
2
|
+
|
|
3
|
+
## Branch Naming
|
|
4
|
+
|
|
5
|
+
Format: `JIRA-ID-description-in-kebab-case`
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Examples
|
|
9
|
+
CRF-629-update-contribution-docs
|
|
10
|
+
MVHOME-765-add-tool-versions
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Commits
|
|
14
|
+
|
|
15
|
+
Use conventional commits. Run `npm run commit` for interactive prompts.
|
|
16
|
+
|
|
17
|
+
### Commit Types
|
|
18
|
+
|
|
19
|
+
| Type | Description | Triggers Release |
|
|
20
|
+
|------|-------------|------------------|
|
|
21
|
+
| `feat` | New feature | Minor (1.x.0) |
|
|
22
|
+
| `fix` | Bug fix | Patch (1.0.x) |
|
|
23
|
+
| `perf` | Performance improvement | Patch |
|
|
24
|
+
| `docs` | Documentation only | No |
|
|
25
|
+
| `style` | Formatting, whitespace | No |
|
|
26
|
+
| `refactor` | Code change (no feature/fix) | No |
|
|
27
|
+
| `test` | Add/correct tests | No |
|
|
28
|
+
| `build` | Build system changes | No |
|
|
29
|
+
| `ci` | CI configuration | No |
|
|
30
|
+
| `chore` | Other changes | No |
|
|
31
|
+
|
|
32
|
+
### Commit Message Format
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
type(scope): Sentence case description
|
|
36
|
+
|
|
37
|
+
JIRA-ID
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Important:** Subject must be sentence-case (commitlint enforces this).
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# ✅ Correct
|
|
44
|
+
fix: Correct broken documentation links
|
|
45
|
+
|
|
46
|
+
# ❌ Wrong
|
|
47
|
+
fix: correct broken documentation links
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Pull Requests
|
|
51
|
+
|
|
52
|
+
1. Ensure working tree is clean
|
|
53
|
+
2. Push branch with `-u` flag
|
|
54
|
+
3. Use PR template from `.github/pull_request_template.md`
|
|
55
|
+
4. Title format: `[JIRA-ID] Summary`
|
|
56
|
+
|
|
57
|
+
### PR Template Structure
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
#### Link to Ticket: https://mindvalley.atlassian.net/browse/<JIRA_TICKET_NO>
|
|
61
|
+
|
|
62
|
+
## Description
|
|
63
|
+
## Screenshots
|
|
64
|
+
## What is the expected behaviour?
|
|
65
|
+
## How to test?
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## CI Pipeline
|
|
69
|
+
|
|
70
|
+
On PR to `main`, CI runs:
|
|
71
|
+
|
|
72
|
+
1. `npm ci` - Install dependencies
|
|
73
|
+
2. `npm run lint:md` - Lint markdown
|
|
74
|
+
3. `npm run build` - Build project
|
|
75
|
+
4. `npm test` - Run tests
|
|
76
|
+
|
|
77
|
+
## Releases
|
|
78
|
+
|
|
79
|
+
Automated via semantic-release on merge to `main`. See [releasing.md](../releasing.md) for details.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
This project uses [Jest](https://jestjs.io/) for testing.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run test # Run all tests
|
|
9
|
+
npm run test:watch # Watch mode
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Directory Structure
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
__tests__/
|
|
16
|
+
├── src/
|
|
17
|
+
│ ├── tailwind/
|
|
18
|
+
│ │ └── plugins/
|
|
19
|
+
│ └── types/
|
|
20
|
+
├── utilities/
|
|
21
|
+
└── utils/
|
|
22
|
+
└── plugin.helpers.ts # Shared test utilities
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Important:** Tests go in `__tests__/`, not `test/`.
|
|
26
|
+
|
|
27
|
+
## Test Patterns
|
|
28
|
+
|
|
29
|
+
### Schema Validation Tests
|
|
30
|
+
|
|
31
|
+
For Zod schemas, test both valid and invalid cases:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
describe('ColorTokenSchema', () => {
|
|
35
|
+
it('should accept valid 6-digit hex color', () => {
|
|
36
|
+
const valid = { value: '#ff0000', type: 'color' as const }
|
|
37
|
+
expect(() => ColorTokenSchema.parse(valid)).not.toThrow()
|
|
38
|
+
expect(ColorTokenSchema.safeParse(valid).success).toBe(true)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should reject invalid hex color format', () => {
|
|
42
|
+
const invalid = { value: 'not-a-color', type: 'color' as const }
|
|
43
|
+
expect(() => ColorTokenSchema.parse(invalid)).toThrow()
|
|
44
|
+
expect(ColorTokenSchema.safeParse(invalid).success).toBe(false)
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Test Naming
|
|
50
|
+
|
|
51
|
+
- Use descriptive `it` statements starting with "should"
|
|
52
|
+
- Group related tests with `describe` blocks
|
|
53
|
+
- Test edge cases and error conditions
|
|
54
|
+
|
|
55
|
+
### Path Aliases in Tests
|
|
56
|
+
|
|
57
|
+
Use the `@test-utils/*` alias for shared test utilities:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { someHelper } from '@test-utils/plugin.helpers'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Coverage
|
|
64
|
+
|
|
65
|
+
Coverage reports are generated in the `coverage/` directory (not committed to git).
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Token System
|
|
2
|
+
|
|
3
|
+
Design tokens are transformed from Figma → Supernova → JSON → JavaScript/Tailwind plugins.
|
|
4
|
+
|
|
5
|
+
## Directory Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
src/tokens/brands/
|
|
9
|
+
├── mindvalley/
|
|
10
|
+
│ ├── colors.json
|
|
11
|
+
│ └── typography.json
|
|
12
|
+
└── b2b/
|
|
13
|
+
├── colors.json
|
|
14
|
+
└── typography.json
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Transformation Pipeline
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
npm run validate-tokens → Zod validation
|
|
21
|
+
npm run build:styledictionary → style-dictionary transform
|
|
22
|
+
npm run build → Full build (validate + transform + bundle)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Token Validation
|
|
26
|
+
|
|
27
|
+
Tokens are validated with Zod schemas before transformation. See [token-validation.md](../token-validation.md).
|
|
28
|
+
|
|
29
|
+
**Key schemas:** `src/types/token-schemas.ts`
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
// Token types must match exactly
|
|
33
|
+
{ value: '#ff0000', type: 'color' } // ✅ Valid
|
|
34
|
+
{ value: 'red', type: 'color' } // ❌ Invalid hex
|
|
35
|
+
{ value: '#ff0000' } // ❌ Missing type
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Multi-Brand Support
|
|
39
|
+
|
|
40
|
+
Two brands are supported:
|
|
41
|
+
|
|
42
|
+
- **mindvalley** - Main brand
|
|
43
|
+
- **b2b** - B2B brand
|
|
44
|
+
|
|
45
|
+
Import the appropriate entry point:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { colors } from '@mindvalley/design-system' // Mindvalley
|
|
49
|
+
import { colors } from '@mindvalley/design-system/b2b' // B2B
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Tailwind Plugins
|
|
53
|
+
|
|
54
|
+
Located in `src/tailwind/plugins/`:
|
|
55
|
+
|
|
56
|
+
- `typography.ts` - Typography utilities
|
|
57
|
+
- `typography-gsf.ts` - Google Sans Font typography
|
|
58
|
+
- `tokens/` - Token-based color/typography plugins
|
|
59
|
+
|
|
60
|
+
## Build Outputs
|
|
61
|
+
|
|
62
|
+
After `npm run build`, outputs go to `dist/`:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
dist/
|
|
66
|
+
├── index.js # Main entry (Mindvalley brand)
|
|
67
|
+
├── b2b.js # B2B brand entry
|
|
68
|
+
├── helpers/ # Helper utilities
|
|
69
|
+
└── tailwind/ # Tailwind plugins
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Figma Sync
|
|
73
|
+
|
|
74
|
+
Icons and wordmarks sync from Figma:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm run build:figma # Requires FIGMA_TOKEN in .env
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Configuration files:
|
|
81
|
+
|
|
82
|
+
- `src/utilities/svg-import/.figma_icons.ts`
|
|
83
|
+
- `src/utilities/svg-import/.figma_wordmarks.ts`
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
# Releasing 🚀
|
|
2
2
|
|
|
3
3
|
By default, semantic-release uses the [Angular Commit Message Conventions](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) and triggers releases based on the following rules:
|
|
4
4
|
|
|
5
|
-
| Commit | Release Type | Semver update type
|
|
6
|
-
|
|
7
|
-
| Commit with breaking change | Breaking release | Major release e.g 1.x.x -> 2.x.x
|
|
8
|
-
| Commit with type `feat` | Feature release |
|
|
9
|
-
| Commit with type `fix` | Fix
|
|
10
|
-
| Commit with type `perf` |
|
|
5
|
+
| Commit | Release Type | Semver update type |
|
|
6
|
+
|-----------------------------|------------------|-----------------------------------|
|
|
7
|
+
| Commit with breaking change | Breaking release | Major release e.g 1.x.x -> 2.x.x |
|
|
8
|
+
| Commit with type `feat` | Feature release | Minor release e.g 1.2.x -> 1.3.x |
|
|
9
|
+
| Commit with type `fix` | Fix release | Patch release e.g 1.2.3 -> 1.2.4 |
|
|
10
|
+
| Commit with type `perf` | Performance fix | Patch release e.g 1.2.3 -> 1.2.4 |
|
|
11
11
|
|
|
12
12
|
Only the above type of commits will trigger a release.
|
|
13
13
|
|
|
@@ -23,7 +23,7 @@ More detailed explanation can be found on the [semantic release steps documentat
|
|
|
23
23
|
|
|
24
24
|
After release and publishing, the package should be available as a [scoped npm package](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages) and is on npm as [@mindvalley/design-system](https://www.npmjs.com/package/@mindvalley/design-system).
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
## Trusted publishing
|
|
27
27
|
|
|
28
28
|
Releases run through the GitHub Actions workflow [`release.yml`](../.github/workflows/release.yml) using [npm trusted publishing](https://docs.npmjs.com/trusted-publishers). The workflow:
|
|
29
29
|
|
|
@@ -34,4 +34,4 @@ Releases run through the GitHub Actions workflow [`release.yml`](../.github/work
|
|
|
34
34
|
|
|
35
35
|
If the workflow fails, re-run it from the Actions tab after addressing the underlying error. No manual npm publishing is expected under normal circumstances.
|
|
36
36
|
|
|
37
|
-
Jump to the [usage guide](
|
|
37
|
+
Jump to the [usage guide](usage.md) to understand how to use the published package in your repo.
|