Skip to content

feat: support data attributes#339

Merged
Brentlok merged 6 commits intomainfrom
feat/data-attributes
Jan 28, 2026
Merged

feat: support data attributes#339
Brentlok merged 6 commits intomainfrom
feat/data-attributes

Conversation

@Brentlok
Copy link
Copy Markdown
Contributor

@Brentlok Brentlok commented Jan 28, 2026

Summary by CodeRabbit

  • New Features

    • Support for data-attribute selectors in styles, enabling conditional styling based on component prop values.
  • Refactor

    • Consolidated style and color resolution across native components for more consistent, prop-aware styling; public APIs remain unchanged.
  • Tests

    • Added tests validating data-attribute selector behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

Walkthrough

Centralizes color and style derivation into an enhanced useStyle hook (now receiving component props), removes useUniwindAccent, and adds data-attribute selector support across style resolution and build-time metadata.

Changes

Cohort / File(s) Summary
Native components – useStyle integration
packages/uniwind/src/components/native/ActivityIndicator.tsx, packages/uniwind/src/components/native/Button.tsx, packages/uniwind/src/components/native/FlatList.tsx, packages/uniwind/src/components/native/Image.tsx, packages/uniwind/src/components/native/ImageBackground.tsx, packages/uniwind/src/components/native/InputAccessoryView.tsx, packages/uniwind/src/components/native/KeyboardAvoidingView.tsx, packages/uniwind/src/components/native/Modal.tsx, packages/uniwind/src/components/native/RefreshControl.tsx, packages/uniwind/src/components/native/SafeAreaView.tsx, packages/uniwind/src/components/native/ScrollView.tsx, packages/uniwind/src/components/native/SectionList.tsx, packages/uniwind/src/components/native/Text.tsx, packages/uniwind/src/components/native/TextInput.tsx, packages/uniwind/src/components/native/TouchableHighlight.tsx, packages/uniwind/src/components/native/TouchableNativeFeedback.tsx, packages/uniwind/src/components/native/TouchableOpacity.tsx, packages/uniwind/src/components/native/TouchableWithoutFeedback.tsx, packages/uniwind/src/components/native/View.tsx, packages/uniwind/src/components/native/VirtualizedList.tsx
All components now pass component props into useStyle (e.g., useStyle(className, props[, state])). Removed useUniwindAccent usages; accent colors read from useStyle(...).accentColor.
Complex native components
packages/uniwind/src/components/native/Pressable.tsx, packages/uniwind/src/components/native/Switch.tsx
Propagated props through multi-call style resolution; updated call sites to match new UniwindStore.getStyles(className, props, options) and useStyle(className, props, state[, options]) signatures.
useStyle hook
packages/uniwind/src/components/native/useStyle.ts
Signature changed to `(className: string
Style store & resolver
packages/uniwind/src/core/native/store.ts
getStyles/resolveStyles now accept componentProps; StylesResult includes dependencySum and hasDataAttributes. Added validateDataAttributes and logic to skip styles when data-attribute selectors do not match componentProps; caching adjusted when data attributes present.
Type additions
packages/uniwind/src/core/types.ts, packages/uniwind/src/metro/types.ts
Added optional `dataAttributes: Record<string,string>
Hook signature changes / removals
packages/uniwind/src/hooks/useResolveClassNames.native.ts, packages/uniwind/src/hooks/useUniwindAccent.native.ts
useResolveClassNames signature simplified (removed state param). useUniwindAccent.native.ts deleted; accent resolution consolidated into useStyle.
Metro build-time processing
packages/uniwind/src/metro/addMetaToStylesTemplate.ts, packages/uniwind/src/metro/processor/mq.ts, packages/uniwind/src/metro/processor/processor.ts
Propagate dataAttributes into generated style metadata and media-query resolver; parser extracts data-attribute selectors and persists them into declaration config and style outputs.
Tests
packages/uniwind/tests/styles-parsing/data-attributes.test.tsx
New test exercising data-attribute selectors (renders Views with data-* props and asserts computed styles).
Lint / Misc / Dev deps
packages/uniwind/eslint.config.ts, package.json
ESLint: added @typescript-eslint/no-unused-vars rule and disabled no-bitwise. Bumped dev dependency turbo 2.6.3 → 2.7.6.

Sequence Diagram(s)

sequenceDiagram
    participant Component
    participant useStyle
    participant UniwindStore
    participant Resolver

    Component->>useStyle: call useStyle(className, props, state)
    useStyle->>UniwindStore: getStyles(className, props, state)
    UniwindStore->>Resolver: resolveStyles(classNames, componentProps, state)
    Resolver->>Resolver: parse rules, evaluate selectors (including dataAttributes)
    alt dataAttributes mismatch
        Resolver-->>UniwindStore: skip style
    else match or no dataAttributes
        Resolver-->>UniwindStore: include style, accumulate dependencySum & hasDataAttributes
    end
    UniwindStore-->>useStyle: StylesResult (styles, dependencies, dependencySum, hasDataAttributes)
    useStyle-->>Component: computed style (includes accentColor)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇
I nibble classNames, props in tow,
One hook now paints the color-glow,
Data-tags whisper which rules apply,
I hop, I patch, the styles comply,
Happy hops — watch Uniwind grow!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: support data attributes' directly and clearly summarizes the main feature addition. It accurately reflects the core changes throughout the PR which introduce data attributes support across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@packages/uniwind/src/core/native/store.ts`:
- Around line 10-16: The StylesResult type is missing the hasDataAttributes
field which resolveStyles returns and callers (e.g., code reading emptyState)
expect; update the StylesResult type to include hasDataAttributes: boolean and
then add hasDataAttributes: false to the emptyState constant so the shape
matches resolveStyles and consumers can safely access that property. Ensure you
update the type declaration named StylesResult and the constant emptyState
accordingly.
- Around line 238-256: The validateDataAttributes function returns early when a
boolean attribute matches, skipping remaining checks; change the logic in
validateDataAttributes to avoid returning true inside the loop: for each
attribute (in function validateDataAttributes) evaluate boolean cases and only
return false when a mismatch is detected, otherwise continue to the next
attribute, and after the loop return true; ensure the checks for
expectedAttributeValue === 'true' and 'false' return false on mismatch (not true
on match) and do not prematurely exit the loop when matched.

In `@packages/uniwind/src/core/types.ts`:
- Line 20: The TypeScript type for Style currently forces the dataAttributes
property (even if nullable) which can break downstream consumers; update the
Style definition to make dataAttributes optional (change the declaration for
dataAttributes on the Style type to be optional, e.g. dataAttributes?:
Record<string,string> | null) so callers that omit it won’t error, and if this
is a public API change ensure you document or version-bump accordingly; locate
the Style type in the file where dataAttributes is declared in
packages/uniwind/src/core/types.ts and adjust that property.

In `@packages/uniwind/src/metro/processor/processor.ts`:
- Around line 181-185: The code stores attribute values with surrounding quotes
causing mismatches in validation; in the block handling selector.type ===
'attribute' and selector.operation?.operator === 'equal' (inside the processor
function where dataAttributes is set), stop wrapping selector.operation.value in
quotes and assign the raw value instead (e.g., dataAttributes[selector.name] =
selector.operation.value) so it matches what validateDataAttributes() in
store.ts expects when comparing boolean/string props.
🧹 Nitpick comments (2)
packages/uniwind/src/components/native/Pressable.tsx (1)

18-31: Consider extracting the state object to reduce duplication.

The state object { isDisabled: Boolean(props.disabled), isPressed: true } partially duplicates the one created at lines 10-12. Minor improvement would be to extract the base state.

♻️ Optional refactor
 export const Pressable = copyComponentProperties(RNPressable, (props: PressableProps) => {
+    const baseState = { isDisabled: Boolean(props.disabled) }
     const style = useStyle(
         props.className,
         props,
-        {
-            isDisabled: Boolean(props.disabled),
-        },
+        baseState,
     )
 
     return (
         <RNPressable
             {...props}
             style={state => {
                 if (state.pressed) {
                     return [
                         UniwindStore.getStyles(
                             props.className,
                             props,
-                            { isDisabled: Boolean(props.disabled), isPressed: true },
+                            { ...baseState, isPressed: true },
                         ).styles,
                         typeof props.style === 'function' ? props.style(state) : props.style,
                     ]
                 }
 
                 return [style, typeof props.style === 'function' ? props.style(state) : props.style]
             }}
         />
     )
 })
packages/uniwind/src/metro/processor/processor.ts (1)

182-185: Only the equal operator is supported for attribute selectors.

Other CSS attribute selector operators (~=, |=, ^=, $=, *=) are not handled. If this is intentional (data attributes typically use exact matching), consider adding a brief comment for clarity.

📝 Optional: Add clarifying comment
-                    if (selector.type === 'attribute' && selector.operation?.operator === 'equal') {
+                    // Only exact-match attribute selectors are supported (e.g., [data-active="true"])
+                    if (selector.type === 'attribute' && selector.operation?.operator === 'equal') {
                         dataAttributes ??= {}
                         dataAttributes[selector.name] = `"${selector.operation.value}"`
                     }

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/uniwind/src/core/native/store.ts (1)

86-124: Add a guard to prevent dependencySum bit-shift overflow if StyleDependency enum grows.

Currently safe with enum values 1–9, but dependencySum |= 1 << dep will silently collide if any enum value reaches 31+ (causing shifts beyond the 32-bit boundary). Since different dependency sets would then map to the same sum, the React dependency array wouldn't detect changes, breaking re-subscriptions.

Consider either:

  • Asserting that StyleDependency values stay ≤ 30
  • Switching to a stable string key (e.g., bitmask-based hash or Set serialization) if further growth is planned

Also applies to: 229–234

@Brentlok Brentlok merged commit 608f5a1 into main Jan 28, 2026
2 checks passed
@Brentlok Brentlok deleted the feat/data-attributes branch January 28, 2026 11:09
@coderabbitai coderabbitai bot mentioned this pull request Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant