@nextrap/style-typography 1.0.4 → 2.0.0

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.
@@ -0,0 +1,38 @@
1
+ # @nextrap/style-typography
2
+
3
+ ## Purpose
4
+
5
+ Provides composable typographic rules and vertical rhythm for individual native text elements. It does not own `.prose`, boxes, tables, image layouts, containers, page wrappers or section layout; those belong to `@nextrap/style-elements` or the consuming layout/theme.
6
+
7
+ ## Usage
8
+
9
+ ```scss
10
+ @use '@nextrap/style-typography' as type;
11
+
12
+ .theme {
13
+ @include type.style-typography();
14
+ }
15
+ ```
16
+
17
+ `index.scss` is a mixin-only Sass API and emits no CSS. `default.scss` invokes `style-typography()` from `_style-typography.scss` at root and materializes the ready-to-use native selectors and helper classes.
18
+
19
+ ```scss
20
+ @use '@nextrap/style-base/default';
21
+ @use '@nextrap/style-typography/default';
22
+ ```
23
+
24
+ ## Token contract
25
+
26
+ - Consume public `--nt-*` tokens from `@nextrap/style-base`; never import private Sass internals from sibling packages.
27
+ - Use `--nt-header`, `--nt-text`, `--nt-text-muted`, typography scale tokens and `--nt-spacing-text` for the standard document rhythm.
28
+ - Semantic surface utilities override the real base tokens locally: `--nt-text`, `--nt-text-muted`, `--nt-header`, `--nt-link` and `--nt-link-hover`.
29
+ - Package-local overrides use the `--typography-*` prefix. Legacy typography variables remain fallback inputs where already supported.
30
+ - Mixins style the current selector and must not own page, content or section selectors.
31
+ - `.small` is the class equivalent of the native `small` element and `.text-body-secondary` provides the Bootstrap-compatible secondary body color.
32
+ - `.text-muted` remains the compatibility alias for older Bootstrap usage. `.text-nowrap`, `.text-break`, `.text-uppercase`, `.fw-normal`, `.fw-semibold` and `.fw-bold` are provided by `@nextrap/style-utils` and are materialized by the consuming theme's utility layer.
33
+
34
+ For rich-content composition, load `@nextrap/style-elements` separately:
35
+
36
+ ```scss
37
+ @use '@nextrap/style-elements/default';
38
+ ```
package/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 1.0.5 (2025-09-09)
2
+
3
+ This was a version bump only for style-typography to align it with other projects, there were no code changes.
4
+
1
5
  ## 1.0.4 (2025-07-24)
2
6
 
3
7
  This was a version bump only for style-typography to align it with other projects, there were no code changes.
package/README.md CHANGED
@@ -1,11 +1,30 @@
1
- # style-typography
1
+ # @nextrap/style-typography
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
3
+ Typographic rules and vertical rhythm for individual text elements. Rich-content patterns such as `.prose`, boxes, tables and image layouts belong to `@nextrap/style-elements`.
4
4
 
5
- ## Building
5
+ ## Sass entry points
6
6
 
7
- Run `nx build style-typography` to build the library.
7
+ The main entry point exports mixins without emitting CSS:
8
8
 
