@financial-times/n-myft-ui 26.0.0 → 27.2.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.
Files changed (40) hide show
  1. package/.circleci/config.yml +42 -16
  2. package/.nvmrc +1 -1
  3. package/Makefile +0 -1
  4. package/README.md +2 -48
  5. package/build-state/npm-shrinkwrap.json +10147 -20187
  6. package/components/collections/collections.html +85 -0
  7. package/components/concept-list/concept-list.html +31 -0
  8. package/components/csrf-token/input.html +5 -0
  9. package/components/follow-button/follow-button.html +79 -0
  10. package/components/instant-alert/instant-alert.html +47 -0
  11. package/components/pin-button/pin-button.html +20 -0
  12. package/components/save-for-later/save-for-later.html +68 -0
  13. package/components/unread-articles-indicator/date-fns.js +6 -6
  14. package/demos/app.js +3 -26
  15. package/demos/templates/demo.html +11 -10
  16. package/myft/main.scss +145 -0
  17. package/myft/ui/lists.js +22 -0
  18. package/myft/ui/save-article-to-list-variant.js +376 -0
  19. package/package.json +16 -30
  20. package/components/collections/collections.jsx +0 -68
  21. package/components/collections/collections.test.js +0 -83
  22. package/components/concept-list/concept-list.jsx +0 -69
  23. package/components/concept-list/concept-list.test.js +0 -116
  24. package/components/csrf-token/input.jsx +0 -20
  25. package/components/csrf-token/input.test.js +0 -23
  26. package/components/follow-button/follow-button.jsx +0 -176
  27. package/components/follow-button/follow-button.test.js +0 -40
  28. package/components/index.js +0 -17
  29. package/components/instant-alert/instant-alert.jsx +0 -73
  30. package/components/instant-alert/instant-alert.test.js +0 -86
  31. package/components/pin-button/pin-button.jsx +0 -40
  32. package/components/pin-button/pin-button.test.js +0 -57
  33. package/components/save-for-later/save-for-later.jsx +0 -101
  34. package/components/save-for-later/save-for-later.test.js +0 -59
  35. package/demos/templates/demo-layout.html +0 -25
  36. package/demos/templates/demo.jsx +0 -125
  37. package/dist/bundles/bundle.js +0 -3232
  38. package/jest.config.js +0 -8
  39. package/jsx-migration.md +0 -16
  40. package/webpack.config.js +0 -34
