Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions combobox-input/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# ComboboxInput
A combobox/autocomplete input component that combines a text input field with a filterable dropdown list.

## Getting Started

Install dependencies:
```bash
npm install
```

Share the component to your Webflow workspace:
```bash
npx webflow library share
```

For local development:
```bash
npm run dev
```

## Designer Properties

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| ID | Id | — | HTML ID attribute for the combobox input |
| Size | Variant | md | Visual size of the input field (sm, md, lg) |
| Label | Text | Select an option | Label text displayed above the input |
| Placeholder | Text | Type to search... | Placeholder text shown in the input when empty |
| No Results Message | Text | No results found | Message displayed when no options match the filter |
| Loading Message | Text | Loading options... | Message displayed during loading state |
| Show Label | Visibility | — | Show or hide the label above the input |
| Show Clear Button | Boolean | true | Show clear button when a value is selected |
| Is Loading | Boolean | false | Display loading state in the dropdown |
| Is Disabled | Boolean | false | Disable the entire combobox input |
| Option 1 Label | Text | Option One | Label text for the first option |
| Option 1 Description | Text | Description for option one | Optional description text for the first option |
| Option 1 Value | Text | option-1 | Value returned when first option is selected |
| Option 1 Visible | Visibility | — | Show or hide the first option |
| Option 2 Label | Text | Option Two | Label text for the second option |
| Option 2 Description | Text | Description for option two | Optional description text for the second option |
| Option 2 Value | Text | option-2 | Value returned when second option is selected |
| Option 2 Visible | Visibility | — | Show or hide the second option |
| Option 3 Label | Text | Option Three | Label text for the third option |
| Option 3 Description | Text | Description for option three | Optional description text for the third option |
| Option 3 Value | Text | option-3 | Value returned when third option is selected |
| Option 3 Visible | Visibility | — | Show or hide the third option |
| Option 4 Label | Text | Option Four | Label text for the fourth option |
| Option 4 Description | Text | Description for option four | Optional description text for the fourth option |
| Option 4 Value | Text | option-4 | Value returned when fourth option is selected |
| Option 4 Visible | Visibility | — | Show or hide the fourth option |
| Option 5 Label | Text | Option Five | Label text for the fifth option |
| Option 5 Description | Text | Description for option five | Optional description text for the fifth option |
| Option 5 Value | Text | option-5 | Value returned when fifth option is selected |
| Option 5 Visible | Visibility | — | Show or hide the fifth option |

## Styling

This component automatically adapts to your Webflow site's design system through site variables and inherited properties.

### Site Variables

To match your site's design system, define these CSS variables in your Webflow project settings. The component will use the fallback values shown below until you configure them.

| Site Variable | What It Controls | Fallback |
|---------------|------------------|----------|
| --background-primary | Input field and dropdown background color | #ffffff |
| --background-secondary | Hover and highlighted option states | #f5f5f5 |
| --text-primary | Main text color for input and option labels | #1a1a1a |
| --text-secondary | Description text, placeholder, and icons | #737373 |
| --border-color | Input border, dropdown border, and dividers | #e5e5e5 |
| --accent-color | Selected option background and focus ring | #1a1a1a |
| --accent-text-color | Text color on selected options | #ffffff |
| --border-radius | Rounding for input, dropdown, and buttons | 8px |

### Inherited Properties

The component inherits these CSS properties from its parent element:
- `font-family` — Typography style
- `color` — Text color
- `line-height` — Text spacing

## Extending in Code

### Loading Options from an API

Set the `isLoading` property to `true` while fetching data, then populate options dynamically:

```javascript
// Show loading state
combobox.isLoading = true;

// Fetch options from API
const response = await fetch('/api/options');
const data = await response.json();

// Update options
data.forEach((item, index) => {
if (index < 5) {
combobox[`option${index + 1}Label`] = item.name;
combobox[`option${index + 1}Description`] = item.description;
combobox[`option${index + 1}Value`] = item.id;
combobox[`option${index + 1}Visible`] = true;
}
});

combobox.isLoading = false;
```

### Handling Selection Events

Listen for selection changes to trigger custom actions:

```javascript
const input = document.querySelector('#my-combobox input');
input.addEventListener('change', (e) => {
const selectedValue = e.target.value;
console.log('Selected:', selectedValue);
// Trigger form validation, update other fields, etc.
});
```

## Dependencies

No external dependencies.
17 changes: 17 additions & 0 deletions combobox-input/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ComboboxInput</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; }
body { color: inherit; }
h1, h2, h3, h4, h5, h6 { color: inherit; }
</style>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions combobox-input/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Combobox Input",
"description": "Searchable dropdown with autocomplete suggestions",
"category": "Forms & Input"
}
25 changes: 25 additions & 0 deletions combobox-input/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "combobox-input",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^19.1.1",
"react-dom": "^19.1.1"
},
"devDependencies": {
"@types/react": "^19.1.13",
"@types/react-dom": "^19.1.9",
"@vitejs/plugin-react": "^5.0.3",
"@webflow/data-types": "^1.0.1",
"@webflow/react": "^1.0.1",
"@webflow/webflow-cli": "^1.8.44",
"typescript": "~5.8.3",
"vite": "^7.1.7"
}
}
1 change: 1 addition & 0 deletions combobox-input/screenshot-brand.b64

