-
-
Notifications
You must be signed in to change notification settings - Fork 228
feat(Templates): add search functionality for user templates #901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✅ Deploy Preview for livecodes ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
WalkthroughAdds a client-side templates search input and FlexSearch-based indexing/filtering, wires index population into starter and user template loading, exposes search-related UI helpers, adds many template aliases and i18n keys, and introduces a modal size variant and related style/layout changes. Changes
Sequence Diagram(s)sequenceDiagram
rect rgba(220,240,255,0.5)
participant User
end
rect rgba(255,240,220,0.5)
participant SearchInput as "templates-search-input (DOM)"
end
rect rgba(220,255,230,0.5)
participant TemplatesModule as "templates.ts"
end
rect rgba(240,230,255,0.5)
participant FlexSearch as "FlexSearch Index"
end
rect rgba(255,230,230,0.5)
participant DOMLists as "starter/user <li> lists"
end
User->>SearchInput: type query
SearchInput->>TemplatesModule: input event
TemplatesModule->>TemplatesModule: debounce(150ms)
TemplatesModule->>FlexSearch: query index
FlexSearch-->>TemplatesModule: return matched ids
TemplatesModule->>DOMLists: show/hide items based on ids
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/livecodes/html/templates.html(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: Redirect rules - livecodes
- GitHub Check: Header rules - livecodes
- GitHub Check: Pages changed - livecodes
🔇 Additional comments (1)
src/livecodes/html/templates.html (1)
36-55: Script logic is sound; confirm filtering implementation is planned.The inline script correctly debounces input (150ms), emits a
templates:filtercustom event with the query value, and uses defensive null checks. The implementation is event-driven as intended, allowing other scripts to listen and filter templates accordingly.Since this is described as a demo PR pending actual filtering logic, verify that:
- Event listeners consuming the
templates:filterevent will be implemented separately.- The event dispatch to
#templates-containeraligns with where filter listeners will be attached.
hatemhosny
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @a0m0rajab
I have added some comments.
src/livecodes/html/templates.html
Outdated
| </div> | ||
|
|
||
| <!-- Inline: emit a "templates:filter" event with the current query so other scripts can perform filtering --> | ||
| <script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can move the logic to src/livecodes/UI/templates.ts.
Think of the html here as the "view" while the logic in templates.ts as the "controller" in MVC pattern.
Also if you do that, you can directly manipulate DOM elements e.g. add display: none; without having to emit events.
src/livecodes/html/templates.html
Outdated
| var val = e.target.value || ''; | ||
| // debounce to avoid excessive events while typing | ||
| clearTimeout(timeout); | ||
| timeout = setTimeout(function () { emit(val.trim()); }, 150); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a debounce function here that you can re-use.
src/livecodes/html/templates.html
Outdated
| </li> | ||
| <li class="templates-search"> | ||
| <label for="templates-search-input" class="visually-hidden" data-i18n="templates.search.label">Search templates</label> | ||
| <input id="templates-search-input" type="search" placeholder="Filter languages..." aria-label="Filter templates by language" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change "Filter languages..." to "Search templates...". And then we can search by title, languages and others (e.g. tags).
Also, after you finish your edits, please run npm run i18n-export to regenerate the i18n json and fix this build error.
|
Thank you @DevAbdelrahmanSayed |
|
Hi, thanks for mentioning me in the comments! I’d love to work on and finish this, but I might not be able to get to it before the weekend. Just a general note, it’s usually nice to check in with the PR contributor first before escalating to the maintainers. It tends to come across as more polite and professional. If the contributor doesn’t respond for a while and the PR becomes stale, then escalating to the maintainers would make sense. |
|
Salam @a0m0rajab 👋 If you do not have enough time to finish this, do you mind other contributors to continue the work you have started? Much appreciated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/livecodes/UI/templates.ts`:
- Around line 66-87: Call setupTemplatesSearch() after the templates UI is
mounted so the '#templates-search-input' listener is attached and can filter
'#templates-user' items; specifically, add a call to setupTemplatesSearch() at
the end of handleNew() when the modal opens (or immediately after
loadUserTemplates() finishes rendering items) to ensure the search input is
wired up to the filtering logic in setupTemplatesSearch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/livecodes/core.ts`:
- Around line 3279-3281: After templates finish rendering and
setupTemplatesSearch() is called, reapply the current query so any keystrokes
typed during load are honored: locate setupTemplatesSearch() and the search
input element it wires up (e.g., the searchInput/inputs used by
setupTemplatesSearch) and programmatically trigger the existing input handler by
dispatching an 'input' event (or calling the filter function directly) on that
element immediately after setupTemplatesSearch() so the list is filtered with
the current value.
src/livecodes/core.ts
Outdated
| }); | ||
| setupTemplatesSearch(); | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reapply the filter after templates render to honor early input.
If the user types while templates are still loading, the list is appended afterward and won’t be filtered until the next input event. Triggering one after render preserves the typed query.
🛠️ Suggested fix
starterTemplates.forEach((template) => {
const link = createStarterTemplateLink(template, starterTemplatesList, baseUrl);
eventsManager.addEventListener(
link,
'click',
(event) => {
event.preventDefault();
loadStarterTemplate(template.name, /* checkSaved= */ false);
},
false,
);
});
setupTemplatesSearch();
+ const searchInput = document.getElementById(
+ 'templates-search-input',
+ ) as HTMLInputElement | null;
+ searchInput?.dispatchEvent(new Event('input', { bubbles: true }));🤖 Prompt for AI Agents
In `@src/livecodes/core.ts` around lines 3279 - 3281, After templates finish
rendering and setupTemplatesSearch() is called, reapply the current query so any
keystrokes typed during load are honored: locate setupTemplatesSearch() and the
search input element it wires up (e.g., the searchInput/inputs used by
setupTemplatesSearch) and programmatically trigger the existing input handler by
dispatching an 'input' event (or calling the filter function directly) on that
element immediately after setupTemplatesSearch() so the list is filtered with
the current value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/livecodes/UI/templates.ts`:
- Around line 67-90: Update setupTemplatesSearch to accept a templatesContainer
parameter and scope DOM queries to it: change setupTemplatesSearch() to
setupTemplatesSearch(templatesContainer?: Element | Document) and use
templatesContainer.querySelectorAll('#templates-starter li') and
templatesContainer.querySelectorAll('#templates-user li') (falling back to
document when templatesContainer is not provided or not yet mounted). Also
ensure filterTemplates and debouncedFilter refer to the scoped items and keep
the existing debounce and input handler logic but query the input from
templatesContainer (or document) so timing and scoping issues are resolved.
- Line 31: Call setupTemplatesSearch after mounting or pass the templates
container into it so it queries the input within the detached node instead of
using document.getElementById; update the setupTemplatesSearch signature to
accept a container parameter (e.g., Element or HTMLElement) and replace
document.getElementById('templates-search-input') with
container.querySelector('#templates-search-input'), then ensure the call site
(where templatesContainer is created/mounted) passes templatesContainer into
setupTemplatesSearch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/livecodes/UI/templates.ts`:
- Around line 71-89: Filtering only runs on user input so dynamically added
templates from loadUserTemplates() bypass the current query; after new templates
are inserted call filterTemplates(input.value.trim()) (or dispatch an 'input'
event on input) to reapply the current query, e.g., at the end of
loadUserTemplates() or its promise callback so filterTemplates, debouncedFilter
and input stay in sync with newly added items.
| const filterTemplates = (query: string) => { | ||
| const mainItems = container.querySelectorAll('#templates-starter li'); | ||
| const userItems = container.querySelectorAll('#templates-user li'); | ||
| const items = Array.from(mainItems).concat(Array.from(userItems)); | ||
| items.forEach((item) => { | ||
| const text = item.textContent?.toLowerCase() || ''; | ||
| const matches = text.includes(query.toLowerCase()); | ||
| (item as HTMLElement).style.display = matches ? '' : 'none'; | ||
| }); | ||
| }; | ||
|
|
||
| const debouncedFilter = debounce((val: string) => { | ||
| filterTemplates(val.trim()); | ||
| }, 150); | ||
|
|
||
| input.addEventListener('input', (e: Event) => { | ||
| const val = (e.target as HTMLInputElement).value || ''; | ||
| debouncedFilter(val); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reapply filter when templates are loaded dynamically.
Filtering only runs on input events; if a user types a query and then loadUserTemplates() inserts items later, those new items won’t be filtered until the user types again. Consider reapplying the current query after templates load (e.g., call filterTemplates(input.value.trim()) or dispatch an input event) so the results stay consistent.
🤖 Prompt for AI Agents
In `@src/livecodes/UI/templates.ts` around lines 71 - 89, Filtering only runs on
user input so dynamically added templates from loadUserTemplates() bypass the
current query; after new templates are inserted call
filterTemplates(input.value.trim()) (or dispatch an 'input' event on input) to
reapply the current query, e.g., at the end of loadUserTemplates() or its
promise callback so filterTemplates, debouncedFilter and input stay in sync with
newly added items.
|
@hatemhosny Salam, just finished the PR, checked the lints locally and fixed them, will wait the actions to check them again. Sorry for the delay, did not expect myself to not be able to work on this in the last few weeks! |
|
Thanks a lot @a0m0rajab While reviewing your changes I found many fixes I needed to add in how I loaded and displayed templates. I have added these changes and started a PR to your branch here. Thank you very much ❤️ |
|
@hatemhosny thanks for that, I just merged the changes you made! I was not aware of the already implemented search functionality. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/livecodes/styles/inc-modal.scss`:
- Around line 67-69: The .large-fixed modal variant sets height: 85vh but is
still constrained by the base `#modal` rule max-height: 72vh; update the
.large-fixed selector (in inc-modal.scss) to also override the max-height (e.g.,
max-height: 85vh or max-height: none) so the declared height can take effect;
ensure you target the same specificity as `#modal` (or increase specificity) so
the override is applied.
In `@src/livecodes/UI/templates.ts`:
- Around line 99-130: The search handler in setupTemplatesSearch currently
listens to the 'keyup' event which misses paste/clear/IME updates; change the
listener on the input element returned by getTemplatesSearchInput to listen for
the 'input' event instead and call the existing debouncedFilter((e.target as
HTMLInputElement).value || '') so paste/clear/IME changes trigger
filterTemplates; keep the existing debounce and trimming behavior and leave
filterTemplates, debouncedFilter, and searchIndex usage unchanged.
In `@src/sdk/models.ts`:
- Around line 1461-1493: The TemplateAlias union currently contains a duplicate
entry 'prolog' which is already defined as a canonical value in TemplateName;
remove 'prolog' from the TemplateAlias type (leave it only in TemplateName) to
avoid redundancy and ambiguity, and run type checks to ensure no callers expect
'prolog' to be treated as an alias (update any uses referencing TemplateAlias if
needed).
♻️ Duplicate comments (1)
src/livecodes/core.ts (1)
3271-3305: Reapply the active search query after templates finish loading.
If the user types while templates are still loading, newly appended items won’t be filtered until the next keystroke. Trigger the existing filter handler (or dispatch the same event) after render.
🧹 Nitpick comments (1)
storybook/stories/EmbedOptions/template.stories.ts (1)
45-51: LGTM!The template values are correctly updated from
'pyodide'to'python-wasm'and from'clang'to'cpp-wasm', aligning with the updatedTemplateNametype.Consider renaming the export variables from
PythonPyodide/CppClangtoPythonWasm/CppWasmfor consistency with the new naming convention, though this is optional.
| &.large-fixed { | ||
| height: 85vh; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
large-fixed height is still capped by the default max-height.
#modal sets max-height: 72vh, so height: 85vh won’t take effect. Consider overriding max-height in the variant.
🐛 Proposed fix
&.large-fixed {
height: 85vh;
+ max-height: 85vh;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| &.large-fixed { | |
| height: 85vh; | |
| } | |
| &.large-fixed { | |
| height: 85vh; | |
| max-height: 85vh; | |
| } |
🤖 Prompt for AI Agents
In `@src/livecodes/styles/inc-modal.scss` around lines 67 - 69, The .large-fixed
modal variant sets height: 85vh but is still constrained by the base `#modal` rule
max-height: 72vh; update the .large-fixed selector (in inc-modal.scss) to also
override the max-height (e.g., max-height: 85vh or max-height: none) so the
declared height can take effect; ensure you target the same specificity as
`#modal` (or increase specificity) so the override is applied.
|
|
Thanks a lot @a0m0rajab |
i18n ActionsSource PR has been merged into the default branch. Maintainers can comment |



(This is a demo PR, will check the functionality later today)
This pull request enhances the templates UI by adding a search input for filtering templates by language and introduces an event-driven mechanism for template filtering. The main changes are grouped below:
UI Enhancements:
<input id="templates-search-input" ...>) to the templates navigation, allowing users to filter templates by language.Event-Driven Filtering:
templates:filtercustom event with the current query. This enables other scripts to react and perform the actual filtering logic.What type of PR is this? (check all applicable)
Description
Related Tickets & Documents
Fixes #900
This pull request adds a search/filter feature to the templates section in the
templates.htmlfile, allowing users to filter templates by language. It introduces a search input UI and emits a custom event to enable template filtering functionality.User interface improvements:
<input id="templates-search-input" ...>) to the templates navigation for filtering templates by language.Interactivity and event handling:
templates:filtercustom event with the current query to enable live filtering of templates.Mobile & Desktop Screenshots/Recordings
Added tests?
Added to documentations?
[optional] Are there any post-deployment tasks we need to perform?
[optional] What gif best describes this PR or how it makes you feel?
Summary by CodeRabbit
New Features
Style
Bug Fixes / UX
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.