9
- ## Running unit tests
9
+ ```scss
10
+ @use '@nextrap/style-typography' as type;
10
11
 
11
- Run `nx test style-typography` to execute the unit tests via [Vitest](https://vitest.dev/).
12
+ .article-theme {
13
+ @include type.style-typography();
14
+ }
15
+ ```
16
+
17
+ The scoped include styles native text elements and typography helper classes below `.article-theme`. To materialize the default typography globally, use:
18
+
19
+ ```scss
20
+ @use '@nextrap/style-base/default';
21
+ @use '@nextrap/style-typography/default';
22
+ ```
23
+
24
+ Load rich-content element patterns separately when needed:
25
+
26
+ ```scss
27
+ @use '@nextrap/style-elements/default';
28
+ ```
29
+
30
+ See the [typography demo](./demo/typography.md) for the supported text elements.
package/default.scss ADDED
@@ -0,0 +1,3 @@
1
+ @use './index' as type;
2
+
3
+ @include type.style-typography();
package/index.css CHANGED
@@ -1 +1 @@
1
- h1,.h1{font-size:var(--nt-fs-h1);font-family:var(--nt-font-family-header),sans-serif;line-height:var(--nt-line-height-header)}h2,.h2{font-size:var(--nt-fs-h2);font-family:var(--nt-font-family-header),sans-serif;line-height:var(--nt-line-height-header)}h3,.h3{font-size:var(--nt-fs-h3);font-family:var(--nt-font-family-header),sans-serif;line-height:var(--nt-line-height-header)}h4,.h4{font-size:var(--nt-fs-h4);font-family:var(--nt-font-family-header) sans-serif;line-height:var(--nt-line-height-header)}h5,.h5{font-size:var(--nt-fs-h5);font-family:var(--nt-font-family-header),sans-serif;line-height:var(--nt-line-height-header)}h6,.h6{font-size:var(--nt-fs-h6);font-family:var(--nt-font-family-header),sans-serif;line-height:var(--nt-line-height-header)}p,ul,ol,blockquote{--fs: var(--nt-fs-base);--font-family: var(--nt-font-family-base);--font-color: var(--nt-text)}body{font-family:var(--nt-font-family-base),sans-serif}p{font-size:var(--font-size-base);color:var(--font-color)}small{font-size:var(--nt-fs-small)}
1
+ h1,.h1{margin-top:0;margin-bottom:var(--typography-heading-margin-bottom, calc(var(--nt-spacing-text, 1rem) * .5));color:var(--nt-header, var(--nt-text, currentColor));font-family:var(--nt-font-family-header, inherit);font-weight:var(--nt-font-weight-header, 500);line-height:var(--nt-line-height-header, 1.2);font-size:var(--nt-fs-h1, calc(1.375rem + 1.5vw) )}h2,.h2{margin-top:0;margin-bottom:var(--typography-heading-margin-bottom, calc(var(--nt-spacing-text, 1rem) * .5));color:var(--nt-header, var(--nt-text, currentColor));font-family:var(--nt-font-family-header, inherit);font-weight:var(--nt-font-weight-header, 500);line-height:var(--nt-line-height-header, 1.2);font-size:var(--nt-fs-h2, calc(1.325rem + .9vw) )}h3,.h3{margin-top:0;margin-bottom:var(--typography-heading-margin-bottom, calc(var(--nt-spacing-text, 1rem) * .5));color:var(--nt-header, var(--nt-text, currentColor));font-family:var(--nt-font-family-header, inherit);font-weight:var(--nt-font-weight-header, 500);line-height:var(--nt-line-height-header, 1.2);font-size:var(--nt-fs-h3, calc(1.3rem + .6vw) )}h4,.h4{margin-top:0;margin-bottom:var(--typography-heading-margin-bottom, calc(var(--nt-spacing-text, 1rem) * .5));color:var(--nt-header, var(--nt-text, currentColor));font-family:var(--nt-font-family-header, inherit);font-weight:var(--nt-font-weight-header, 500);line-height:var(--nt-line-height-header, 1.2);font-size:var(--nt-fs-h4, calc(1.275rem + .3vw) )}h5,.h5{margin-top:0;margin-bottom:var(--typography-heading-margin-bottom, calc(var(--nt-spacing-text, 1rem) * .5));color:var(--nt-header, var(--nt-text, currentColor));font-family:var(--nt-font-family-header, inherit);font-weight:var(--nt-font-weight-header, 500);line-height:var(--nt-line-height-header, 1.2);font-size:var(--nt-fs-h5, 1.25rem)}h6,.h6{margin-top:0;margin-bottom:var(--typography-heading-margin-bottom, calc(var(--nt-spacing-text, 1rem) * .5));color:var(--nt-header, var(--nt-text, currentColor));font-family:var(--nt-font-family-header, inherit);font-weight:var(--nt-font-weight-header, 500);line-height:var(--nt-line-height-header, 1.2);font-size:var(--nt-fs-h6, 1rem)}p{margin-top:0;margin-bottom:var(--typography-paragraph-margin-bottom, var(--nt-spacing-text, 1rem));color:var(--nt-text, currentColor);font-family:var(--nt-font-family-base, inherit);font-weight:var(--nt-font-weight-base, 400);line-height:var(--nt-line-height-base, 1.5)}b,strong{color:inherit;font-weight:var(--nt-font-weight-bold, 700)}em{font-style:italic}small,.small{font-size:var(--nt-font-size-small, .875em)}a{color:var(--nt-link, currentColor);text-decoration:underline;text-decoration-color:currentColor;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}a:hover{color:var(--nt-link-hover, var(--nt-link, currentColor))}a:focus-visible{outline:var(--typography-focus-ring-width, 1px) dashed var(--nt-focus, currentColor);outline-offset:var(--typography-focus-ring-offset, 2px)}mark{padding:var(--typography-mark-padding, .1875em);color:var(--typography-mark-color, var(--nt-warning-emphasis, var(--nt-text, currentColor)));background-color:var(--typography-mark-bg, var(--nt-warning-subtle, #fff3cd))}ul{margin-top:0;margin-bottom:var(--typography-list-margin-bottom, var(--nt-spacing-text, 1rem));list-style:disc}ol{margin-top:0;margin-bottom:var(--typography-list-margin-bottom, var(--nt-spacing-text, 1rem));padding-left:var(--typography-list-padding-left, var(--nt-space-6, 2rem));list-style:decimal}dl{margin-top:0;margin-bottom:var(--typography-list-margin-bottom, var(--nt-spacing-text, 1rem))}dt{font-weight:var(--nt-font-weight-bold, 700)}dd{margin-bottom:var(--typography-definition-margin-bottom, calc(var(--nt-spacing-text, 1rem) * .5));margin-left:0;color:var(--nt-text-muted, currentColor)}hr{margin:var(--typography-hr-margin-y, var(--nt-spacing-text, 1rem)) 0;color:inherit;border:0;border-top:var(--nt-border-width, 1px) solid;opacity:var(--typography-hr-opacity, .25)}code{padding:var(--typography-code-padding-y, .125em) var(--typography-code-padding-x, .375em);color:var(--typography-code-color, var(--nt-text, inherit));background:var(--typography-code-bg, color-mix(in oklch, currentColor 8%, transparent));border-radius:var(--nt-border-radius-sm, var(--nt-border-radius, .25rem));font-family:var(--typography-font-family-monospace, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace);font-size:var(--typography-code-font-size, .875em)}pre{display:block;margin-top:0;margin-bottom:var(--typography-pre-margin-bottom, var(--nt-spacing-text, 1rem));padding:var(--typography-pre-padding, var(--nt-space-4, 1rem));overflow:auto;color:var(--nt-text, currentColor);background:var(--typography-pre-bg, color-mix(in oklch, currentColor 8%, transparent));border-radius:var(--nt-border-radius, .375rem);font-family:var(--typography-font-family-monospace, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace);font-size:var(--typography-code-font-size, .875em)}pre code{padding:0;color:inherit;background:transparent;border-radius:0;font-size:inherit}blockquote{margin:0 0 var(--typography-blockquote-margin-bottom, var(--nt-spacing-text, 1rem));padding:var(--typography-blockquote-padding-y, .75rem) var(--typography-blockquote-padding-x, 1rem);color:var(--nt-text-muted, currentColor);border-left:var(--typography-blockquote-border-width, .25rem) solid var(--nt-primary-emphasis, var(--nt-primary, currentColor));font-size:var(--typography-blockquote-font-size, 1.125em)}figure{margin:0 0 var(--typography-figure-margin-bottom, var(--nt-spacing-text, 1rem))}figcaption,.figure-caption{margin-top:var(--typography-figure-caption-margin-top, var(--nt-space-2, .5rem));color:var(--nt-text-muted, currentColor);font-size:var(--nt-font-size-small, .875em);text-align:center}.lead{margin-top:0;margin-bottom:var(--typography-lead-margin-bottom, var(--nt-spacing-text, 1rem));color:var(--nt-text, currentColor);font-size:var(--typography-lead-font-size, var(--nt-fs-1, 1.25rem));font-weight:var(--typography-lead-font-weight, 300);line-height:var(--nt-line-height-base, 1.5)}.muted,.text-muted,.text-body-secondary{color:var(--nt-text-muted, currentColor)!important}
package/index.scss ADDED
@@ -0,0 +1,9 @@
1
+ // @nextrap/style-typography — public Sass API only; importing emits no CSS.
2
+ //
3
+ // @use '@nextrap/style-typography' as type;
4
+ // .theme { @include type.style-typography(); }
5
+ //
6
+ // For ready-to-use root-level typography use `@nextrap/style-typography/default`.
7
+
8
+ @forward './src/typography';
9
+ @forward './src/style-typography' show style-typography;
package/package.json CHANGED
@@ -1,8 +1,20 @@
1
1
  {
2
- "name": "@nextrap/style-typography",
3
- "version": "1.0.4",
4
- "main": "./index.js",
5
- "dependencies": {},
6
- "type": "module",
7
- "types": "./index.d.ts"
2
+ "name": "@nextrap/style-typography",
3
+ "version": "2.0.0",
4
+ "main": "./index.js",
5
+ "exports": {
6
+ ".": "./index.scss",
7
+ "./default": "./default.scss"
8
+ },
9
+ "repository": {
10
+ "directory": "nextrap-base/style-typography",
11
+ "type": "git",
12
+ "url": "https://github.com/nextrap/nextrap-monorepo"
13
+ },
14
+ "dependencies": {},
15
+ "devDependencies": {
16
+ "@nextrap/style-base": "^2.0.0"
17
+ },
18
+ "type": "module",
19
+ "types": "./index.d.ts"
8
20
  }
@@ -0,0 +1,35 @@
1
+ @use './typography' as t;
2
+
3
+ // Materialize the complete typography API in the current Sass scope.
4
+ // Typography intentionally includes native text-element selectors because its
5
+ // default purpose is to establish a coherent document text rhythm. It never
6
+ // styles page/section/content layout containers.
7
+ @mixin style-typography() {
8
+ h1, .h1 { @include t.h1(); }
9
+ h2, .h2 { @include t.h2(); }
10
+ h3, .h3 { @include t.h3(); }
11
+ h4, .h4 { @include t.h4(); }
12
+ h5, .h5 { @include t.h5(); }
13
+ h6, .h6 { @include t.h6(); }
14
+
15
+ p { @include t.p(); }
16
+ b, strong { @include t.strong(); }
17
+ em { @include t.em(); }
18
+ small, .small { @include t.small(); }
19
+ a { @include t.link(); }
20
+ mark { @include t.mark(); }
21
+ ul { @include t.ul(); }
22
+ ol { @include t.ol(); }
23
+ dl { @include t.dl(); }
24
+ dt { @include t.dt(); }
25
+ dd { @include t.dd(); }
26
+ hr { @include t.hr(); }
27
+ code { @include t.code(); }
28
+ pre { @include t.pre(); }
29
+ blockquote { @include t.blockquote(); }
30
+ figure { @include t.figure(); }
31
+ figcaption, .figure-caption { @include t.figure-caption(); }
32
+ .lead { @include t.lead(); }
33
+ .muted, .text-muted { @include t.text-muted(); }
34
+ .text-body-secondary { @include t.text-body-secondary(); }
35
+ }
@@ -0,0 +1,214 @@
1
+ // Typography mixin API — each mixin styles the current selector.
2
+ //
3
+ // Typography owns the rhythm and visual treatment of individual text elements.
4
+ // It deliberately does NOT add spacing/padding to content wrappers, sections,
5
+ // pages, or other layout containers. Layout spacing belongs to the consuming
6
+ // layout/theme layer.
7
+
8
+ @mixin heading() {
9
+ margin-top: 0;
10
+ margin-bottom: var(--typography-heading-margin-bottom, calc(var(--nt-spacing-text, 1rem) * 0.5));
11
+ color: var(--nt-header, var(--nt-text, currentColor));
12
+ font-family: var(--nt-font-family-header, inherit);
13
+ font-weight: var(--nt-font-weight-header, 500);
14
+ line-height: var(--nt-line-height-header, 1.2);
15
+ }
16
+
17
+ @mixin h1() {
18
+ @include heading();
19
+ font-size: var(--nt-fs-h1, calc(1.375rem + 1.5vw));
20
+ }
21
+
22
+ @mixin h2() {
23
+ @include heading();
24
+ font-size: var(--nt-fs-h2, calc(1.325rem + 0.9vw));
25
+ }
26
+
27
+ @mixin h3() {
28
+ @include heading();
29
+ font-size: var(--nt-fs-h3, calc(1.3rem + 0.6vw));
30
+ }
31
+
32
+ @mixin h4() {
33
+ @include heading();
34
+ font-size: var(--nt-fs-h4, calc(1.275rem + 0.3vw));
35
+ }
36
+
37
+ @mixin h5() {
38
+ @include heading();
39
+ font-size: var(--nt-fs-h5, 1.25rem);
40
+ }
41
+
42
+ @mixin h6() {
43
+ @include heading();
44
+ font-size: var(--nt-fs-h6, 1rem);
45
+ }
46
+
47
+ @mixin p() {
48
+ margin-top: 0;
49
+ margin-bottom: var(--typography-paragraph-margin-bottom, var(--nt-spacing-text, 1rem));
50
+ color: var(--nt-text, currentColor);
51
+ font-family: var(--nt-font-family-base, inherit);
52
+ font-weight: var(--nt-font-weight-base, 400);
53
+ line-height: var(--nt-line-height-base, 1.5);
54
+ }
55
+
56
+ @mixin strong() {
57
+ color: inherit;
58
+ font-weight: var(--nt-font-weight-bold, 700);
59
+ }
60
+
61
+ @mixin em() {
62
+ font-style: italic;
63
+ }
64
+
65
+ @mixin small() {
66
+ font-size: var(--nt-font-size-small, 0.875em);
67
+ }
68
+
69
+ @mixin text-body-secondary() {
70
+ color: var(--nt-text-muted, currentColor) !important;
71
+ }
72
+
73
+ @mixin link() {
74
+ color: var(--nt-link, currentColor);
75
+ text-decoration: underline;
76
+ text-decoration-color: currentColor;
77
+ transition:
78
+ color 0.15s ease-in-out,
79
+ background-color 0.15s ease-in-out,
80
+ border-color 0.15s ease-in-out,
81
+ box-shadow 0.15s ease-in-out;
82
+
83
+ &:hover {
84
+ color: var(--nt-link-hover, var(--nt-link, currentColor));
85
+ }
86
+
87
+ &:focus-visible {
88
+ outline: var(--typography-focus-ring-width, 1px) dashed var(--nt-focus, currentColor);
89
+ outline-offset: var(--typography-focus-ring-offset, 2px);
90
+ }
91
+ }
92
+
93
+ @mixin mark() {
94
+ padding: var(--typography-mark-padding, 0.1875em);
95
+ color: var(--typography-mark-color, var(--nt-warning-emphasis, var(--nt-text, currentColor)));
96
+ background-color: var(--typography-mark-bg, var(--nt-warning-subtle, #fff3cd));
97
+ }
98
+
99
+ @mixin ul() {
100
+ margin-top: 0;
101
+ margin-bottom: var(--typography-list-margin-bottom, var(--nt-spacing-text, 1rem));
102
+ list-style: disc;
103
+ }
104
+
105
+ @mixin ol() {
106
+ margin-top: 0;
107
+ margin-bottom: var(--typography-list-margin-bottom, var(--nt-spacing-text, 1rem));
108
+ padding-left: var(--typography-list-padding-left, var(--nt-space-6, 2rem));
109
+ list-style: decimal;
110
+ }
111
+
112
+ @mixin dl() {
113
+ margin-top: 0;
114
+ margin-bottom: var(--typography-list-margin-bottom, var(--nt-spacing-text, 1rem));
115
+ }
116
+
117
+ @mixin dt() {
118
+ font-weight: var(--nt-font-weight-bold, 700);
119
+ }
120
+
121
+ @mixin dd() {
122
+ margin-bottom: var(--typography-definition-margin-bottom, calc(var(--nt-spacing-text, 1rem) * 0.5));
123
+ margin-left: 0;
124
+ color: var(--nt-text-muted, currentColor);
125
+ }
126
+
127
+ @mixin hr() {
128
+ margin: var(--typography-hr-margin-y, var(--nt-spacing-text, 1rem)) 0;
129
+ color: inherit;
130
+ border: 0;
131
+ border-top: var(--nt-border-width, 1px) solid;
132
+ opacity: var(--typography-hr-opacity, 0.25);
133
+ }
134
+
135
+ @mixin code() {
136
+ padding: var(--typography-code-padding-y, 0.125em) var(--typography-code-padding-x, 0.375em);
137
+ color: var(--typography-code-color, var(--nt-text, inherit));
138
+ background: var(--typography-code-bg, color-mix(in oklch, currentColor 8%, transparent));
139
+ border-radius: var(--nt-border-radius-sm, var(--nt-border-radius, 0.25rem));
140
+ font-family: var(
141
+ --typography-font-family-monospace,
142
+ ui-monospace,
143
+ SFMono-Regular,
144
+ Menlo,
145
+ Monaco,
146
+ Consolas,
147
+ 'Liberation Mono',
148
+ monospace
149
+ );
150
+ font-size: var(--typography-code-font-size, 0.875em);
151
+ }
152
+
153
+ @mixin pre() {
154
+ display: block;
155
+ margin-top: 0;
156
+ margin-bottom: var(--typography-pre-margin-bottom, var(--nt-spacing-text, 1rem));
157
+ padding: var(--typography-pre-padding, var(--nt-space-4, 1rem));
158
+ overflow: auto;
159
+ color: var(--nt-text, currentColor);
160
+ background: var(--typography-pre-bg, color-mix(in oklch, currentColor 8%, transparent));
161
+ border-radius: var(--nt-border-radius, 0.375rem);
162
+ font-family: var(
163
+ --typography-font-family-monospace,
164
+ ui-monospace,
165
+ SFMono-Regular,
166
+ Menlo,
167
+ Monaco,
168
+ Consolas,
169
+ 'Liberation Mono',
170
+ monospace
171
+ );
172
+ font-size: var(--typography-code-font-size, 0.875em);
173
+
174
+ code {
175
+ padding: 0;
176
+ color: inherit;
177
+ background: transparent;
178
+ border-radius: 0;
179
+ font-size: inherit;
180
+ }
181
+ }
182
+
183
+ @mixin blockquote() {
184
+ margin: 0 0 var(--typography-blockquote-margin-bottom, var(--nt-spacing-text, 1rem));
185
+ padding: var(--typography-blockquote-padding-y, 0.75rem) var(--typography-blockquote-padding-x, 1rem);
186
+ color: var(--nt-text-muted, currentColor);
187
+ border-left: var(--typography-blockquote-border-width, 0.25rem) solid
188
+ var(--nt-primary-emphasis, var(--nt-primary, currentColor));
189
+ font-size: var(--typography-blockquote-font-size, 1.125em);
190
+ }
191
+
192
+ @mixin figure() {
193
+ margin: 0 0 var(--typography-figure-margin-bottom, var(--nt-spacing-text, 1rem));
194
+ }
195
+
196
+ @mixin figure-caption() {
197
+ margin-top: var(--typography-figure-caption-margin-top, var(--nt-space-2, 0.5rem));
198
+ color: var(--nt-text-muted, currentColor);
199
+ font-size: var(--nt-font-size-small, 0.875em);
200
+ text-align: center;
201
+ }
202
+
203
+ @mixin lead() {
204
+ margin-top: 0;
205
+ margin-bottom: var(--typography-lead-margin-bottom, var(--nt-spacing-text, 1rem));
206
+ color: var(--nt-text, currentColor);
207
+ font-size: var(--typography-lead-font-size, var(--nt-fs-1, 1.25rem));
208
+ font-weight: var(--typography-lead-font-weight, 300);
209
+ line-height: var(--nt-line-height-base, 1.5);
210
+ }
211
+
212
+ @mixin text-muted() {
213
+ color: var(--nt-text-muted, currentColor) !important;
214
+ }