Skip to content

Commit 0438580

Browse files
authored
chore(fabric): implement focus view props (#2692)
Needs #2690 to land first. ## Summary: Implement focus on RCTViewComponentView. Much of the implementation is taken from #1437, #2117 and comparing against `RCTView`. The border path used for `drawFocusRingMask` is the same as what is used for box shadows and cursors. ## Test Plan: The focus loop seems nonexistent on both paper and Fabric in RNTester... but I can verify that calling `ref.current?/.focus()` on a Pressable displays the focus ring
1 parent 9842cc8 commit 0438580

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,73 @@ - (BOOL)didActivateAccessibilityCustomAction:(UIAccessibilityCustomAction *)acti
15101510
}
15111511
}
15121512

1513+
#if TARGET_OS_OSX // [macOS
1514+
1515+
# pragma mark - Focus Ring
1516+
1517+
- (CGRect)focusRingMaskBounds
1518+
{
1519+
return [self bounds];
1520+
}
1521+
1522+
- (void)drawFocusRingMask
1523+
{
1524+
if (_props->enableFocusRing) {
1525+
CGContextRef context = NSGraphicsContext.currentContext.CGContext;
1526+
1527+
const auto borderMetrics = _props->resolveBorderMetrics(_layoutMetrics);
1528+
const RCTCornerInsets cornerInsets =
1529+
RCTGetCornerInsets(RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero);
1530+
CGPathRef path = RCTPathCreateWithRoundedRect(self.bounds, cornerInsets, NULL);
1531+
1532+
CGContextAddPath(context, path);
1533+
CGContextFillPath(context);
1534+
CGPathRelease(path);
1535+
}
1536+
}
1537+
1538+
1539+
#pragma mark - Focus Events
1540+
1541+
- (BOOL)needsPanelToBecomeKey
1542+
{
1543+
// We need to override this so that mouse clicks don't move keyboard focus on focusable views by default.
1544+
return false;
1545+
}
1546+
1547+
- (BOOL)acceptsFirstResponder
1548+
{
1549+
return _props->focusable || [super acceptsFirstResponder];
1550+
}
1551+
1552+
- (BOOL)becomeFirstResponder
1553+
{
1554+
if (![super becomeFirstResponder]) {
1555+
return NO;
1556+
}
1557+
1558+
if (_eventEmitter) {
1559+
_eventEmitter->onFocus();
1560+
}
1561+
1562+
return YES;
1563+
}
1564+
1565+
- (BOOL)resignFirstResponder
1566+
{
1567+
if (![super resignFirstResponder]) {
1568+
return NO;
1569+
}
1570+
1571+
if (_eventEmitter) {
1572+
_eventEmitter->onBlur();
1573+
}
1574+
1575+
return YES;
1576+
}
1577+
1578+
#endif // macOS]
1579+
15131580
- (SharedTouchEventEmitter)touchEventEmitterAtPoint:(CGPoint)point
15141581
{
15151582
return _eventEmitter;

0 commit comments

Comments
 (0)