@@ -0,0 +1,85 @@
1
+ <section
2
+ class="collection {{#if liteStyle}}collection--lite{{else}}collection--regular{{/if}}"
3
+ data-trackable="{{#if trackable}}{{trackable}}{{else}}collection{{/if}}">
4
+ <header class="collection__header {{#if liteStyle}}collection__header--lite{{else}}collection__header--regular{{/if}}">
5
+ <h2 class="collection__title {{#if liteStyle}}collection__title--lite{{else}}collection__title--regular{{/if}}">
6
+ {{title}}
7
+ </h2>
8
+ </header>
9
+ <ul class="collection__concepts">
10
+ {{#concepts}}
11
+ <li class="collection__concept">
12
+ {{#if ../liteStyle}}
13
+ {{> n-myft-ui/components/follow-button/follow-button
14
+ variant="primary"
15
+ buttonText=name
16
+ collectionName=../collectionName
17
+ }}
18
+ {{else}}
19
+ {{> n-myft-ui/components/follow-button/follow-button
20
+ variant="inverse"
21
+ buttonText=name
22
+ collectionName=../collectionName
23
+ }}
24
+ {{/if}}
25
+ </li>
26
+ {{/concepts}}
27
+ </ul>
28
+ <div class="collection__meta">
29
+ <form
30
+ method="POST"
31
+ action="#"
32
+ data-myft-ui="follow"
33
+ {{#if collectionName}}data-myft-tracking="collectionName={{collectionName}}"{{/if}}
34
+ data-concept-id="
35
+ {{~#concepts~}}
36
+ {{conceptId}}
37
+ {{~#unless @last~}}
38
+ ,
39
+ {{~/unless~}}
40
+ {{~/concepts~}}"
41
+ class="n-myft-ui n-myft-ui--follow n-ui-hide-core collection-follow-all">
42
+ <input
43
+ type="hidden"
44
+ name="directType"
45
+ value="
46
+ {{~#concepts~}}
47
+ {{directType}}
48
+ {{~#unless @last~}}
49
+ ,
50
+ {{~/unless~}}
51
+ {{~/concepts~}}"
52
+ />
53
+ {{> n-myft-ui/components/csrf-token/input}}
54
+ <input
55
+ type="hidden"
56
+ name="name"
57
+ value="
58
+ {{~#concepts~}}
59
+ {{name}}
60
+ {{~#unless @last~}}
61
+ ,
62
+ {{~/unless~}}
63
+ {{~/concepts~}}"
64
+ />
65
+ <button
66
+ type="submit"
67
+ aria-pressed="false"
68
+ class="collection-follow-all__button {{#if liteStyle}}collection-follow-all__button--lite{{else}}collection-follow-all__button--regular{{/if}}"
69
+ data-trackable="follow all"
70
+ data-concept-id="
71
+ {{~#concepts~}}
72
+ {{conceptId}}
73
+ {{~#unless @last~}}
74
+ ,
75
+ {{~/unless~}}
76
+ {{~/concepts~}}"
77
+ aria-label="Add all topics in the {{title}} collection to my F T"
78
+ data-alternate-label="Remove all topics in the {{title}} collection from my F T"
79
+ data-alternate-text="Added"
80
+ title="Add all topics in the {{title}} collection to my F T">
81
+ Add all to myFT
82
+ </button>
83
+ </form>
84
+ </div>
85
+ </section>
@@ -0,0 +1,31 @@
1
+ {{#ifAll @root.flags.myFtApi @root.flags.myFtApiWrite concepts concepts.length}}
2
+ <div
3
+ class="concept-list"
4
+ data-trackable="{{#if trackable}}{{trackable}}{{else}}concept-list{{/if}}">
5
+ {{#ifSome contentType conceptListTitle}}
6
+ <h2 class="concept-list__title">
7
+ {{#if conceptListTitle}}
8
+ {{conceptListTitle}}
9
+ {{else}}
10
+ Follow the topics in this {{contentType}}
11
+ {{/if}}
12
+ </h2>
13
+ {{/ifSome}}
14
+ <ul class="concept-list__list">
15
+ {{#each concepts}}
16
+ <li class="concept-list__list-item">
17
+ <a
18
+ href="{{relativeUrl}}"
19
+ data-trackable="{{#if conceptTrackable}}{{conceptTrackable}}{{else}}concept{{/if}}"
20
+ class="concept-list__concept">
21
+ {{prefLabel}}
22
+ </a>
23
+ {{> n-myft-ui/components/follow-button/follow-button
24
+ conceptId=id
25
+ name=prefLabel
26
+ }}
27
+ </li>
28
+ {{/each}}
29
+ </ul>
30
+ </div>
31
+ {{/ifAll}}
@@ -0,0 +1,5 @@
1
+ <input
2
+ data-myft-csrf-token
3
+ value="{{#if @root.cacheablePersonalisedUrl}}{{@root.csrfToken}}{{/if}}"
4
+ type="hidden"
5
+ name="token">
@@ -0,0 +1,79 @@
1
+ {{#if @root.flags.myFtApiWrite}}
2
+ <form
3
+ class="n-myft-ui n-myft-ui--follow {{extraClasses}}"
4
+ method="GET"
5
+ data-myft-ui="follow"
6
+ data-concept-id="{{conceptId}}"
7
+ {{#if collectionName}}data-myft-tracking="collectionName={{collectionName}}"{{/if}}
8
+ {{#if followPlusDigestEmail}}
9
+ action="/__myft/api/core/follow-plus-digest-email/{{conceptId}}?method=put"
10
+ data-myft-ui-variant="followPlusDigestEmail"
11
+ {{else}}
12
+ {{#ifAll setFollowButtonStateToSelected @root.cacheablePersonalisedUrl}}
13
+ action="/myft/remove/{{conceptId}}"
14
+ data-js-action="/__myft/api/core/followed/concept/{{conceptId}}?method=delete"
15
+ {{else}}
16
+ action="/myft/add/{{conceptId}}"
17
+ data-js-action="/__myft/api/core/followed/concept/{{conceptId}}?method=put"
18
+ {{/ifAll}}
19
+ {{/if}}>
20
+ {{> n-myft-ui/components/csrf-token/input}}
21
+ <div
22
+ class="n-myft-ui__announcement o-normalise-visually-hidden"
23
+ aria-live="assertive"
24
+ data-pressed-text="Now following {{name}}."
25
+ data-unpressed-text="No longer following {{name}}."
26
+ ></div>
27
+ <button
28
+ {{#ifAll setFollowButtonStateToSelected @root.cacheablePersonalisedUrl}}
29
+ aria-label="Remove {{name}} from myFT"
30
+ title="Remove {{name}} from myFT"
31
+ data-alternate-label="Add {{name}} to myFT"
32
+ aria-pressed="true"
33
+ {{#if alternateText}}
34
+ data-alternate-text="{{alternateText}}"
35
+ {{else}}
36
+ {{#if buttonText}}
37
+ data-alternate-text="{{buttonText}}"
38
+ {{else}}
39
+ data-alternate-text="Add to myFT"
40
+ {{/if}}
41
+ {{/if}}
42
+ {{else}}
43
+ aria-pressed="false"
44
+ aria-label="Add {{name}} to myFT"
45
+ title="Add {{name}} to myFT"
46
+ data-alternate-label="Remove {{name}} from myFT"
47
+ {{#if alternateText}}
48
+ data-alternate-text="{{alternateText}}"
49
+ {{else}}
50
+ {{#if buttonText}}
51
+ data-alternate-text="{{buttonText}}"
52
+ {{else}}
53
+ data-alternate-text="Added"
54
+ {{/if}}
55
+ {{/if}}
56
+ {{/ifAll}}
57
+ class="{{extraButtonClasses}}
58
+ n-myft-follow-button
59
+ {{~#variant}} n-myft-follow-button--{{this}}{{/variant~}}"
60
+ data-concept-id="{{conceptId}}" {{! duplicated here for tracking}}
61
+ {{#if followPlusDigestEmail}}
62
+ data-trackable-context-messaging="add-to-myft-plus-digest-button"
63
+ {{/if}}
64
+ data-trackable="follow"
65
+ type="submit">
66
+ {{~#if buttonText~}}
67
+ {{buttonText}}
68
+ {{~else~}}
69
+ {{~#ifAll setFollowButtonStateToSelected @root.cacheablePersonalisedUrl~}}
70
+ Added
71
+ {{~else~}}
72
+ Add to myFT
73
+ {{~/ifAll~}}
74
+ {{~/if~}}
75
+ </button>
76
+ </form>
77
+ {{else}}
78
+ <!-- Add to myFT button hidden due to myFtApiWrite being off -->
79
+ {{/if}}
@@ -0,0 +1,47 @@
1
+ {{#if @root.flags.myFtApiWrite}}
2
+ <form class="n-myft-ui n-myft-ui--instant{{#if hideButtonText}} n-myft-ui--instant--hide-text{{/if}} {{extraClasses}}"
3
+ method="GET"
4
+ data-myft-ui="instant"
5
+ data-concept-id="{{conceptId}}"
6
+ action="/myft/add/{{conceptId}}?instant=true"
7
+ data-js-action="/__myft/api/core/followed/concept/{{conceptId}}?method=put">
8
+ {{> n-myft-ui/components/csrf-token/input}}
9
+ <input type="hidden" value="{{name}}" name="name">
10
+ {{#if directType}}
11
+ <input type="hidden" value="{{directType}}" name="directType">
12
+ {{else}}
13
+ <input type="hidden" value="http://www.ft.com/ontology/concept/Concept" name="directType">
14
+ {{/if}}
15
+ <button
16
+ aria-label="Get instant alerts for {{name}}"
17
+ {{#ifAll hasInstantAlert @root.cacheablePersonalisedUrl}}
18
+ aria-pressed="true"
19
+ {{else}}
20
+ aria-pressed="false"
21
+ {{/ifAll}}
22
+ class="n-myft-ui__button
23
+ {{#variant}} n-myft-ui__button--{{this}}{{/variant}}
24
+ {{#size}} n-myft-ui__button--{{this}}{{/size}}
25
+ n-myft-ui__button--instant
26
+ n-myft-ui__button--instant-light"
27
+ data-alternate-label="Stop instant alerts for {{name}}"
28
+ {{#if alternateText}}
29
+ data-alternate-text="{{alternateText}}"
30
+ {{else}}
31
+ {{#if buttonText}}
32
+ data-alternate-text="{{buttonText}}"
33
+ {{else}}
34
+ data-alternate-text="Instant alerts"
35
+ {{/if}}
36
+ {{/if}}
37
+ data-concept-id="{{conceptId}}" {{! duplicated here for tracking}}
38
+ data-trackable="instant"
39
+ title="Get instant alerts for {{name}}"
40
+ name="_rel.instant"
41
+ value="{{#if hasInstantAlert}}false{{else}}true{{/if}}"
42
+ type="submit"
43
+ >{{#if buttonText}}{{buttonText}}{{else}}Instant alerts{{/if}}</button>
44
+ </form>
45
+ {{else}}
46
+ <!-- Instant alert button hidden due to myFtApiWrite being off -->
47
+ {{/if}}
@@ -0,0 +1,20 @@
1
+ {{#if showPrioritiseButton}}
2
+ <span class="myft-pin-divider"></span>
3
+ <div class="myft-pin-button-wrapper">
4
+ <form method="post" action="/__myft/api/core/prioritised/concept/{{id}}?method={{#if prioritised}}delete{{else}}put{{/if}}" data-myft-prioritise>
5
+ {{> n-myft-ui/components/csrf-token/input }}
6
+ <input type="hidden" value="{{name}}" name="name"> {{#if directType}}
7
+ <input type="hidden" value="{{directType}}" name="directType"> {{else}}
8
+ <input type="hidden" value="http://www.ft.com/ontology/concept/Concept" name="directType"> {{/if}}
9
+ <div
10
+ class="n-myft-ui__announcement o-normalise-visually-hidden"
11
+ aria-live="assertive"
12
+ data-pressed-text="{{name}} pinned in myFT."
13
+ data-unpressed-text="Unpinned {{name}} from myFT."
14
+ ></div>
15
+ <button id="myft-pin-button__{{id}}" class="myft-pin-button" data-prioritise-button data-trackable="prioritised" data-concept-id="{{id}}" data-prioritised="{{#if prioritised}}true{{else}}false{{/if}}"
16
+ aria-label="{{#if prioritised}}Unpin{{else}}Pin{{/if}} {{name}} {{#if prioritised}}from{{else}}in{{/if}} myFT" aria-pressed="{{#if prioritised}}true{{else}}false{{/if}}" title="{{#if prioritised}}Unpin{{else}}Pin{{/if}} {{name}}">
17
+ </button>
18
+ </form>
19
+ </div>
20
+ {{/if}}
@@ -0,0 +1,68 @@
1
+ {{#if @root.flags.myFtApiWrite}}
2
+ <form class="n-myft-ui n-myft-ui--save" method="GET"
3
+ data-content-id="{{contentId}}"
4
+ data-myft-ui="saved"
5
+ action="/myft/save/{{contentId}}"
6
+ data-js-action="/__myft/api/core/saved/content/{{contentId}}?method=put"
7
+ {{#ifEquals @root.flags.professorLists 'variant'}}data-myft-ui-variant="createListAndSaveArticleVariant"{{/ifEquals}}>
8
+ {{> n-myft-ui/components/csrf-token/input}}
9
+ <div
10
+ class="n-myft-ui__announcement o-normalise-visually-hidden"
11
+ aria-live="assertive"
12
+ data-pressed-text="Article saved in My FT."
13
+ data-unpressed-text="Removed article from My FT."
14
+ ></div>
15
+ <button
16
+ type="submit"
17
+ class="{{#if saveButtonWithIcon}}n-myft-ui__save-button-with-icon{{else}}n-myft-ui__button{{#variant}} n-myft-ui__button--{{this}}{{/variant}}{{/if}}"
18
+ data-trackable="{{#if trackableId}}{{trackableId}}{{else}}save-for-later{{/if}}"
19
+ {{#if isSaved}}
20
+ {{!-- The value of alternate label needs to be the opposite of label / the current saved state. This allows the client side JS to toggle the labels on state changes --}}
21
+ title="{{#if title}}{{title}} is{{/if}} Saved to myFT"
22
+ aria-label="{{#if title}}{{title}} is{{/if}} Saved to myFT"
23
+ data-alternate-label="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
24
+ aria-pressed="true"
25
+ {{else}}
26
+ title="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
27
+ aria-label="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
28
+ data-alternate-label="{{#if title}}{{title}} is{{/if}} Saved to myFT"
29
+ aria-pressed="false"
30
+ {{/if}}
31
+ {{#unlessEquals appIsStreamPage true}}
32
+ {{#if saveButtonWithIcon}}
33
+ data-text-variant="save-button-with-icon-copy"
34
+ {{else}}
35
+ data-text-variant="save-button-longer-copy"
36
+ {{/if}}
37
+ {{/unlessEquals}}
38
+ {{#if alternateText}}
39
+ data-alternate-text="{{alternateText}}"
40
+ {{else}}
41
+ {{#if isSaved}}
42
+ data-alternate-text="Save&nbsp;"
43
+ {{else}}
44
+ data-alternate-text="Saved&nbsp;"
45
+ {{/if}}
46
+ {{/if}}
47
+ data-content-id="{{contentId}}" {{! duplicated here for tracking}}
48
+ >
49
+ {{#if saveButtonWithIcon}}
50
+ <span class="save-button-with-icon-copy" data-variant-label>{{#if buttonText~}}
51
+ {{buttonText}}
52
+ {{~else~}}
53
+ {{#if isSaved}}Saved{{else}}Save{{/if}}
54
+ {{~/if}}</span>
55
+ {{else}}
56
+ {{#if buttonText}}{{buttonText}}{{else}}
57
+ {{#unlessEquals appIsStreamPage true}}
58
+ <span class="save-button-longer-copy" data-variant-label>{{#if isSaved}}Saved&nbsp;{{else}}Save&nbsp;{{/if}}</span><span class="n-myft-ui__button--viewport-large" aria-hidden="true">to myFT</span>
59
+ {{else}}
60
+ <span>{{#if isSaved}}Saved{{else}}Save{{/if}}</span>
61
+ {{/unlessEquals}}
62
+ {{/if}}
63
+ {{/if}}
64
+ </button>
65
+ </form>
66
+ {{else}}
67
+ <!-- Save button hidden due to myFtApiWrite being off -->
68
+ {{/if }}
@@ -2,12 +2,12 @@
2
2
  // the detail => https://github.com/date-fns/date-fns/blob/HEAD/CHANGELOG.md#200---2019-08-20
3
3
  // By adding validation for dates before their functions allows us to know it when unexpected value passed.
4
4
 
5
- import isTodayOriginal from 'date-fns/src/isToday';
6
- import isAfterOriginal from 'date-fns/src/isAfter';
7
- import addMinutesOriginal from 'date-fns/src/addMinutes';
8
- import startOfDayOriginal from 'date-fns/src/startOfDay';
9
- import isValidOriginal from 'date-fns/src/isValid';
10
- import parseISO from 'date-fns/src/parseISO';
5
+ import isTodayOriginal from "date-fns/src/isToday";
6
+ import isAfterOriginal from "date-fns/src/isAfter";
7
+ import addMinutesOriginal from "date-fns/src/addMinutes";
8
+ import startOfDayOriginal from "date-fns/src/startOfDay";
9
+ import isValidOriginal from "date-fns/src/isValid";
10
+ import parseISO from "date-fns/src/parseISO";
11
11
 
12
12
  const isValid = (date) => {
13
13
  if (!isValidOriginal(date)) {
package/demos/app.js CHANGED
@@ -1,17 +1,11 @@
1
- require('sucrase/register');
2
1
  const nExpress = require('@financial-times/n-express');
3
2
  const chalk = require('chalk');
4
3
  const errorHighlight = chalk.bold.red;
5
4
  const highlight = chalk.bold.green;
6
- const { PageKitReactJSX } = require('@financial-times/dotcom-server-react-jsx');
7
- const fs = require('fs');
8
5
  const path = require('path');
9
6
  const handlebars = require('handlebars');
10
7
  const { PageKitHandlebars, helpers } = require('@financial-times/dotcom-server-handlebars');
11
8
 
12
- const demoJSX = require('./templates/demo').default;
13
- const demoLayoutSource = fs.readFileSync(path.join(__dirname, './templates/demo-layout.html'),'utf8').toString();
14
-
15
9
  const fixtures = {
16
10
  followButton: require('./fixtures/follow-button'),
17
11
  saveButton: require('./fixtures/save-button'),
@@ -37,43 +31,26 @@ const app = module.exports = nExpress({
37
31
 
38
32
  app.set('views', path.join(__dirname, '/templates'));
39
33
  app.set('view engine', '.html');
40
-
41
34
  app.engine('.html', new PageKitHandlebars({
42
35
  cache: false,
43
36
  handlebars,
44
- helpers
37
+ helpers: {
38
+ ...helpers
39
+ }
45
40
  }).engine);
46
41
 
47
42
  app.use('/public', nExpress.static(path.join(__dirname, '../public'), { redirect: false }));
48
43
 
49
- const jsxRenderer = (new PageKitReactJSX({ includeDoctype: false }));
50
-
51
44
  app.get('/', (req, res) => {
52
45
  res.render('demo', Object.assign({
53
- title: 'n-myft-ui demo',
54
- flags: {
55
- myFtApi: true,
56
- myFtApiWrite: true
57
- },
58
- }, fixtures));
59
- });
60
-
61
- app.get('/demo-jsx', async (req, res) => {
62
- let demo = await jsxRenderer.render(demoJSX, Object.assign({
63
46
  title: 'n-myft-ui demo',
64
47
  flags: {
65
48
  myFtApi: true,
66
49
  myFtApiWrite: true
67
50
  }
68
51
  }, fixtures));
69
-
70
- let template = handlebars.compile(demoLayoutSource);
71
- let result = template({body: demo});
72
-
73
- res.send(result);
74
52
  });
75
53
 
76
-
77
54
  function runPa11yTests () {
78
55
  const spawn = require('child_process').spawn;
79
56
  const pa11y = spawn('pa11y-ci');
@@ -32,7 +32,7 @@
32
32
  </h2>
33
33
 
34
34
  {{#followButton}}
35
- {{{renderReactComponent localPath="components/follow-button/follow-button" flags=@root.flags}}}
35
+ {{> n-myft-ui/components/follow-button/follow-button}}
36
36
  {{/followButton}}
37
37
 
38
38
  <h2
@@ -41,51 +41,52 @@
41
41
  </h2>
42
42
 
43
43
  {{#followButton}}
44
- {{{renderReactComponent localPath="components/follow-button/follow-button" buttonText=name flags=@root.flags}}}
44
+ {{> n-myft-ui/components/follow-button/follow-button buttonText=name}}
45
45
  {{/followButton}}
46
46
 
47
47
  {{#saveButton}}
48
48
  <h2 class="demo-section__title">
49
49
  Save button
50
50
  </h2>
51
- {{{renderReactComponent localPath="components/save-for-later/save-for-later" flags=@root.flags title=title contentId=contentId }}}
51
+ {{> n-myft-ui/components/save-for-later/save-for-later }}
52
52
  {{/saveButton}}
53
53
 
54
54
  {{#saveButton}}
55
55
  <h2 class="demo-section__title">
56
56
  Unsave button
57
57
  </h2>
58
- {{{renderReactComponent localPath="components/save-for-later/save-for-later" flags=@root.flags title=title contentId=contentId isSaved=true }}}
58
+ {{> n-myft-ui/components/save-for-later/save-for-later isSaved=true }}
59
59
  {{/saveButton}}
60
60
 
61
61
  {{#saveButton}}
62
62
  <h2 class="demo-section__title">
63
63
  Save button with icon
64
64
  </h2>
65
- {{{renderReactComponent localPath="components/save-for-later/save-for-later" flags=@root.flags title=title contentId=contentId saveButtonWithIcon=true }}}
65
+ {{> n-myft-ui/components/save-for-later/save-for-later saveButtonWithIcon=true }}
66
66
  {{/saveButton}}
67
67
 
68
68
  {{#saveButton}}
69
69
  <h2 class="demo-section__title">
70
70
  Unsave button with icon
71
71
  </h2>
72
- {{{renderReactComponent localPath="components/save-for-later/save-for-later" flags=@root.flags title=title contentId=contentId saveButtonWithIcon=true isSaved=true }}}
72
+ {{> n-myft-ui/components/save-for-later/save-for-later isSaved=true saveButtonWithIcon=true }}
73
73
  {{/saveButton}}
74
74
 
75
75
  <h2 class="demo-section__title">
76
76
  Pin button
77
77
  </h2>
78
78
  {{#each pinButton}}
79
- {{{renderReactComponent localPath="components/pin-button/pin-button" flags=@root.flags title=title id=id name=name directType=directType showPrioritiseButton=showPrioritiseButton }}}
79
+ {{> n-myft-ui/components/pin-button/pin-button }}
80
80
  {{/each}}
81
81
 
82
82
  {{#instantAlert}}
83
83
  <h2 class="demo-section__title">
84
84
  Instant Alert
85
85
  </h2>
86
- {{{renderReactComponent localPath="components/instant-alert/instant-alert" flags=@root.flags title=title conceptId=id name=name directType=directType }}}
86
+ {{> n-myft-ui/components/instant-alert/instant-alert }}
87
87
  {{/instantAlert}}
88
88
 
89
+
89
90
  </div>
90
91
  </div>
91
92
  </section>
@@ -448,7 +449,7 @@
448
449
 
449
450
  {{#collections}}
450
451
  <div data-o-grid-colspan="3">
451
- {{{renderReactComponent localPath="components/collections/collections" flags=@root.flags concepts=this.concepts title=this.title liteStyle=this.liteStyle collectionName=this.collectionName trackable=this.trackable}}}
452
+ {{> n-myft-ui/components/collections/collections }}
452
453
  </div>
453
454
  {{/collections}}
454
455
  </div>
@@ -470,7 +471,7 @@
470
471
 
471
472
  {{#each conceptList}}
472
473
  <div data-o-grid-colspan="3">
473
- {{{renderReactComponent localPath="components/concept-list/concept-list" flags=@root.flags concepts=this.concepts contentType=this.contentType conceptListTitle=this.conceptListTitle trackable=this.trackable}}}
474
+ {{> n-myft-ui/components/concept-list/concept-list }}
474
475
  </div>
475
476
  {{/each}}
476
477
  </div>
package/myft/main.scss CHANGED
@@ -173,3 +173,148 @@ $spacing-unit: 20px;
173
173
  }
174
174
 
175
175
  }
176
+
177
+ .share-nav {
178
+ &.data-overlap-initialised {
179
+ .o-overlay {
180
+ transition: opacity 0.15s ease-in;
181
+ opacity: 0;
182
+ z-index: -1;
183
+ }
184
+ }
185
+
186
+ .myft-ui-create-list-variant {
187
+ border-radius: 10px;
188
+ border: 1px solid oColorsByName('black-5');
189
+ background: oColorsByName('white-80');
190
+
191
+ .o-overlay__heading {
192
+ border-radius: 10px 10px 0 0;
193
+ background: oColorsByName('white-60');
194
+ @include oTypographySans($scale: 2);
195
+ color: oColorsByName('black-80');
196
+ }
197
+
198
+ .o-overlay__content {
199
+ @include oTypographySans($scale: 0);
200
+ color: oColorsByName('black-80');
201
+ padding: 0;
202
+ }
203
+
204
+ .o-overlay__title {
205
+ margin: 8px 14px 0 8px;
206
+ }
207
+
208
+ &-container {
209
+ display: block;
210
+ width: 340px;
211
+ top: 115.5px;
212
+ left: 50px;
213
+ }
214
+
215
+ &-add {
216
+ border: 0;
217
+ background: none;
218
+ @include oTypographySans($scale: 1, $weight: 'semibold');
219
+ color: oColorsByName('black-80');
220
+
221
+ padding-left: 0;
222
+ margin-left: -8px;
223
+
224
+ &:hover {
225
+ text-decoration: underline;
226
+ }
227
+
228
+ &::before {
229
+ content: '';
230
+ @include oIconsContent(
231
+ 'plus',
232
+ oColorsByName('black-80'),
233
+ 28,
234
+ $iconset-version: 1
235
+ );
236
+ vertical-align: middle;
237
+ margin-top: -2px;
238
+ }
239
+ }
240
+
241
+ &-add-description {
242
+ margin: 4px 0;
243
+ }
244
+
245
+ &-heading {
246
+ &::before {
247
+ content: '';
248
+ @include oIconsContent(
249
+ 'tick',
250
+ oColorsByName('teal'),
251
+ 32,
252
+ $iconset-version: 1
253
+ );
254
+ vertical-align: middle;
255
+ margin-top: -2px;
256
+ }
257
+ }
258
+
259
+ &-footer {
260
+ border-top: 1px solid oColorsByName('black-5');
261
+ padding: 16px;
262
+ }
263
+
264
+ &-icon {
265
+ &::before {
266
+ content: "";
267
+ display: inline-block;
268
+ background-repeat: no-repeat;
269
+ background-size: contain;
270
+ background-position: 50%;
271
+ background-color: transparent;
272
+ background-image: url(https://www.ft.com/__origami/service/image/v2/images/raw/ftlogo-v1:brand-myft?source=next-article);
273
+ width: 42px;
274
+ height: 42px;
275
+ vertical-align: middle;
276
+ margin-top: -2px;
277
+ }
278
+
279
+ &-visually-hidden {
280
+ clip: rect(0 0 0 0);
281
+ clip-path: inset(50%);
282
+ height: 1px;
283
+ overflow: hidden;
284
+ position: absolute;
285
+ white-space: nowrap;
286
+ width: 1px;
287
+ }
288
+ }
289
+
290
+ &-form {
291
+ display: flex;
292
+ width: calc(100% - 32px);
293
+ justify-content: space-between;
294
+ height: 40px;
295
+ gap: 8px;
296
+ padding: 0 16px 16px;
297
+
298
+ & > * {
299
+ flex: 1 1 auto;
300
+ }
301
+
302
+ .o-forms-input {
303
+ margin-top: 0;
304
+ }
305
+ }
306
+
307
+ &-lists {
308
+ padding: 16px 16px 0;
309
+ @include oTypographySans($scale: 1);
310
+ &-text {
311
+ @include oTypographySans($weight: 'semibold');
312
+ color: oColorsByName('black-80');
313
+ margin-bottom: 16px;
314
+ }
315
+ &-container {
316
+ margin-top: 0;
317
+ }
318
+ }
319
+ }
320
+ }