Skip to content

Implement outline properties on iOS - #46444

Closed
jorge-cab wants to merge 1 commit into
react:mainfrom
jorge-cab:export-D62273339
Closed

Implement outline properties on iOS#46444
jorge-cab wants to merge 1 commit into
react:mainfrom
jorge-cab:export-D62273339

Conversation

@jorge-cab

Copy link
Copy Markdown
Contributor

Summary:
This diff adds:

outline-width: https://developer.mozilla.org/en-US/docs/Web/CSS/outline-width
outline-color: https://developer.mozilla.org/en-US/docs/Web/CSS/outline-color
outline-style: https://developer.mozilla.org/en-US/docs/Web/CSS/outline-style
outline-offset: https://developer.mozilla.org/en-US/docs/Web/CSS/outline-offset

Using BackgroundStyleApplicator

Changelog: [iOS] [Added] - Outline properties outline-width, outline-color, outline-style & outline-offset

Differential Revision: D62273339

@facebook-github-botfacebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Facebook Partner: Facebook Partner labels Sep 11, 2024
@facebook-github-bot

Copy link
Copy Markdown
Contributor

This pull request was exported from Phabricator. Differential Revision: D62273339

@facebook-github-bot

Copy link
Copy Markdown
Contributor

This pull request was exported from Phabricator. Differential Revision: D62273339

@facebook-github-bot

Copy link
Copy Markdown
Contributor

This pull request was exported from Phabricator. Differential Revision: D62273339

@facebook-github-bot

Copy link
Copy Markdown
Contributor

This pull request was exported from Phabricator. Differential Revision: D62273339

@facebook-github-bot

Copy link
Copy Markdown
Contributor

This pull request was exported from Phabricator. Differential Revision: D62273339

Summary:
Pull Request resolved: react#46444
This diff adds:
`outline-width`: https://developer.mozilla.org/en-US/docs/Web/CSS/outline-width
`outline-color`: https://developer.mozilla.org/en-US/docs/Web/CSS/outline-color
`outline-style`: https://developer.mozilla.org/en-US/docs/Web/CSS/outline-style
`outline-offset`: https://developer.mozilla.org/en-US/docs/Web/CSS/outline-offset
Using `BackgroundStyleApplicator`
Changelog: [iOS] [Added] - Outline properties `outline-width`, `outline-color`, `outline-style` & `outline-offset`
Differential Revision: D62273339
@facebook-github-bot

Copy link
Copy Markdown
Contributor

This pull request was exported from Phabricator. Differential Revision: D62273339

@facebook-github-bot

Copy link
Copy Markdown
Contributor

This pull request has been merged in 1288e38.

@react-native-bot

Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @jorge-cab in 1288e38

When will my fix make it into a release? | How to file a pick request?

