Feature: Script Filtering
Relevant source files
The following files were used as context for generating this wiki page:The Script Filtering feature allows users to display a subset of their saved scripts based on a selected tag. This functionality is primarily managed by a central state store, which holds the current filter criteria and provides a derived list of items that match. The main script list component subscribes to this store and automatically re-renders when the filter changes, ensuring the UI is always in sync with the selected filter tag.
The core filtering logic resides within the useListStore Zustand store, which defines how scripts are filtered. A special "Archive" tag is used to control script visibility, effectively creating a separate view for archived items and hiding them from default and other filtered views.
Architecture and Data Flow
The filtering system is built around a centralized state management pattern using Zustand (useListStore). UI components read the filter state and the filtered data from this store.
State Management (useListStore)
The useListStore hook is the single source of truth for script data, tags, and the current filter state.
Sources: src/Hooks/useListStore.js
The diagram below shows the key state and functions related to filtering within the store.
This diagram illustrates the filtering-related parts of the useListStore, where setFilterTag updates the filterTag state, and getFilteredItems uses that state to compute the visible list.
Sources: src/Hooks/useListStore.js:29-69
Key Store Properties
| Name | Type | Description |
|---|---|---|
filterTag | string | null | Stores the currently selected tag for filtering. A null value indicates no filter is applied. |
setFilterTag(tag) | function | An action to update the filterTag state. |
getFilteredItems() | function | A selector that returns an array of script items based on the current filterTag. |
Sources: src/Hooks/useListStore.js:33-35, src/Hooks/useListStore.js:59-61, src/Hooks/useListStore.js:63-76
Filtering Logic
The getFilteredItems function contains the specific rules for filtering:
- If
filterTagis"Archive", it returns only items that include the "Archive" tag. - If
filterTagis any other string, it returns items that include that tag and do not include the "Archive" tag. - If
filterTagisnullor falsy, it returns all items that do not include the "Archive" tag. This is the default view.
Sources: src/Hooks/useListStore.js:64-75
// src/Hooks/useListStore.js:63-76
getFilteredItems: () => {
const { items, filterTag } = get();
if (filterTag === "Archive") {
return items.filter((item) => item.tags.includes(filterTag));
} else if (filterTag) {
return items.filter(
(item) =>
item.tags.includes(filterTag) && !item.tags.includes("Archive"),
);
} else {
return items.filter((item) => !item.tags.includes("Archive"));
}
},
Data Flow
The following sequence diagram shows how a user interaction (though not explicitly implemented in the provided files) would trigger a filter change and update the UI.
This diagram depicts the flow where a UI component calls setFilterTag, which updates the store, causing the List.jsx component to re-fetch the filtered items and update the display.
Sources: src/Hooks/useListStore.js:59-61, src/components/Form/List.jsx:26-27
UI Components
List.jsx
This component is responsible for rendering the list of scripts. It uses the getFilteredItems selector from useListStore to get the data it needs to display. It then maps over the filteredItems array and renders a ListItem for each script.
Sources: src/components/Form/List.jsx
// src/components/Form/List.jsx:25-27
export default function List({ setVisible, visible }) {
const filterTag = useListStore((state) => state.filterTag);
const getFilteredItems = useListStore((state) => state.getFilteredItems);
const filteredItems = getFilteredItems();
// ...
return (
<div className="bg-transparent w-full h-2/3 flex flex-col items-center overflow-y-scroll gap-y-5">
<AnimatePresence>
{filteredItems.map((item) => (
<ListItem
key={item.id}
item={item}
// ...
/>
))}
</AnimatePresence>
</div>
);
}
FilterComp.jsx (Divergent Implementation)
The FilterComp.jsx file contains a React component TagFilter that appears designed for a multi-tag filtering system. It uses checkboxes to allow the user to select multiple tags.
However, its state management logic is inconsistent with the implementation in useListStore.js. The component attempts to use selectedFilterTags (plural) and setFilterTags from the store, but the store only provides filterTag (singular) and setFilterTag. This suggests that FilterComp.jsx may be part of a deprecated or incomplete feature.
Sources: src/components/Form/FilterComp.jsx:5-7
// src/components/Form/FilterComp.jsx:5-15
export function TagFilter() {
const selectedFilterTags = useListStore(state => state.selectedFilterTags);
const setFilterTags = useListStore(state => state.setFilterTags);
const tags= useListStore((state) => state.tags);
const toggleTag = (tag) => {
if (selectedFilterTags.includes(tag)) {
setFilterTags(selectedFilterTags.filter(t => t !== tag));
} else {
setFilterTags([...selectedFilterTags, tag]);
}
};
// ...
}
As shown, this component's logic for toggling tags in an array (selectedFilterTags) does not match the single-string filterTag state in useListStore.js.
Sources: src/components/Form/FilterComp.jsx:9-15, src/Hooks/useListStore.js:33-35
Related Components
While not directly part of filtering, the following components are essential to the ecosystem as they create the data (scripts and tags) that is filtered.
| Component | Purpose | Relevant Files |
|---|---|---|
Form.jsx | Renders a form to add a new script. Allows users to assign one or more existing tags to the new script. | [src/components/Form/Form.jsx](https://github.com/SemtexHR/Scripty/blob/HEAD/src/components/Form/Form.jsx) |
FormTag.jsx | Renders a form to add a new tag to the global list of tags in useListStore. | [src/components/Form/FormTag.jsx](https://github.com/SemtexHR/Scripty/blob/HEAD/src/components/Form/FormTag.jsx) |
App.jsx | The main application component that renders the List and provides buttons to open the Form and FormTag modals. It imports setFilterTag but does not currently use it. | [src/App.jsx:7, 61-75](https://github.com/SemtexHR/Scripty/blob/HEAD/src/App.jsx#L7) |
Summary
The script filtering feature is a core organizational tool in Scripty, powered by a centralized Zustand store. The filtering logic is concentrated in the getFilteredItems selector, which provides a declarative way to derive the visible script list based on a single filterTag. A notable aspect is the special handling of the "Archive" tag, which segregates archived scripts from all other views. While the foundation for single-tag filtering is solid and in use by the List component, there is evidence of an incomplete or divergent multi-tag filtering feature in FilterComp.jsx.