@atlaskit/editor-plugin-show-diff 15.1.6 → 15.1.7

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 (23) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +5 -4
  3. package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +25 -4
  4. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +40 -14
  5. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeView.js +14 -0
  6. package/dist/cjs/ui/ContributorTag/buildContributorTagDom.js +70 -14
  7. package/dist/cjs/ui/ContributorTag/contributorTagController.js +169 -150
  8. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +5 -4
  9. package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +25 -4
  10. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +40 -14
  11. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeView.js +14 -0
  12. package/dist/es2019/ui/ContributorTag/buildContributorTagDom.js +69 -13
  13. package/dist/es2019/ui/ContributorTag/contributorTagController.js +164 -104
  14. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +5 -4
  15. package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +25 -4
  16. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +40 -14
  17. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeView.js +14 -0
  18. package/dist/esm/ui/ContributorTag/buildContributorTagDom.js +69 -13
  19. package/dist/esm/ui/ContributorTag/contributorTagController.js +171 -152
  20. package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +8 -2
  21. package/dist/types/ui/ContributorTag/buildContributorTagDom.d.ts +32 -3
  22. package/dist/types/ui/ContributorTag/contributorTagController.d.ts +32 -12
  23. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 15.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [`e80305319abbb`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e80305319abbb) -
8
+ CCI-19338: Gate Review moment on `platform_editor_ai_streaming_ux_experience_m1` and
9
+ `platform_editor_ai_xstate_migration` only, dropping
10
+ `platform_editor_ai_new_aifc_editor_experience` and its FE/BE params. Optional Review moment
11
+ slices now read prefixed tokens from `platform_editor_ai_streaming_ux_m1_config`.
12
+ - [`3dc7417891a0c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3dc7417891a0c) -
13
+ Render a `blockquote` inside a diff widget decoration as `display: flow-root` so the diff
14
+ indicator bar spans the quote's full height instead of a single line. Behind the existing
15
+ `platform_editor_ai_show_diff_patch_1` gate; with the gate off the quote keeps its `inline-block`
16
+ display as before.
17
+
18
+ Editor CSS renders `blockquote` as `inline-block`, which both establishes a block formatting
19
+ context and makes the quote an atomic inline-level box. The widget container is an inline `span`,
20
+ so the bar's anchor rect is the union of that span's fragments — and an inline box takes its
21
+ height from its font metrics, not from an inline-level child. A quote therefore contributed only
22
+ one line-height, and the bar showed as a stub beside it; most visible when reviewing an AI
23
+ suggestion that wraps content in a quote. `flow-root` is block-level and still establishes the
24
+ formatting context, so the container gets a block fragment sized to the quote while the quote's
25
+ own geometry is unchanged. Every other block node is already block-level and is unaffected.
26
+
27
+ - [`8815e3a163409`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8815e3a163409) -
28
+ Restyle contributor diff tags to read as a label on the change they caption: flush against it,
29
+ square bottom corners, no bottom border or shadow, and sized to their own content up to a maximum
30
+ width. A tag now paints above the diff highlights instead of below them, so a highlight on the
31
+ line it overlays can no longer slice through it, and it is clipped to its own box so it still
32
+ cannot paint over the change it captions. A tag is now filled with its accent colour's bolder tone
33
+ and labelled in inverse text, rather than the subtlest tint its highlight is drawn in. Tags now
34
+ fade and rise in and out rather than snapping, with a `prefers-reduced-motion` opt-out. Behind the
35
+ `confluence_ncs_step_diffing_version_history` gate.
36
+ - Updated dependencies
37
+
3
38
  ## 15.1.6
4
39
 
5
40
  ### Patch Changes
@@ -16,7 +16,7 @@ var _transform = require("@atlaskit/editor-prosemirror/transform");
16
16
  var _view = require("@atlaskit/editor-prosemirror/view");
17
17
  var _unsafeExpValNoExposure = require("@atlaskit/platform-feature-experiments/unsafe-exp-val-no-exposure");
18
18
  var _fg = require("@atlaskit/platform-feature-flags/fg");
19
- var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
19
+ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
20
20
  var _areDocsEqualByBlockStructureAndText = require("../areDocsEqualByBlockStructureAndText");
21
21
  var _createAnchorDecorationWidgets = require("../decorations/createAnchorDecorationWidgets");
22
22
  var _createBlockChangedDecoration = require("../decorations/createBlockChangedDecoration");
@@ -521,8 +521,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
521
521
  // gets highlighted, and structural gaps never do.
522
522
  var isSmartNodeLevel = diffType === 'smart' && (0, _fg.fg)('platform_editor_ai_smart_diff') && (0, _helpers.smartChangeLevel)(change) === 'node';
523
523
  // For a large inserted table, skip the per-cell inline decorations that
524
- // freeze the browser on re-render. Only active in the AIFC experience.
525
- var useCoarseTableDecoration = isSmartNodeLevel && (0, _expValEquals.expValEquals)('platform_editor_ai_new_aifc_editor_experience', 'isBackendReviewMomentEnabled', true) && isLargeInsertedTableRange(tr.doc, change.fromB, change.toB);
524
+ // freeze the browser on re-render. Only active when Review moment is
525
+ // eligible (xstate + M1).
526
+ var useCoarseTableDecoration = isSmartNodeLevel && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_ai_xstate_migration', 'isEnabled', true) && (0, _unsafeExpValNoExposure.UNSAFE_expValNoExposure)('platform_editor_ai_streaming_ux_experience_m1', 'isEnabled', false) === true && isLargeInsertedTableRange(tr.doc, change.fromB, change.toB);
526
527
  // Whether the deleted-content widget will actually be rendered for this
527
528
  // change. Used to decide if indicator anchor positions should be adjusted
528
529
  // inward — when the widget is present the anchor must stay at the block
@@ -721,7 +722,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
721
722
  })));
722
723
  // If the original node position is known (e.g. a panel type change), also render
723
724
  // the old block node as a "deleted" widget so the reviewer sees the before/after.
724
- var isSmartNodeLevelAttrChange = diffType === 'smart' && (0, _fg.fg)('platform_editor_ai_smart_diff') && (0, _expValEquals.expValEquals)('platform_editor_ai_new_aifc_editor_experience', 'isEnabled', true);
725
+ var isSmartNodeLevelAttrChange = diffType === 'smart' && (0, _fg.fg)('platform_editor_ai_smart_diff') && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_ai_xstate_migration', 'isEnabled', true) && (0, _unsafeExpValNoExposure.UNSAFE_expValNoExposure)('platform_editor_ai_streaming_ux_experience_m1', 'isEnabled', false) === true;
725
726
  if (isSmartNodeLevelAttrChange && change.fromA !== undefined && change.toA !== undefined) {
726
727
  var placeBelow = deletedDiffPlacement === 'bottom';
727
728
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createNodeChangedDecorationWidget.createNodeChangedDecorationWidget)(_objectSpread(_objectSpread({
@@ -135,6 +135,18 @@ var bgSubtlerPressedMap = {
135
135
  gray: "var(--ds-background-accent-gray-subtler-pressed, #8C8F97)",
136
136
  lime: "var(--ds-background-accent-lime-subtler-pressed, #B3DF72)"
137
137
  };
138
+ var bgBolderMap = {
139
+ green: "var(--ds-background-accent-green-bolder, #1F845A)",
140
+ teal: "var(--ds-background-accent-teal-bolder, #227D9B)",
141
+ blue: "var(--ds-background-accent-blue-bolder, #1868DB)",
142
+ purple: "var(--ds-background-accent-purple-bolder, #964AC0)",
143
+ red: "var(--ds-background-accent-red-bolder, #C9372C)",
144
+ orange: "var(--ds-background-accent-orange-bolder, #BD5B00)",
145
+ yellow: "var(--ds-background-accent-yellow-bolder, #946F00)",
146
+ magenta: "var(--ds-background-accent-magenta-bolder, #AE4787)",
147
+ gray: "var(--ds-background-accent-gray-bolder, #6B6E76)",
148
+ lime: "var(--ds-background-accent-lime-bolder, #5B7F24)"
149
+ };
138
150
  var borderAccentMap = {
139
151
  green: "var(--ds-border-accent-green, #22A06B)",
140
152
  teal: "var(--ds-border-accent-teal, #2898BD)",
@@ -168,6 +180,9 @@ function bgSubtlestPressed(color) {
168
180
  function bgSubtler(color) {
169
181
  return bgSubtlerMap[color];
170
182
  }
183
+ function bgBolder(color) {
184
+ return bgBolderMap[color];
185
+ }
171
186
  function bgSubtlerPressed(color) {
172
187
  return bgSubtlerPressedMap[color];
173
188
  }
@@ -178,12 +193,18 @@ function textAccent(color) {
178
193
  return textAccentMap[color];
179
194
  }
180
195
 
181
- /** Presentation tokens for one diff colour, shared by highlights and contributor tags. */
196
+ /**
197
+ * Presentation tokens for a contributor tag in one diff colour.
198
+ *
199
+ * A `bolder` fill rather than the `subtlest` tint the highlight uses: the tag is a label on the
200
+ * change, and at tag size a tint reads as a second, weaker highlight sitting above the real one.
201
+ * `inverse` is the only text tone that reads on a bolder fill, and it needs no per-colour map —
202
+ * which is also why the tag carries no border: the fill alone bounds it.
203
+ */
182
204
  function getAccentTokens(color) {
183
205
  return {
184
- background: bgSubtlest(color),
185
- border: borderAccent(color),
186
- text: textAccent(color)
206
+ background: bgBolder(color),
207
+ text: "var(--ds-text-inverse, #FFFFFF)"
187
208
  };
188
209
  }
189
210
 
@@ -10,6 +10,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
10
10
  var _lazyNodeView = require("@atlaskit/editor-common/lazy-node-view");
11
11
  var _view = require("@atlaskit/editor-prosemirror/view");
12
12
  var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
13
+ var _buildContributorTagDom = require("../../ui/ContributorTag/buildContributorTagDom");
13
14
  var _isExtendedEnabled = require("../isExtendedEnabled");
14
15
  var _hasVisibleContent = require("../utils/hasVisibleContent");
15
16
  var _factory = require("./colorSchemes/factory");
@@ -24,6 +25,25 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
24
25
  var displayNoneStyle = (0, _lazyNodeView.convertToInlineCss)({
25
26
  display: 'none'
26
27
  });
28
+
29
+ /**
30
+ * Stacks the change's highlight below its contributor tag, so no highlight can slice through a tag:
31
+ * a tag overlays the line *above* its own change, and a highlight already on that line — the tail of
32
+ * this change, or another change entirely — would otherwise paint straight over it.
33
+ *
34
+ * The tag still reads as attached to the change rather than laid on top of it, because it cannot
35
+ * paint over this highlight at all: its bottom edge is pinned to the highlight's top edge and
36
+ * clipped there. See `CONTRIBUTOR_TAG_Z_INDEX`.
37
+ *
38
+ * prosemirror-view places the tag's host widget as a *sibling* of this decoration's span, so
39
+ * painting order is decided by stacking level — and the host is absolutely positioned at
40
+ * `CONTRIBUTOR_TAG_Z_INDEX`. `position: relative` is what makes `z-index` apply to an otherwise
41
+ * static inline box; it adds no offset.
42
+ */
43
+ var stackBelowContributorTagStyle = (0, _lazyNodeView.convertToInlineCss)({
44
+ position: 'relative',
45
+ zIndex: _buildContributorTagDom.CONTRIBUTOR_TAG_Z_INDEX - 1
46
+ });
27
47
  var getColorScheme = function getColorScheme(colorScheme) {
28
48
  return _schemes.colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard'];
29
49
  };
@@ -183,8 +203,23 @@ var createInlineChangedDecoration = exports.createInlineChangedDecoration = func
183
203
  });
184
204
  var isAtomicInlineInsertion = isAtomicInlineNode && isInserted;
185
205
  var atomicInlineAttrs = isAtomicInlineInsertion ? resolveAtomicInlineAttrs(inlineNodeName, colorScheme, colors) : undefined;
206
+
207
+ // Built from the raw change range, not the indicator anchors resolved below: a tag lines up with
208
+ // the changed text, while the bar's anchors are held on a block boundary when a deleted widget
209
+ // renders beside them.
210
+ //
211
+ // Built up here, ahead of where it is pushed, so the highlight's stacking below keys off whether a
212
+ // tag exists rather than re-deriving the condition and risking disagreement.
213
+ var tagWidget = canTagChange && doc ? (0, _createContributorTagWidget.createContributorTagWidget)({
214
+ doc: doc,
215
+ from: change.fromB,
216
+ to: change.toB,
217
+ diffId: diffId,
218
+ mountContext: tagMountContext
219
+ }) : undefined;
220
+ var inlineStyle = [style, atomicInlineAttrs === null || atomicInlineAttrs === void 0 ? void 0 : atomicInlineAttrs.styleSuffix, tagWidget ? stackBelowContributorTagStyle : undefined].filter(Boolean).join('');
186
221
  var decorations = [_view.Decoration.inline(change.fromB, change.toB, _objectSpread(_objectSpread(_objectSpread({
187
- style: atomicInlineAttrs ? "".concat(style).concat(atomicInlineAttrs.styleSuffix) : style
222
+ style: inlineStyle
188
223
  }, atomicInlineAttrs && {
189
224
  class: atomicInlineAttrs.className
190
225
  }), revealed && (0, _defineProperty2.default)({}, _revealStyles.REVEAL_ATTR, revealed.role)), {}, {
@@ -235,19 +270,10 @@ var createInlineChangedDecoration = exports.createInlineChangedDecoration = func
235
270
  })));
236
271
  }
237
272
 
238
- // Built from the raw change range, not the anchors above: a tag lines up with the changed text,
239
- // while the bar's anchors are held on a block boundary when a deleted widget renders beside them.
240
- if (canTagChange && doc) {
241
- var tagWidget = (0, _createContributorTagWidget.createContributorTagWidget)({
242
- doc: doc,
243
- from: change.fromB,
244
- to: change.toB,
245
- diffId: diffId,
246
- mountContext: tagMountContext
247
- });
248
- if (tagWidget) {
249
- decorations.push(tagWidget);
250
- }
273
+ // Pushed after the indicator anchors so the decoration order is unchanged — see `tagWidget` above
274
+ // for why it is built before them.
275
+ if (tagWidget) {
276
+ decorations.push(tagWidget);
251
277
  }
252
278
  return decorations;
253
279
  };
@@ -10,6 +10,7 @@ var _lazyNodeView = require("@atlaskit/editor-common/lazy-node-view");
10
10
  var _messages = require("@atlaskit/editor-common/messages");
11
11
  var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
12
12
  var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
13
+ var _fg = require("@atlaskit/platform-feature-flags/fg");
13
14
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
14
15
  var _isExtendedEnabled = require("../../isExtendedEnabled");
15
16
  var _revealStyles = require("../revealStyles");
@@ -284,6 +285,16 @@ var applyInlineLeafNodeStyles = function applyInlineLeafNodeStyles(_ref8) {
284
285
  });
285
286
  });
286
287
  };
288
+
289
+ /**
290
+ * Editor CSS makes `blockquote` `inline-block` for its block formatting context. Inside a widget
291
+ * that collapses the indicator bar: the container is an inline `span`, so its anchor rect comes from
292
+ * font metrics, not from an inline-level child. `flow-root` keeps the formatting context but is
293
+ * block-level — unlike `block`, which lets the child paragraph's top margin collapse out.
294
+ */
295
+ var quoteBlockLevelStyle = (0, _lazyNodeView.convertToInlineCss)({
296
+ display: 'flow-root'
297
+ });
287
298
  var applyTextLikeBlockNodeStyles = function applyTextLikeBlockNodeStyles(_ref9) {
288
299
  var element = _ref9.element,
289
300
  targetNode = _ref9.targetNode,
@@ -547,6 +558,9 @@ var wrapBlockNodeView = exports.wrapBlockNodeView = function wrapBlockNodeView(_
547
558
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
548
559
  highlightInlineLeafNodes: highlightInlineLeafNodes
549
560
  });
561
+ if (targetNode.type.name === 'blockquote' && (0, _fg.fg)('platform_editor_ai_show_diff_patch_1')) {
562
+ appendStyleToElement(nodeView, quoteBlockLevelStyle);
563
+ }
550
564
  dom.append(nodeView);
551
565
  return;
552
566
  }
@@ -4,50 +4,105 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.buildContributorTagDom = exports.MIN_TAG_WIDTH = exports.CONTRIBUTOR_TAG_TESTID = exports.CONTRIBUTOR_TAG_NAME_TESTID = void 0;
7
+ exports.buildContributorTagDom = exports.TAG_EXIT_FALLBACK_MS = exports.MAX_TAG_WIDTH = exports.CONTRIBUTOR_TAG_Z_INDEX = exports.CONTRIBUTOR_TAG_TESTID = exports.CONTRIBUTOR_TAG_REVEALED_ATTRIBUTE = exports.CONTRIBUTOR_TAG_NAME_TESTID = exports.CONTRIBUTOR_TAG_CLASS = void 0;
8
8
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
9
  var _lazyNodeView = require("@atlaskit/editor-common/lazy-node-view");
10
10
  var CONTRIBUTOR_TAG_TESTID = exports.CONTRIBUTOR_TAG_TESTID = 'diff-contributor-tag';
11
11
  var CONTRIBUTOR_TAG_NAME_TESTID = exports.CONTRIBUTOR_TAG_NAME_TESTID = 'diff-contributor-tag-name';
12
12
 
13
13
  /**
14
- * Floor for the tag width (~one 16px avatar plus padding), so the highlight-width clamp cannot
15
- * collapse the box on a very short highlight.
14
+ * Ceiling for the tag width. A constant rather than the width of the change: a change is routinely a
15
+ * word or two, and clamping to it ellipsised the contributor's name — the one thing the tag exists to
16
+ * show. Longer names are ellipsised into the tooltip.
16
17
  */
17
- var MIN_TAG_WIDTH = exports.MIN_TAG_WIDTH = '28px';
18
+ var MAX_TAG_WIDTH = exports.MAX_TAG_WIDTH = '200px';
19
+
20
+ /**
21
+ * The tag sits on the line above the change, so it has to paint over that line to be readable —
22
+ * including any diff highlight already on it, which would otherwise slice straight through the tag.
23
+ * Hence one level above `akEditorUnitZIndex`, where the highlights sit; exported because the
24
+ * change's own highlight is stacked one level below it — see `stackBelowContributorTagStyle` in
25
+ * `createInlineChangedDecoration`.
26
+ *
27
+ * Painting above its own highlight is only safe because the tag can never reach it: `bottom: 100%`
28
+ * puts the root's bottom edge exactly on the highlight's top edge, and the root's `overflow: clip`
29
+ * keeps every pixel the tag paints inside it.
30
+ */
31
+ var CONTRIBUTOR_TAG_Z_INDEX = exports.CONTRIBUTOR_TAG_Z_INDEX = 2;
32
+
33
+ /**
34
+ * The plugin's whole side of the tag's motion: the fade and the hidden state are
35
+ * `contributorTagStyles` in both EditorContentContainer stylesheets, keyed on this literal and the
36
+ * one below — rename in step. This package cannot import `@atlaskit/editor-core` at runtime, so the
37
+ * plugin emits the hook and editor-core owns the rule, as `VanillaTooltip` does with
38
+ * `VANILLA_TOOLTIP_DEFAULT_CLASS`.
39
+ */
40
+ var CONTRIBUTOR_TAG_CLASS = exports.CONTRIBUTOR_TAG_CLASS = 'ak-editor-diff-contributor-tag';
41
+
42
+ /** Toggled by the controller to move the tag between the fade's two ends. */
43
+ var CONTRIBUTOR_TAG_REVEALED_ATTRIBUTE = exports.CONTRIBUTOR_TAG_REVEALED_ATTRIBUTE = 'data-revealed';
44
+
45
+ /**
46
+ * Backstop for removing a fading-out tag: a cancelled transition fires no `transitionend`. Must stay
47
+ * above the fade's 600ms, which lives in another package's stylesheet and cannot be read back as a
48
+ * number — hence the wide margin. Raise in step with that duration.
49
+ */
50
+ var TAG_EXIT_FALLBACK_MS = exports.TAG_EXIT_FALLBACK_MS = 1200;
18
51
 
19
52
  // Positioned against the host widget its decoration renders on the change's first character:
20
53
  // `bottom: 100%` lifts the tag onto the line above, `inset-inline-start` starts it on that
21
54
  // character.
22
55
  var constraintStyle = (0, _lazyNodeView.convertToInlineCss)({
23
- display: 'block',
56
+ // `flex`, not `block`: a block box lays the tag on a line box whose strut is the *paragraph's*
57
+ // line-height (~24px) against the tag's ~20px, so `bottom: 100%` pins that leftover strut to the
58
+ // change and the tag floats above it. A flex container has no line box.
59
+ display: 'flex',
24
60
  position: 'absolute',
25
61
  bottom: '100%',
26
62
  insetInlineStart: 0,
63
+ // On the root, since that is the absolutely positioned box; the tag below fills it.
64
+ maxWidth: MAX_TAG_WIDTH,
27
65
  minWidth: 0,
28
- // The tag may cover surrounding text, so it has to paint over it. Matches `akEditorUnitZIndex`.
29
- zIndex: 1,
66
+ // This box's bottom edge is the join with the highlight, and the tag paints *above* that
67
+ // highlight — so anything spilling past this edge would read as the tag laid on top of the change
68
+ // rather than attached to it. The reveal's `translateY` is exactly that spill: it starts the tag
69
+ // 4px low, and clipping the part that hangs over the highlight turns the rise into an unfurl out
70
+ // of the join. `clip`, not `hidden`: `hidden` would make this a scroll container, and focusing the
71
+ // tag mid-reveal would scroll it 4px out of alignment for good.
72
+ //
73
+ // The tooltip is unaffected — it is a `popover`, so it paints in the top layer, which no
74
+ // ancestor's clip reaches.
75
+ overflow: 'clip',
76
+ zIndex: CONTRIBUTOR_TAG_Z_INDEX,
30
77
  // It renders inside the document and it is not content: dragging a selection across the change
31
78
  // must not select it.
32
79
  userSelect: 'none'
33
80
  });
34
81
 
35
- // `backgroundColor`, `borderBottomColor` and the visibility come from the model, and are set by the
36
- // controller.
82
+ // `backgroundColor` comes from the model, and is set by the controller. `opacity`, `pointer-events`
83
+ // and the transition between their two states are in `contributorTagStyles` — see
84
+ // `CONTRIBUTOR_TAG_CLASS`.
37
85
  var tagStyle = (0, _lazyNodeView.convertToInlineCss)({
38
86
  display: 'inline-flex',
39
87
  alignItems: 'center',
40
88
  gap: "var(--ds-space-050, 4px)",
41
- // Never wider than the highlight; overflow is ellipsised on the name below.
89
+ // Never wider than `MAX_TAG_WIDTH` on the root; overflow is ellipsised on the name below.
42
90
  maxWidth: '100%',
43
91
  minWidth: 0,
44
92
  overflow: 'hidden',
45
93
  paddingInline: "var(--ds-space-050, 4px)",
46
94
  paddingBlock: "var(--ds-space-025, 2px)",
47
- borderRadius: "var(--ds-radius-small, 4px)",
48
- borderBottomStyle: 'solid',
49
- borderBottomWidth: "var(--ds-border-width-selected, 2px)",
50
- boxShadow: "var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)",
95
+ // Top corners only: the bottom edge butts onto the change, and a rounded corner there would let
96
+ // the page background through at the join.
97
+ borderTopLeftRadius: "var(--ds-radius-small, 4px)",
98
+ borderTopRightRadius: "var(--ds-radius-small, 4px)",
99
+ borderBottomLeftRadius: 0,
100
+ borderBottomRightRadius: 0,
101
+ // Deliberately no bottom border: the change already carries the accent as its own underline, and
102
+ // a second rule directly above it reads as two objects rather than one label on one change.
103
+ //
104
+ // Deliberately no `elevation.shadow.overlay`: its `0 8px 12px` offset casts downwards onto the
105
+ // change, which reads as a gap between the tag and the content it captions.
51
106
  font: "var(--ds-font-body-small, normal 400 12px/16px \"Atlassian Sans\", ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)",
52
107
  whiteSpace: 'nowrap',
53
108
  boxSizing: 'border-box'
@@ -98,6 +153,7 @@ var createSpan = function createSpan(doc, style) {
98
153
  var buildContributorTagDom = exports.buildContributorTagDom = function buildContributorTagDom(doc) {
99
154
  var root = createSpan(doc, constraintStyle);
100
155
  var tag = createSpan(doc, tagStyle, {
156
+ class: CONTRIBUTOR_TAG_CLASS,
101
157
  'data-testid': CONTRIBUTOR_TAG_TESTID,
102
158
  // Deliberately no `aria-label`: it would be announced ahead of the element's contents, but
103
159
  // design requires the contributor *after* the change — hence the visually hidden label.