@financial-times/o-teaser 9.1.2 → 10.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [10.0.0](https://github.com/Financial-Times/origami/compare/o-teaser-v9.1.3...o-teaser-v10.0.0) (2026-02-19)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * Add Byline component
9
+
10
+ ### Features
11
+
12
+ * Add Byline component ([4d01245](https://github.com/Financial-Times/origami/commit/4d01245fb5d767a0f1cf5972714b603fab66383f))
13
+ * Add Byline stylings ([be46170](https://github.com/Financial-Times/origami/commit/be461709df3c64537e0519ca45009e1b116765e5))
14
+ * Add title indicator icon with Opinion teasers ([fc23079](https://github.com/Financial-Times/origami/commit/fc23079fdac6d2591842854058e26a2873e4985f))
15
+ * Add titlePrefix into Title component ([7e754f1](https://github.com/Financial-Times/origami/commit/7e754f111ca880defbe2cdc8ddba36fa624a0bad))
16
+ * Add titlePrefix stylings ([3ce1ae0](https://github.com/Financial-Times/origami/commit/3ce1ae0cdfdefe325f7ea2f9f2f930ba9c55cba9))
17
+
18
+ ## [9.1.3](https://github.com/Financial-Times/origami/compare/o-teaser-v9.1.2...o-teaser-v9.1.3) (2026-02-05)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * depend on v7 and v8 of o-labels on o-teaser ([#2360](https://github.com/Financial-Times/origami/issues/2360)) ([e4d4c46](https://github.com/Financial-Times/origami/commit/e4d4c464ad3acfa412002a550590d497a246de45))
24
+
3
25
  ## [9.1.2](https://github.com/Financial-Times/origami/compare/o-teaser-v9.1.1...o-teaser-v9.1.2) (2025-12-03)
4
26
 
5
27
 
package/MIGRATION.md CHANGED
@@ -1,5 +1,61 @@
1
1
  # Migration guide
2
2
 
3
+ ### Migrating to v10.0.0
4
+
5
+ v10.0.0 introduces:
6
+
7
+ * **Byline** component, which replaces the legacy Headshot component
8
+ * **title indicator icon** for only Opinion teaser
9
+ * **titlePrefix**
10
+
11
+ #### Byline
12
+
13
+ The Byline component is enabled by default (`showByline: true`) in the presets.
14
+ When `byline` data is provided, the Byline component will be rendered instead of Headshot.
15
+
16
+ If you are not ready to use the Byline component, pass:
17
+
18
+ ```js
19
+ showByline: false
20
+ ```
21
+
22
+ This keeps the existing Headshot behaviour.
23
+
24
+ If you are migrating to the Byline component, you must provide a `byline` property:
25
+
26
+ | Property name | Type | Note |
27
+ | ------------- | ------------------------------ | ---------------------------------- |
28
+ | `byline` | `[string, string?, string?][]` | `[text, linkUrl?, headshotUrl?][]` |
29
+
30
+ Example with single author with headshot:
31
+
32
+ ```js
33
+ byline: [
34
+ ['Martin Wolf', '/martin-wolf', '/martin-wolf-headshot']
35
+ ]
36
+ ```
37
+
38
+ Example with multiple authors:
39
+
40
+ ```js
41
+ // This will render: Martin Wolf & Paul Krugman
42
+ byline: [
43
+ ['Martin Wolf', '/martin-wolf'],
44
+ [' & '],
45
+ ['Paul Krugman', '/paul-krugman']
46
+ ]
47
+ ```
48
+
49
+ #### titlePrefix
50
+
51
+ `titlePrefix` is enabled by default (`showTitlePrefix: true`) in the presets.
52
+ Nothing will be rendered unless a `titlePrefix` string is provided.
53
+
54
+ | Property name | Type | Note |
55
+ | ------------- | -------- | ------------------------------- |
56
+ | `titlePrefix` | `string` | Text displayed before the title |
57
+
58
+
3
59
  ### Migrating to v9.0.0
4
60
 
5
61
  v9 upgrades [html-react-parser to v5.2.7](https://github.com/remarkablemark/html-react-parser), which has a dependency on React 19.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/o-teaser",
3
- "version": "9.1.2",
3
+ "version": "10.0.0",
4
4
  "description": "Provides styling for teaser elements, which contain information about an article and link through to it",
5
5
  "keywords": [
6
6
  "article",
@@ -24,7 +24,7 @@
24
24
  "watch": "bash ../../scripts/component/watch.bash"
25
25
  },
26
26
  "peerDependencies": {
27
- "@financial-times/o-labels": "^7.0.0",
27
+ "@financial-times/o-labels": "^7.0.0 || ^8.0.0",
28
28
  "@financial-times/o-private-foundation": "^1.5.0"
29
29
  },
30
30
  "devDependencies": {
@@ -105,6 +105,10 @@
105
105
  .o-teaser__visually-hidden {
106
106
  @include oPrivateNormaliseVisuallyHidden;
107
107
  }
108
+
109
+ .o-teaser__byline {
110
+ @include _oTeaserByline;
111
+ }
108
112
  }
109
113
 
110
114
  @mixin _oTeaserElementsImages {
@@ -15,6 +15,25 @@
15
15
  color: $_o-teaser-base-color;
16
16
  margin-top: 0;
17
17
  margin-bottom: 0;
18
+
19
+ &:before {
20
+ display: none;
21
+ mask-repeat: no-repeat;
22
+ mask-size: contain;
23
+ vertical-align: text-bottom;
24
+ content: '';
25
+ margin-right: 0.2em;
26
+ width: 1em;
27
+ height: 1em;
28
+ }
29
+
30
+ .o-teaser__heading-prefix {
31
+ font-family: inherit;
32
+ font-size: inherit;
33
+ font-weight: oPrivateFoundationGet('o3-font-weight-semibold');
34
+ line-height: inherit;
35
+ color: inherit;
36
+ }
18
37
  }
19
38
 
20
39
  /// Base styles for a teaser
@@ -64,6 +83,42 @@
64
83
  }
65
84
  }
66
85
 
86
+ @mixin _oTeaserByline {
87
+ @include _oTeaserLink();
88
+ a:focus,
89
+ a:hover {
90
+ color: $_o-teaser-focus-hover;
91
+ }
92
+ a:visited {
93
+ color: $_o-teaser-base-color;
94
+ }
95
+ font-family: oPrivateFoundationGet('o3-font-family-metric');
96
+ font-size: oPrivateFoundationGet('o3-font-size-metric2-0');
97
+ font-weight: oPrivateFoundationGet('o3-font-weight-regular');
98
+ line-height: oPrivateFoundationGet('o3-font-lineheight-2');
99
+ color: $_o-teaser-base-color;
100
+ margin-top: oPrivateSpacingByName('s3');
101
+ margin-bottom: 0;
102
+ display: flex;
103
+ align-items: center;
104
+ flex-wrap: wrap;
105
+ gap: oPrivateSpacingByName('s1');
106
+
107
+ .o-teaser__byline-link {
108
+ display: flex;
109
+ align-items: center;
110
+
111
+ img {
112
+ width: 40px;
113
+ height: 40px;
114
+ border-radius: 50%;
115
+ border: 1px solid oPrivateFoundationGet('o3-color-palette-black-20');
116
+ background-color: oPrivateFoundationGet('o3-color-palette-black-10');
117
+ margin-right: oPrivateSpacingByName('s3');
118
+ }
119
+ }
120
+ }
121
+
67
122
  /// Links within title or standfirst
68
123
  @mixin _oTeaserLink {
69
124
  a {
@@ -37,6 +37,8 @@
37
37
  .o-teaser__heading a:focus,
38
38
  .o-teaser__heading a:visited,
39
39
  .o-teaser__standfirst a:visited,
40
+ .o-teaser__byline a:hover,
41
+ .o-teaser__byline a:focus,
40
42
  .o-teaser__tag:hover,
41
43
  .o-teaser__tag:focus {
42
44
  color: oPrivateColorsMix(
@@ -116,6 +118,8 @@
116
118
  .o-teaser__heading,
117
119
  .o-teaser__heading a,
118
120
  .o-teaser__heading a:visited,
121
+ .o-teaser__byline a,
122
+ .o-teaser__byline a:visited,
119
123
  .o-teaser__meta,
120
124
  .o-teaser__standfirst,
121
125
  .o-teaser__standfirst a,
@@ -177,6 +181,10 @@
177
181
  font-weight: oPrivateFoundationGet('o3-type-headline-md-font-weight');
178
182
  line-height: oPrivateFoundationGet('o3-type-headline-md-line-height');
179
183
  }
184
+
185
+ .o-teaser__byline {
186
+ justify-self: center;
187
+ }
180
188
  }
181
189
 
182
190
  /// Centred hero teaser styles to centre image
@@ -213,7 +221,9 @@
213
221
  $hero-extra-highlight-border: oPrivateFoundationGet('o3-color-palette-lemon');
214
222
  $hero-extra-highlight-color: oPrivateFoundationGet('o3-color-palette-lemon');
215
223
  .o-teaser__heading a:hover,
216
- .o-teaser__heading a:focus {
224
+ .o-teaser__heading a:focus,
225
+ .o-teaser__byline a:hover,
226
+ .o-teaser__byline a:focus {
217
227
  color: $hero-extra-highlight-color;
218
228
  }
219
229
 
@@ -26,6 +26,8 @@
26
26
  .o-teaser__meta a:hover,
27
27
  .o-teaser__heading a:focus,
28
28
  .o-teaser__heading a:hover,
29
+ .o-teaser__byline a:focus,
30
+ .o-teaser__byline a:hover,
29
31
  .o-teaser__standfirst a:visited {
30
32
  color: oPrivateColorsMix('o3-color-palette-white', 'o3-color-palette-crimson', 90);
31
33
  outline-color: currentColor;
@@ -6,6 +6,8 @@
6
6
  .o-teaser__heading a:hover,
7
7
  .o-teaser__heading a:focus,
8
8
  .o-teaser__heading a:visited,
9
+ .o-teaser__byline a:hover,
10
+ .o-teaser__byline a:focus,
9
11
  .o-teaser__standfirst a:visited,
10
12
  .o-teaser__tag:hover,
11
13
  .o-teaser__tag:focus {
@@ -17,6 +19,8 @@
17
19
  }
18
20
 
19
21
  .o-teaser__meta,
22
+ .o-teaser__byline,
23
+ .o-teaser__byline a:visited,
20
24
  .o-teaser__tag-suffix,
21
25
  .o-teaser__heading {
22
26
  color: oPrivateFoundationGet('o3-color-palette-white');
@@ -53,6 +57,23 @@
53
57
  .o-teaser__meta {
54
58
  color: oPrivateFoundationGet('o3-color-palette-oxford');
55
59
  }
60
+
61
+ .o-teaser__heading {
62
+ &:before {
63
+ display: inline-block;
64
+ background-color: oPrivateFoundationGet('o3-color-palette-oxford');
65
+ mask-image: oPrivateFoundationGet(o3-icon-quote-left);
66
+ width: 1.1em;
67
+ height: 1.1em;
68
+ }
69
+ }
70
+
71
+ &.o-teaser--inverse,
72
+ &.o-teaser--hero {
73
+ .o-teaser__heading:before {
74
+ background-color: oPrivateFoundationGet('o3-color-palette-white');
75
+ }
76
+ }
56
77
  }
57
78
 
58
79
  /// Opinion background theme - colours background blue and adjust text
@@ -100,6 +121,8 @@
100
121
  .o-teaser__heading a:hover,
101
122
  .o-teaser__heading a:focus,
102
123
  .o-teaser__heading a:visited,
124
+ .o-teaser__byline a:hover,
125
+ .o-teaser__byline a:focus,
103
126
  .o-teaser__standfirst a:visited,
104
127
  .o-teaser__tag:hover,
105
128
  .o-teaser__tag:focus {