meta-codesyncBot pushed a commit that referenced this pull request Aug 21, 2026
…dii (#58028)
Summary:
Fixes#57841.
`outlineStyle: 'dotted'` and `'dashed'` render as solid on iOS. Android renders all three correctly, and the documented API lists all three values with no platform caveat.
### Root cause
`-[RCTViewComponentView invalidateLayer]` draws the outline through one of two paths:
- **Core Animation** — sets `_outlineLayer.borderWidth` / `.borderColor`. Cheap, but `CALayer` can only stroke a *solid* border.
- **Core Graphics** — `RCTAddContourEffectToLayer`, which forwards `outlineStyle` to `RCTGetBorderImage` and does honour dotted/dashed.
The branch choosing between them only looked at the border radii:
```objc
if (areBorderRadiiCircular(borderMetrics.borderRadii) && borderMetrics.borderRadii.topLeft.horizontal == 0) {
```
Every view **without a border radius** therefore took the Core Animation path, and its `outlineStyle` was silently dropped. Rounded views fell through to Core Graphics — which is why a dotted or dashed outline starts working as soon as a `borderRadius` is set.
The equivalent branch for *borders*, ~80 lines above, already gets this right: `useCoreAnimationBorderRendering` includes `borderMetrics.borderStyles.left == BorderStyle::Solid`, so a non-solid border falls through to Core Graphics. The outline branch never got the matching check when `outline` was implemented in #46444.
### Fix
Add the missing `outlineStyle == OutlineStyle::Solid` term, so non-solid outlines fall through to Core Graphics exactly as non-solid borders already do. Solid outlines keep the cheaper Core Animation path, so there is no cost for the common case.
### Why it went unnoticed
The only RNTester examples using `outlineStyle: 'dotted'` / `'dashed'` also set a `borderRadius`, so they only ever exercised the working path. This PR adds the square-cornered cases next to them, labelled, so all six combinations of `{square, rounded} × {solid, dashed, dotted}` are visible at once.
### Note on #57837#57837 (open) rewrites the two `UIColor *outlineColor = ...` lines in this same block to resolve
dynamic colors against the trait collection. This change deliberately leaves those two lines
untouched — it only adds a term to the surrounding `if` — so the two patches touch disjoint lines
and should merge without conflict in either order.
## Changelog:
[IOS] [FIXED] - Render `outlineStyle: 'dotted'` and `'dashed'` on views without border radii
Pull Request resolved: #58028
Test Plan:
### Manual verification
RNTester → Components → View → Outline, iPhone 17 Pro Simulator (iOS 26.1), New Architecture, built from source (`RCT_USE_PREBUILT_RNCORE=0`).
| Before | After |
| --- | --- |
| <img src="https://raw.githubusercontent.com/neutronm/react-native/960889bd70d6cb18839f9d3586690908b0d8207d/assets/57841/before.png" width="420"> | <img src="https://raw.githubusercontent.com/neutronm/react-native/960889bd70d6cb18839f9d3586690908b0d8207d/assets/57841/after.png" width="420"> |
| `square dashed` and `square dotted` render solid | all six render correctly |
The rounded cases and every pre-existing example in the Outline screen are pixel-identical before and after; only the two square non-solid outlines change.
### Automated
| Command | Result |
| --- | --- |
| `yarn jest` | 222/223 suites, 5713 tests pass |
| `yarn flow-check` | `Found 0 errors` |
| `yarn lint` (`eslint --max-warnings 0 .`) | clean |
| `node ./scripts/clang-format.js <changed .mm files>` | no changes |
| `yarn build-types --validate` | `PASS API snapshot is up to date.` |
| `tsc -p packages/react-native/__typetests__/tsconfig.json` | clean |
| `yarn test-ios` (`RNTesterUnitTests`) | `** TEST SUCCEEDED **` — 167 tests, 16 skipped, 0 failures |
The one Jest suite that did not pass in the full run (`GenerateComponentDescriptorH-test.js`) was a worker `SIGSEGV`, not an assertion failure; it passes 18/18 when run on its own.
### Unit tests
`React/Tests/Mounting/RCTViewComponentViewTests.mm` gains two cases next to the existing ones:
- `testSquareSolidOutlineUsesCoreAnimationBorder` — a square solid outline still uses `CALayer.borderWidth` (the fast path is not regressed).
- `testSquareDottedAndDashedOutlinesAreDrawnWithCoreGraphics` — square dotted and dashed outlines are drawn into `layer.contents` with `borderWidth == 0`.
`React/Tests/**` is excluded from the `React-Core` podspec, so these are not built by the OSS `RNTesterUnitTests` target. They were verified to compile against the installed pod headers with `clang -fsyntax-only -x objective-c++ -std=c++20`.
Reviewed By: cipolleschi
Differential Revision: D116779403
Pulled By: javache
fbshipit-source-id: b8d1f3508418016252ec9b1f9aaab7107c8f3b9f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.fb-exportedMergedThis PR has been merged.p: FacebookPartner: FacebookPartner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jorge-cab@facebook-github-bot@react-native-bot