Large diffs are not rendered by default.

Binary file added combobox-input/screenshot-brand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions combobox-input/screenshot-dark.b64

Large diffs are not rendered by default.

Binary file added combobox-input/screenshot-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions combobox-input/screenshot-light.b64

Large diffs are not rendered by default.

Binary file added combobox-input/screenshot-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
198 changes: 198 additions & 0 deletions combobox-input/src/components/ComboboxInput/ComboboxInput.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* Webflow Site Variables Used:
* - --background-primary: Input and dropdown background
* - --background-secondary: Hover and highlighted states
* - --text-primary: Main text color for input and options
* - --text-secondary: Description text and placeholder
* - --border-color: Input border and dropdown dividers
* - --accent-color: Selected option background
* - --accent-text-color: Selected option text
* - --border-radius: Input and dropdown rounding
*/

.wf-comboboxinput *,
.wf-comboboxinput *::before,
.wf-comboboxinput *::after {
box-sizing: border-box;
}

.wf-comboboxinput {
font-family: inherit;
color: inherit;
line-height: inherit;
padding: 24px;
--wf-comboboxinput-height: 40px;
position: relative;
display: flex;
flex-direction: column;
gap: 8px;
}

.wf-comboboxinput-label {
display: block;
font-size: 14px;
font-weight: 500;
color: var(--text-primary, #1a1a1a);
margin-bottom: 4px;
}

.wf-comboboxinput-wrapper {
position: relative;
display: flex;
align-items: center;
}

.wf-comboboxinput-input {
width: 100%;
height: var(--wf-comboboxinput-height);
padding: 0 40px 0 12px;
background: var(--background-primary, #ffffff);
border: 1px solid var(--border-color, #e5e5e5);
border-radius: var(--border-radius, 8px);
color: var(--text-primary, #1a1a1a);
font-size: 14px;
font-family: inherit;
line-height: inherit;
transition: border-color 0.2s, box-shadow 0.2s;
outline: none;
}

.wf-comboboxinput-input::placeholder {
color: var(--text-secondary, #737373);
opacity: 1;
}

.wf-comboboxinput-input:hover:not(:disabled) {
border-color: var(--text-secondary, #737373);
}

.wf-comboboxinput-input:focus {
border-color: var(--accent-color, #1a1a1a);
box-shadow: 0 0 0 3px rgba(26, 26, 26, 0.1);
}

.wf-comboboxinput-input:disabled {
opacity: 0.5;
cursor: not-allowed;
background: var(--background-secondary, #f5f5f5);
}

.wf-comboboxinput-clear {
position: absolute;
right: 36px;
top: 50%;
transform: translateY(-50%);
background: transparent;
border: none;
padding: 4px;
cursor: pointer;
color: var(--text-secondary, #737373);
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--border-radius, 8px);
transition: background-color 0.2s, color 0.2s;
}

.wf-comboboxinput-clear:hover {
background: var(--background-secondary, #f5f5f5);
color: var(--text-primary, #1a1a1a);
}

.wf-comboboxinput-clear:focus-visible {
outline: 2px solid var(--accent-color, #1a1a1a);
outline-offset: 2px;
}

.wf-comboboxinput-icon {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary, #737373);
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}

.wf-comboboxinput-dropdown {
position: absolute;
top: calc(100% + 4px);
left: 0;
right: 0;
background: var(--background-primary, #ffffff);
border: 1px solid var(--border-color, #e5e5e5);
border-radius: var(--border-radius, 8px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
max-height: 240px;
overflow-y: auto;
z-index: 1000;
padding: 4px;
}

.wf-comboboxinput-dropdown::-webkit-scrollbar {
width: 8px;
}

.wf-comboboxinput-dropdown::-webkit-scrollbar-track {
background: transparent;
}

.wf-comboboxinput-dropdown::-webkit-scrollbar-thumb {
background: var(--border-color, #e5e5e5);
border-radius: 4px;
}

.wf-comboboxinput-dropdown::-webkit-scrollbar-thumb:hover {
background: var(--text-secondary, #737373);
}

.wf-comboboxinput-message {
padding: 12px;
color: var(--text-secondary, #737373);
font-size: 14px;
text-align: center;
}

.wf-comboboxinput-option {
padding: 10px 12px;
cursor: pointer;
border-radius: var(--border-radius, 8px);
transition: background-color 0.2s;
}

.wf-comboboxinput-option:hover {
background: var(--background-secondary, #f5f5f5);
}

.wf-comboboxinput-option-highlighted {
background: var(--background-secondary, #f5f5f5);
}

.wf-comboboxinput-option-selected {
background: var(--accent-color, #1a1a1a);
}

.wf-comboboxinput-option-selected .wf-comboboxinput-option-label {
color: var(--accent-text-color, #ffffff);
font-weight: 500;
}

.wf-comboboxinput-option-selected .wf-comboboxinput-option-description {
color: var(--accent-text-color, #ffffff);
opacity: 0.8;
}

.wf-comboboxinput-option-label {
font-size: 14px;
color: var(--text-primary, #1a1a1a);
font-weight: 400;
margin-bottom: 2px;
}

.wf-comboboxinput-option-description {
font-size: 12px;
color: var(--text-secondary, #737373);
line-height: 1.4;
}
Loading