Skip to content
Twilight React Playground
ثيم رائدaren

sortOptions

functionBeginnerserverbrowserlive demo

Returns the five product sort orders the listing understands, with names in the page language and the current one flagged, ready for a select.

import { sortOptions } from '@salla.sa/twilight-theme-engine/utils';

In plain words

Product lists let shoppers sort: suggested, best selling, top rated, price low to high, price high to low. sortOptions(current, t) returns those five as a list of { id, name, is_selected }, with name translated. Use id as each option's value and name as its label.

The listing page reads the chosen id from the sort parameter of the address, as in ?sort=bestSell.

Signature

function sortOptions(
  currentSort: string,
  t: (key: string, fallback: string) => string
): Array<{ id: string; name: string; is_selected: boolean }>

// ids, in this order:
// 'ourSuggest' | 'bestSell' | 'topRated' | 'priceFromLowToTop' | 'priceFromTopToLow'

Try it live

The five sort orders Salla's product API understands, named in the page language, with the current one flagged.Try this: pick newest: it is not one of the five, so nothing is flagged and the select falls back to its first option. Switch the language pill too.
Storefront canvas · en · LTR
ourSuggestOur Suggestionsis_selected: false
bestSellBest selleris_selected: true
topRatedTop ratedis_selected: false
priceFromLowToTopPrice low to highis_selected: false
priceFromTopToLowPrice high to lowis_selected: false
Controls
What a theme writes
import { useMemo } from 'react';
import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
import { useLocation, useNavigate } from '@salla.sa/twilight-theme-engine/providers';
import { sortOptions } from '@salla.sa/twilight-theme-engine/utils';

export function SortSelect({ current = 'bestSell' }: { current?: string }) {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const location = useLocation();
  const options = useMemo(() => sortOptions(current, t), [current, t]);

  return (
    <select
      className="form-input"
      value={current}
      onChange={(event) => {
        // Built from the router's location, never window.location.
        const params = new URLSearchParams(location.searchStr);
        params.set('sort', event.target.value);
        params.delete('page');
        navigate(`${location.pathname}?${params.toString()}`);
      }}
    >
      {options.map((option) => (
        <option key={option.id} value={option.id}>
          {option.name}
        </option>
      ))}
    </select>
  );
}

Example

app/components/listing/SortSelect.tsx
import { useMemo } from 'react';
import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
import { useLocation, useNavigate } from '@salla.sa/twilight-theme-engine/providers';
import { sortOptions } from '@salla.sa/twilight-theme-engine/utils';

export function SortSelect({ current }: { current: string }) {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const location = useLocation();
  const options = useMemo(() => sortOptions(current, t), [current, t]);

  return (
    <select
      className="form-input"
      value={current}
      onChange={(event) => {
        const params = new URLSearchParams(location.searchStr);
        params.set('sort', event.target.value);
        params.delete('page');
        navigate(`${location.pathname}?${params.toString()}`);
      }}
    >
      {options.map((option) => (
        <option key={option.id} value={option.id}>
          {option.name}
        </option>
      ))}
    </select>
  );
}

How it behaves

  • The names come from t with the keys pages.categories.sort_by_suggestions, sort_by_sales, sort_by_rating, sort_by_price_az and sort_by_price_za, falling back to "Our Suggestions", "Best Seller", "Top Rated", "Price Low to High" and "Price High to Low". Pass t from useTranslation().

  • is_selected is simply currentSort === id. The listing loader uses ourSuggest when the address has no sort, and passes the value to the products API unchanged.

  • The engine's ProductListPage builds its select from it, exactly like the example: it sets sort, removes page and navigates with the router's location.

  • It returns a new array on every call; wrap it in useMemo when a child depends on its identity.

Gotchas

  • Building the new address from window.location adds the store segment a second time on localhost and the preview host, where the address bar carries it. Use useLocation() and useNavigate() from @salla.sa/twilight-theme-engine/providers.

  • A current value that is not one of the five ids flags nothing, and a controlled select then shows its first option.

Related

Source and docs