Skip to content

feat(FoInputFile): First implementation#137

Merged
michaelcozzolino merged 5 commits into2.xfrom
feat/input-file
Mar 8, 2026
Merged

feat(FoInputFile): First implementation#137
michaelcozzolino merged 5 commits into2.xfrom
feat/input-file

Conversation

@michaelcozzolino
Copy link
Owner

@michaelcozzolino michaelcozzolino commented Mar 8, 2026

Summary by CodeRabbit

  • New Features

    • Introduced Input File component supporting single and multiple file uploads with configurable labels, helper text, sizes (extraSmall to extraLarge), and validation states.
  • Bug Fixes

    • Fixed floating label styling logic in Select component.
  • Documentation

    • Added comprehensive Input File component documentation with examples and API reference.

@michaelcozzolino michaelcozzolino marked this pull request as ready for review March 8, 2026 19:10
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 8, 2026

Walkthrough

This pull request introduces a new FoInputFile component for file uploads. The change updates type definitions across multiple modules to include FoInputFile in relevant unions for floating labels, sizing, helper text positioning, and label configuration. The PR adds two Vue components: FoInputFile for single-file uploads and FoInputFiles for multiple-file uploads. Supporting type definitions, hook configurations, and app config mappings are updated to handle the new component. Additionally, comprehensive documentation files and example components are added, and the sidebar navigation is updated to include an InputFile section. A minor change removes floating label type checks from the Select component. The FoImageRadio component is marked as non-configurable.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: the first implementation of the FoInputFile component, which is the primary focus of all changes across the codebase.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/input-file

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.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 8, 2026

Deploying flyonui-vue with  Cloudflare Pages  Cloudflare Pages

Latest commit: f25ad0c
Status: ✅  Deploy successful!
Preview URL: https://c852d21a.flyonui-vue.pages.dev
Branch Preview URL: https://feat-input-file.flyonui-vue.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 8, 2026

Deploying flyonui-vue-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: f25ad0c
Status: ✅  Deploy successful!
Preview URL: https://82e3ee67.flyonui-vue-v3.pages.dev
Branch Preview URL: https://feat-input-file.flyonui-vue-v3.pages.dev

View logs

Copy link
Contributor

@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

🧹 Nitpick comments (3)
packages/core/src/Lib/UseFlyonUIVueAppConfig/Types/ComponentName.ts (1)

10-12: Consider alphabetical ordering for consistency.

FoImageRadio should be placed before FoJoin to maintain alphabetical ordering in the union type.

♻️ Suggested fix
     | 'FoDotStyleBadge'
+    | 'FoImageRadio'
     | 'FoJoin'
-    | 'FoImageRadio'
     | 'FoLabel'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/Lib/UseFlyonUIVueAppConfig/Types/ComponentName.ts` around
lines 10 - 12, The union type ComponentName has its members out of alphabetical
order: move the 'FoImageRadio' entry so it appears before 'FoJoin' (resulting
order: 'FoImageRadio', 'FoJoin', 'FoLabel') to keep the union list sorted;
locate the union in ComponentName and reorder those string literals accordingly.
packages/core/src/Lib/UseFloatingLabel/Types/FloatingLabel.ts (1)

3-4: Address the TODO comment.

The TODO indicates a potential mismatch between configurable and floating label types that should be investigated. Consider creating an issue to track this technical debt.

Would you like me to help clarify what the mismatch is, or open a new issue to track this TODO?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/Lib/UseFloatingLabel/Types/FloatingLabel.ts` around lines 3
- 4, The TODO warns that FloatingLabelComponentName may not match the set of
components that actually support configurable floating labels; inspect the
source of ComponentName and the configuration map/type that lists components
with configurable floating labels (e.g., any Configurable* type or a component
config object) and make FloatingLabelComponentName derived from that
authoritative source instead of a hardcoded union—either by using
Extract<ComponentName, keyof typeof ConfigurableComponentMap> or by creating a
dedicated ConfigurableFloatingLabelComponents union and using that in place of
the current type; if you cannot resolve it now, create a tracked issue
describing the mismatch and link this TODO, then replace the TODO with a brief
comment pointing to the issue and keep the current type until the follow-up is
done.
packages/core/src/Lib/UseFloatingLabel/Internal/Lib/UseFloatingLabel.ts (1)

14-21: Avoid allocating ComputedRefs inside the computed getter.

The classes map creates four fresh ComputedRef objects on every evaluation (via useClass() calls), even though their values are immediately extracted with .value. Since isFloating depends on labelType, you cannot hoist the map as-is, but you can restructure to compute the class string directly without intermediate computed refs:

return computed(() => {
    const isFloating = toValue(labelType) === 'floating';
    const component = toValue(componentName);
    
    const classMap = {
        FoInputFile: isFloating ? 'input-floating' : '',
        FoInputText: isFloating ? 'input-floating' : '',
        FoSelect: isFloating ? 'select-floating' : '',
        FoTextarea: isFloating ? 'textarea-floating' : '',
    };
    
    return classMap[component];
});

This eliminates unnecessary reactive object allocations while preserving reactivity to both labelType and componentName.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/Lib/UseFloatingLabel/Internal/Lib/UseFloatingLabel.ts`
around lines 14 - 21, The computed currently allocates four ComputedRef objects
by calling useClass(...) for each key (FoInputFile, FoInputText, FoSelect,
FoTextarea) and then returning classes[toValue(componentName)].value; instead,
compute the class string directly inside the computed: derive isFloating from
toValue(labelType), derive component from toValue(componentName), and return the
appropriate string from a simple object/map (e.g. map component keys to
'input-floating'/'select-floating'/'textarea-floating' or '' when not floating).
Remove the useClass(...) calls and the intermediate classes map so the computed
only returns the class string based on labelType and componentName.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/UI/Forms/InputFile/Types/InputFile.ts`:
- Around line 6-11: InputFileProps is missing a `multiple` prop so
FoInputFile.vue's :multiple binding is dropped (and FoInputFiles currently
hardcodes multiple on the <input>); add an optional `multiple?: boolean` to the
exported InputFileProps type (or create two types InputFileProps and
InputFilesProps and export/use the multi-file variant) and update FoInputFiles
to accept that prop and bind it to the native <input> instead of hardcoding it
(ensure the component uses the new prop name in its props definition and
template).

In `@packages/core/src/UI/Forms/InputFile/UI/FoInputFiles.vue`:
- Around line 93-100: The change handler in FoInputFiles.vue emits files but
doesn't clear the native input, so selecting the same file won't retrigger
change; update the change(event: Event) function to, after verifying target is
an HTMLInputElement and emitting via emit('upload:files', target.files), reset
the input's value (e.g., set target.value = '' or use target.form?.reset() as
appropriate) to ensure subsequent identical selections fire change again while
preserving the existing type checks and emit call.

In `@packages/docs/Next/Forms/InputFile.md`:
- Around line 3-17: The document uses h3 headings ("### Default", "### Labels",
"### Sizes", "### Validation states") directly under the page h1, breaking
heading hierarchy; update these headings to h2 (change "###" to "##") so each
<InputFileDocs section="default|label|size|validation-state"> block sits under a
proper h2, preserving accessible document outline and consistent navigation.

In `@packages/docs/Next/Forms/InputFile/InputFileDocs.vue`:
- Around line 2-5: The API docs only register FoInputFile but the module also
re-exports FoInputFiles, so either document FoInputFiles or keep it internal; to
fix, update the ComponentDocs invocation (the ComponentDocs usage that currently
passes api-docs-component-names="FoInputFile") to include "FoInputFiles" as well
when the component is public, or remove/stop exporting FoInputFiles from the
InputFile barrel so it is not included in the public API; identify the symbols
FoInputFile and FoInputFiles and adjust the api-docs-component-names list or the
module export accordingly to ensure the public component has props/events
documented.

---

Nitpick comments:
In `@packages/core/src/Lib/UseFloatingLabel/Internal/Lib/UseFloatingLabel.ts`:
- Around line 14-21: The computed currently allocates four ComputedRef objects
by calling useClass(...) for each key (FoInputFile, FoInputText, FoSelect,
FoTextarea) and then returning classes[toValue(componentName)].value; instead,
compute the class string directly inside the computed: derive isFloating from
toValue(labelType), derive component from toValue(componentName), and return the
appropriate string from a simple object/map (e.g. map component keys to
'input-floating'/'select-floating'/'textarea-floating' or '' when not floating).
Remove the useClass(...) calls and the intermediate classes map so the computed
only returns the class string based on labelType and componentName.

In `@packages/core/src/Lib/UseFloatingLabel/Types/FloatingLabel.ts`:
- Around line 3-4: The TODO warns that FloatingLabelComponentName may not match
the set of components that actually support configurable floating labels;
inspect the source of ComponentName and the configuration map/type that lists
components with configurable floating labels (e.g., any Configurable* type or a
component config object) and make FloatingLabelComponentName derived from that
authoritative source instead of a hardcoded union—either by using
Extract<ComponentName, keyof typeof ConfigurableComponentMap> or by creating a
dedicated ConfigurableFloatingLabelComponents union and using that in place of
the current type; if you cannot resolve it now, create a tracked issue
describing the mismatch and link this TODO, then replace the TODO with a brief
comment pointing to the issue and keep the current type until the follow-up is
done.

In `@packages/core/src/Lib/UseFlyonUIVueAppConfig/Types/ComponentName.ts`:
- Around line 10-12: The union type ComponentName has its members out of
alphabetical order: move the 'FoImageRadio' entry so it appears before 'FoJoin'
(resulting order: 'FoImageRadio', 'FoJoin', 'FoLabel') to keep the union list
sorted; locate the union in ComponentName and reorder those string literals
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6d8e7268-d565-421e-8aaf-db7837023eb6

📥 Commits

Reviewing files that changed from the base of the PR and between e15d21e and f25ad0c.

⛔ Files ignored due to path filters (7)
  • packages/docs/tests/EndToEnd/Docs.browser.spec.ts-snapshots/forms-input-file-default-chromium-linux.png is excluded by !**/*.png
  • packages/docs/tests/EndToEnd/Docs.browser.spec.ts-snapshots/forms-input-file-disabled-chromium-linux.png is excluded by !**/*.png
  • packages/docs/tests/EndToEnd/Docs.browser.spec.ts-snapshots/forms-input-file-helper-text-chromium-linux.png is excluded by !**/*.png
  • packages/docs/tests/EndToEnd/Docs.browser.spec.ts-snapshots/forms-input-file-label-chromium-linux.png is excluded by !**/*.png
  • packages/docs/tests/EndToEnd/Docs.browser.spec.ts-snapshots/forms-input-file-multiple-files-chromium-linux.png is excluded by !**/*.png
  • packages/docs/tests/EndToEnd/Docs.browser.spec.ts-snapshots/forms-input-file-size-chromium-linux.png is excluded by !**/*.png
  • packages/docs/tests/EndToEnd/Docs.browser.spec.ts-snapshots/forms-input-file-validation-state-chromium-linux.png is excluded by !**/*.png
📒 Files selected for processing (29)
  • packages/core/src/Lib/UseFloatingLabel/Internal/Lib/UseFloatingLabel.ts
  • packages/core/src/Lib/UseFloatingLabel/Types/FloatingLabel.ts
  • packages/core/src/Lib/UseFlyonUIVueAppConfig/Types/ComponentName.ts
  • packages/core/src/Lib/UseFlyonUIVueAppConfig/Types/FlyonUIVueAppConfig.ts
  • packages/core/src/Lib/UseSize/Internal/Lib/UseSize.ts
  • packages/core/src/Lib/UseSize/Types/Size.ts
  • packages/core/src/UI/Components/HelperText/Types/HelperText.ts
  • packages/core/src/UI/Components/Label/Internal/Types/Label.ts
  • packages/core/src/UI/Components/Label/Internal/UI/FoLabel.vue
  • packages/core/src/UI/Forms/InputFile/Types/InputFile.ts
  • packages/core/src/UI/Forms/InputFile/Types/index.ts
  • packages/core/src/UI/Forms/InputFile/UI/FoInputFile.vue
  • packages/core/src/UI/Forms/InputFile/UI/FoInputFiles.vue
  • packages/core/src/UI/Forms/InputFile/UI/index.ts
  • packages/core/src/UI/Forms/InputFile/index.ts
  • packages/core/src/UI/Forms/Select/UI/FoSelect.vue
  • packages/core/src/UI/Forms/index.ts
  • packages/docs/.vitepress/theme/Components/Layout/Features/Sidebar/Lib/UseSidebarItems.ts
  • packages/docs/.vitepress/theme/index.ts
  • packages/docs/Next/Forms/InputFile.md
  • packages/docs/Next/Forms/InputFile/DefaultInputFile.vue
  • packages/docs/Next/Forms/InputFile/DisabledInputFile.vue
  • packages/docs/Next/Forms/InputFile/InputFileDocs.vue
  • packages/docs/Next/Forms/InputFile/InputFileHelperText.vue
  • packages/docs/Next/Forms/InputFile/InputFileLabel.vue
  • packages/docs/Next/Forms/InputFile/InputFileSize.vue
  • packages/docs/Next/Forms/InputFile/InputFileValidationState.vue
  • packages/docs/Next/Forms/InputFile/MultipleFilesInputFile.vue
  • packages/docs/Next/Forms/Radio/RadioDocs.vue

@michaelcozzolino michaelcozzolino merged commit 2c02af3 into 2.x Mar 8, 2026
7 checks passed
@michaelcozzolino michaelcozzolino deleted the feat/input-file branch March 8, 2026 19:22
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