diff --git a/src/apps/state-docs/pd-to-md.ts b/src/apps/state-docs/pd-to-md.ts
index f0df30519f9e4e18dfd3cd60509d6b45baf244f0..a55d372a06c822da0839c01d8cc612cff4a898f9 100644
--- a/src/apps/state-docs/pd-to-md.ts
+++ b/src/apps/state-docs/pd-to-md.ts
@@ -39,7 +39,7 @@ function paramInfo(param: PD.Any, offset: number): string {
     }
 }
 
-function oToS(options: readonly (readonly [string, string])[]) {
+function oToS(options: readonly (readonly [string, string] | [string, string, string])[]) {
     return options.map(o => `'${o[0]}'`).join(', ');
 }
 
diff --git a/src/examples/proteopedia-wrapper/coloring.ts b/src/examples/proteopedia-wrapper/coloring.ts
index 0f7bc4b3a5f423f5ccabcdb4f5cb38ca521508fb..3b25496365d11cc143d1c182c1e8a273286a171b 100644
--- a/src/examples/proteopedia-wrapper/coloring.ts
+++ b/src/examples/proteopedia-wrapper/coloring.ts
@@ -96,6 +96,7 @@ export function createProteopediaCustomTheme(colors: number[]) {
 
     const ProteopediaCustomColorThemeProvider: ColorTheme.Provider<ProteopediaCustomColorThemeParams> = {
         label: 'Proteopedia Custom',
+        category: 'Custom',
         factory: ProteopediaCustomColorTheme,
         getParams: getChainIdColorThemeParams,
         defaultValues: PD.getDefaultValues(ProteopediaCustomColorThemeParams),
diff --git a/src/mol-model-props/common/custom-element-property.ts b/src/mol-model-props/common/custom-element-property.ts
index 3dea414a939e75449f7438195624b5387c5b300f..4684a20e428f90b48a8ec7f6b404faf13f19e911 100644
--- a/src/mol-model-props/common/custom-element-property.ts
+++ b/src/mol-model-props/common/custom-element-property.ts
@@ -99,6 +99,7 @@ namespace CustomElementProperty {
 
         return {
             label: modelProperty.label,
+            category: 'Custom',
             factory: Coloring,
             getParams: () => ({}),
             defaultValues: {},
diff --git a/src/mol-model-props/computed/themes/accessible-surface-area.ts b/src/mol-model-props/computed/themes/accessible-surface-area.ts
index fe2a60134c831deb06d546d4bec2c49f7ec8252c..3218bc0b5ba49050ebe101babd7c00dee5ff774b 100644
--- a/src/mol-model-props/computed/themes/accessible-surface-area.ts
+++ b/src/mol-model-props/computed/themes/accessible-surface-area.ts
@@ -68,6 +68,7 @@ export function AccessibleSurfaceAreaColorTheme(ctx: ThemeDataContext, props: PD
 
 export const AccessibleSurfaceAreaColorThemeProvider: ColorTheme.Provider<AccessibleSurfaceAreaColorThemeParams> = {
     label: 'Accessible Surface Area',
+    category: ColorTheme.Category.Computed,
     factory: AccessibleSurfaceAreaColorTheme,
     getParams: getAccessibleSurfaceAreaColorThemeParams,
     defaultValues: PD.getDefaultValues(AccessibleSurfaceAreaColorThemeParams),
diff --git a/src/mol-model-props/computed/themes/interaction-type.ts b/src/mol-model-props/computed/themes/interaction-type.ts
index d6ede61affd4cb58b9bb04faf2037961e431ad13..f816d2b4180da5ebad18bba0ec03c5578bf36d90 100644
--- a/src/mol-model-props/computed/themes/interaction-type.ts
+++ b/src/mol-model-props/computed/themes/interaction-type.ts
@@ -108,6 +108,7 @@ export function InteractionTypeColorTheme(ctx: ThemeDataContext, props: PD.Value
 
 export const InteractionTypeColorThemeProvider: ColorTheme.Provider<InteractionTypeColorThemeParams> = {
     label: 'Interaction Type',
+    category: ColorTheme.Category.Computed,
     factory: InteractionTypeColorTheme,
     getParams: getInteractionTypeColorThemeParams,
     defaultValues: PD.getDefaultValues(InteractionTypeColorThemeParams),
diff --git a/src/mol-model-props/integrative/cross-link-restraint/color.ts b/src/mol-model-props/integrative/cross-link-restraint/color.ts
index 4000f437139cccdbca5c6892e00bd0e0b07770b2..3ba49d73d14c505ae0192d5584ae459fc5940173 100644
--- a/src/mol-model-props/integrative/cross-link-restraint/color.ts
+++ b/src/mol-model-props/integrative/cross-link-restraint/color.ts
@@ -63,6 +63,7 @@ export function CrossLinkColorTheme(ctx: ThemeDataContext, props: PD.Values<Cros
 
 export const CrossLinkColorThemeProvider: ColorTheme.Provider<CrossLinkColorThemeParams> = {
     label: 'Cross Link',
+    category: ColorTheme.Category.Advanced,
     factory: CrossLinkColorTheme,
     getParams: getCrossLinkColorThemeParams,
     defaultValues: PD.getDefaultValues(CrossLinkColorThemeParams),
diff --git a/src/mol-model-props/pdbe/themes/structure-quality-report.ts b/src/mol-model-props/pdbe/themes/structure-quality-report.ts
index e3296bab946d7dc478f50b5b20c3cfe05a533ef4..a4b23e9eb54470a393a5df10319088adc69b6b74 100644
--- a/src/mol-model-props/pdbe/themes/structure-quality-report.ts
+++ b/src/mol-model-props/pdbe/themes/structure-quality-report.ts
@@ -79,6 +79,7 @@ export function StructureQualityReportColorTheme(ctx: ThemeDataContext, props: P
 
 export const StructureQualityReportColorThemeProvider: ColorTheme.Provider<Params> =  {
     label: 'PDBe Structure Quality Report',
+    category: 'PDBe',
     factory: StructureQualityReportColorTheme,
     getParams: ctx => {
         const issueTypes = StructureQualityReport.getIssueTypes(ctx.structure);
diff --git a/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts b/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts
index b8e1d2f7c712961ea20b358d91856fd191274744..cbab8e1e4645869dcf81445f074bce354bf00abb 100644
--- a/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts
+++ b/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts
@@ -93,6 +93,7 @@ export function AssemblySymmetryClusterColorTheme(ctx: ThemeDataContext, props:
 
 export const AssemblySymmetryClusterColorThemeProvider: ColorTheme.Provider<AssemblySymmetryClusterColorThemeParams> = {
     label: 'RCSB Assembly Symmetry Cluster',
+    category: 'RCSB',
     factory: AssemblySymmetryClusterColorTheme,
     getParams: getAssemblySymmetryClusterColorThemeParams,
     defaultValues: PD.getDefaultValues(AssemblySymmetryClusterColorThemeParams),
diff --git a/src/mol-model-props/rcsb/themes/density-fit.ts b/src/mol-model-props/rcsb/themes/density-fit.ts
index 9bc3d3d0fe4f8756e9483ad1b205e2966629a677..319c3c60297e757a40f7c5880c1db54d23e78ec1 100644
--- a/src/mol-model-props/rcsb/themes/density-fit.ts
+++ b/src/mol-model-props/rcsb/themes/density-fit.ts
@@ -62,6 +62,7 @@ export function DensityFitColorTheme(ctx: ThemeDataContext, props: {}): ColorThe
 
 export const DensityFitColorThemeProvider: ColorTheme.Provider<{}> = {
     label: 'RCSB Density Fit',
+    category: 'RCSB',
     factory: DensityFitColorTheme,
     getParams: () => ({}),
     defaultValues: PD.getDefaultValues({}),
diff --git a/src/mol-model-props/rcsb/themes/geometry-quality.ts b/src/mol-model-props/rcsb/themes/geometry-quality.ts
index 1f39b8de4b19e47b1765c0c85ae93cbe7ab9c64f..ca6d54e3507eebe3a716fdb56e70f272864985d2 100644
--- a/src/mol-model-props/rcsb/themes/geometry-quality.ts
+++ b/src/mol-model-props/rcsb/themes/geometry-quality.ts
@@ -102,6 +102,7 @@ export function GeometryQualityColorTheme(ctx: ThemeDataContext, props: PD.Value
 
 export const GeometryQualityColorThemeProvider: ColorTheme.Provider<GeometricQualityColorThemeParams> = {
     label: 'RCSB Geometry Quality',
+    category: 'RCSB',
     factory: GeometryQualityColorTheme,
     getParams: getGeometricQualityColorThemeParams,
     defaultValues: PD.getDefaultValues(getGeometricQualityColorThemeParams({})),
diff --git a/src/mol-model-props/rcsb/themes/random-coil-index.ts b/src/mol-model-props/rcsb/themes/random-coil-index.ts
index 596aa205587e6fbbade46e08d205404414e226a5..c8a7e90f21bbbd3c54f40048a7312dbe0c21c85f 100644
--- a/src/mol-model-props/rcsb/themes/random-coil-index.ts
+++ b/src/mol-model-props/rcsb/themes/random-coil-index.ts
@@ -53,6 +53,7 @@ export function RandomCoilIndexColorTheme(ctx: ThemeDataContext, props: {}): Col
 
 export const RandomCoilIndexColorThemeProvider: ColorTheme.Provider<{}> = {
     label: 'RCSB Random Coil Index',
+    category: 'RCSB',
     factory: RandomCoilIndexColorTheme,
     getParams: () => ({}),
     defaultValues: PD.getDefaultValues({}),
diff --git a/src/mol-plugin-ui/controls/action-menu.tsx b/src/mol-plugin-ui/controls/action-menu.tsx
index 0d67b8c80475d366ef9b372ebc6772fee5cd8168..bc223a0debb329857133837a6d9f9735cd9765e8 100644
--- a/src/mol-plugin-ui/controls/action-menu.tsx
+++ b/src/mol-plugin-ui/controls/action-menu.tsx
@@ -7,6 +7,7 @@
 import * as React from 'react'
 import { Icon } from './common';
 import { Subscription, BehaviorSubject, Observable } from 'rxjs';
+import { ParamDefinition } from '../../mol-util/param-definition';
 
 export class ActionMenu {
     private _command: BehaviorSubject<ActionMenu.Command>;
@@ -139,16 +140,29 @@ export namespace ActionMenu {
         }
     }
 
-    class Section extends React.PureComponent<{ menu: ActionMenu, header?: string, items: Spec, onSelect: OnSelect, current: Item | undefined  }, { isExpanded: boolean }> {
-        state = { isExpanded: false }
+    type SectionProps = { menu: ActionMenu, header?: string, items: Spec, onSelect: OnSelect, current: Item | undefined }
+    type SectionState = { items: Spec, current: Item | undefined, isExpanded: boolean }
+
+    class Section extends React.PureComponent<SectionProps, SectionState> {
+        state = {
+            items: this.props.items,
+            current: this.props.current,
+            isExpanded: !!this.props.current && !!findCurrent(this.props.items, this.props.current.value)
+        }
 
         toggleExpanded = (e: React.MouseEvent<HTMLButtonElement>) => {
             this.setState({ isExpanded: !this.state.isExpanded });
             e.currentTarget.blur();
         }
 
+        static getDerivedStateFromProps(props: SectionProps, state: SectionState) {
+            if (props.items === state.items && props.current === state.current) return null;
+            return { items: props.items, current: props.current, isExpanded: props.current && !!findCurrent(props.items, props.current.value) }
+        }
+
         render() {
             const { header, items, onSelect, current, menu } = this.props;
+
             if (typeof items === 'string') return null;
             if (isItem(items)) return <Action menu={menu} item={items} onSelect={onSelect} current={current} />
             return <div>
@@ -196,4 +210,47 @@ export namespace ActionMenu {
         if (value) return { name, icon: iconOrValue, value };
         return { name, value: iconOrValue };
     }
+
+    function createSpecFromSelectParamSimple(param: ParamDefinition.Select<any>) {
+        const spec: Item[] = [];
+        for (const [v, l] of param.options) {
+            spec.push(ActionMenu.Item(l, v));
+        }
+        return spec as Spec;
+    }
+
+    function createSpecFromSelectParamCategories(param: ParamDefinition.Select<any>) {
+        const cats = new Map<string, (Item | string)[]>();
+        const spec: (Item | (Item | string)[] | string)[] = [];
+        for (const [v, l, c] of param.options) {
+            if (!!c) {
+                let cat = cats.get(c);
+                if (!cat) {
+                    cat = [c];
+                    cats.set(c, cat);
+                    spec.push(cat);
+                }
+                cat.push(ActionMenu.Item(l, v));
+            } else {
+                spec.push(ActionMenu.Item(l, v));
+            }
+        }
+        return spec as Spec;
+    }
+
+    export function createSpecFromSelectParam(param: ParamDefinition.Select<any>) {
+        for (const o of param.options) {
+            if (!!o[2]) return createSpecFromSelectParamCategories(param);
+        }
+        return createSpecFromSelectParamSimple(param);
+    }
+
+    export function findCurrent(spec: Spec, value: any): Item | undefined {
+        if (typeof spec === 'string') return;
+        if (isItem(spec)) return spec.value === value ? spec : void 0;
+        for (const s of spec) {
+            const found = findCurrent(s, value);
+            if (found) return found;
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/mol-plugin-ui/controls/parameters.tsx b/src/mol-plugin-ui/controls/parameters.tsx
index f52c546ccc97e69402aa253f5a666c0933e93173..2576f59e727f1a7fc59e0b1f69c53b020103fff4 100644
--- a/src/mol-plugin-ui/controls/parameters.tsx
+++ b/src/mol-plugin-ui/controls/parameters.tsx
@@ -8,7 +8,7 @@
 import { Vec2, Vec3 } from '../../mol-math/linear-algebra';
 import { Color } from '../../mol-util/color';
 import { ColorListName, getColorListFromName } from '../../mol-util/color/lists';
-import { memoize1 } from '../../mol-util/memoize';
+import { memoize1, memoizeLatest } from '../../mol-util/memoize';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { camelCaseToWords } from '../../mol-util/string';
 import * as React from 'react';
@@ -328,22 +328,14 @@ export class SelectControl extends SimpleParam<PD.Select<string | number>> {
         this.update(value);
     }
 
+    items = memoizeLatest((param: PD.Select<any>) => ActionMenu.createSpecFromSelectParam(param));
+
     renderControl() {
-        const isInvalid = this.props.value !== void 0 && !this.props.param.options.some(e => e[0] === this.props.value);
-        const items: ActionMenu.Item[] = [];
-        let current: ActionMenu.Item | undefined = void 0;
-        if (isInvalid) {
-            current = ActionMenu.Item(`[Invalid] ${this.props.value}`, this.props.value);
-            items.push(current);
-        }
-        for (const [value, label] of this.props.param.options) {
-            const item = ActionMenu.Item(label, value);
-            items.push(item);
-            if (value === this.props.value) current = item;
-        }
+        const items = this.items(this.props.param);
+        const current = ActionMenu.findCurrent(items, this.props.value);
 
         return <ActionMenu.Toggle menu={this.menu} disabled={this.props.isDisabled} 
-            onSelect={this.onSelect} items={items as ActionMenu.Spec} label={current?.name}
+            onSelect={this.onSelect} items={items as ActionMenu.Spec} label={current?.name || `[Invalid] ${this.props.value}`}
             current={current} />;
     }
 
diff --git a/src/mol-theme/color.ts b/src/mol-theme/color.ts
index 67537bb8ff32bf4ab8bde1e6e473231bf470f800..6efcc769161ac2472ea82fdf9c7ac70d73ec817d 100644
--- a/src/mol-theme/color.ts
+++ b/src/mol-theme/color.ts
@@ -46,6 +46,13 @@ interface ColorTheme<P extends PD.Params> {
     readonly legend?: Readonly<ScaleLegend | TableLegend>
 }
 namespace ColorTheme {
+    export const enum Category {
+        Basic = 'Basic',
+        Advanced = 'Advanced',
+        Computed = 'Computed',
+        Misc = 'Miscellaneous'
+    }
+
     export type Props = { [k: string]: any }
     export type Factory<P extends PD.Params> = (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<P>
     export const EmptyFactory = () => Empty
@@ -62,7 +69,7 @@ namespace ColorTheme {
     }
 
     export interface Provider<P extends PD.Params> extends ThemeProvider<ColorTheme<P>, P> { }
-    export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true }
+    export const EmptyProvider: Provider<{}> = { label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true }
 
     export type Registry = ThemeRegistry<ColorTheme<any>>
     export function createRegistry() {
diff --git a/src/mol-theme/color/carbohydrate-symbol.ts b/src/mol-theme/color/carbohydrate-symbol.ts
index f29d10170f11dffba9626bc8ac4a212e68db3d94..853e7cf9ce3828c1288be8b09521914d6b4ef342 100644
--- a/src/mol-theme/color/carbohydrate-symbol.ts
+++ b/src/mol-theme/color/carbohydrate-symbol.ts
@@ -61,7 +61,8 @@ export function CarbohydrateSymbolColorTheme(ctx: ThemeDataContext, props: PD.Va
 }
 
 export const CarbohydrateSymbolColorThemeProvider: ColorTheme.Provider<CarbohydrateSymbolColorThemeParams> = {
-    label: 'Carbohydrate Symbol',
+    label: 'Carbohydrate Symbol',    
+    category: ColorTheme.Category.Advanced,
     factory: CarbohydrateSymbolColorTheme,
     getParams: getCarbohydrateSymbolColorThemeParams,
     defaultValues: PD.getDefaultValues(CarbohydrateSymbolColorThemeParams),
diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts
index 16c072ff40491cae1f2c181df6d4eef3194fe1fa..d9ae75cb9d3fb4282a2016974059d54ec0afdb20 100644
--- a/src/mol-theme/color/chain-id.ts
+++ b/src/mol-theme/color/chain-id.ts
@@ -119,6 +119,7 @@ export function ChainIdColorTheme(ctx: ThemeDataContext, props: PD.Values<ChainI
 
 export const ChainIdColorThemeProvider: ColorTheme.Provider<ChainIdColorThemeParams> = {
     label: 'Chain Id',
+    category: ColorTheme.Category.Basic,
     factory: ChainIdColorTheme,
     getParams: getChainIdColorThemeParams,
     defaultValues: PD.getDefaultValues(ChainIdColorThemeParams),
diff --git a/src/mol-theme/color/element-index.ts b/src/mol-theme/color/element-index.ts
index be94f3376dd57a6609497ea829522055eff3e7d2..d2e13588ba64f46174ae2a5889d90800c3374d41 100644
--- a/src/mol-theme/color/element-index.ts
+++ b/src/mol-theme/color/element-index.ts
@@ -73,6 +73,7 @@ export function ElementIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<E
 
 export const ElementIndexColorThemeProvider: ColorTheme.Provider<ElementIndexColorThemeParams> = {
     label: 'Element Index',
+    category: ColorTheme.Category.Basic,
     factory: ElementIndexColorTheme,
     getParams: getElementIndexColorThemeParams,
     defaultValues: PD.getDefaultValues(ElementIndexColorThemeParams),
diff --git a/src/mol-theme/color/element-symbol.ts b/src/mol-theme/color/element-symbol.ts
index 6f2f8881f7d016719366e50f9c3730ad96ed996d..8c559ff64356da9d0083e9bb1fa9098f9edf14e6 100644
--- a/src/mol-theme/color/element-symbol.ts
+++ b/src/mol-theme/color/element-symbol.ts
@@ -69,6 +69,7 @@ export function ElementSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values<
 
 export const ElementSymbolColorThemeProvider: ColorTheme.Provider<ElementSymbolColorThemeParams> = {
     label: 'Element Symbol',
+    category: ColorTheme.Category.Basic,
     factory: ElementSymbolColorTheme,
     getParams: getElementSymbolColorThemeParams,
     defaultValues: PD.getDefaultValues(ElementSymbolColorThemeParams),
diff --git a/src/mol-theme/color/entity-source.ts b/src/mol-theme/color/entity-source.ts
index a8ac312bfe1693d8be1637d780f1709702303b5d..e8b4e71bc264df06283932b4566ad48039df0320 100644
--- a/src/mol-theme/color/entity-source.ts
+++ b/src/mol-theme/color/entity-source.ts
@@ -175,6 +175,7 @@ export function EntitySourceColorTheme(ctx: ThemeDataContext, props: PD.Values<E
 
 export const EntitySourceColorThemeProvider: ColorTheme.Provider<EntitySourceColorThemeParams> = {
     label: 'Entity Source',
+    category: ColorTheme.Category.Advanced,
     factory: EntitySourceColorTheme,
     getParams: getEntitySourceColorThemeParams,
     defaultValues: PD.getDefaultValues(EntitySourceColorThemeParams),
diff --git a/src/mol-theme/color/hydrophobicity.ts b/src/mol-theme/color/hydrophobicity.ts
index 47f3b94e424b93a3c2741a2bee072659f82f87f2..e49e3f25cc77111133365feb1e1a55d1b5c5605b 100644
--- a/src/mol-theme/color/hydrophobicity.ts
+++ b/src/mol-theme/color/hydrophobicity.ts
@@ -94,6 +94,7 @@ export function HydrophobicityColorTheme(ctx: ThemeDataContext, props: PD.Values
 
 export const HydrophobicityColorThemeProvider: ColorTheme.Provider<HydrophobicityColorThemeParams> = {
     label: 'Hydrophobicity',
+    category: ColorTheme.Category.Advanced,
     factory: HydrophobicityColorTheme,
     getParams: getHydrophobicityColorThemeParams,
     defaultValues: PD.getDefaultValues(HydrophobicityColorThemeParams),
diff --git a/src/mol-theme/color/illustrative.ts b/src/mol-theme/color/illustrative.ts
index 6025f1eed563a09a307540d332fc67f3f4583bd7..9b86d8b97a76e5ac85504745ffb30c46fa28b17a 100644
--- a/src/mol-theme/color/illustrative.ts
+++ b/src/mol-theme/color/illustrative.ts
@@ -76,6 +76,7 @@ export function IllustrativeColorTheme(ctx: ThemeDataContext, props: PD.Values<I
 
 export const IllustrativeColorThemeProvider: ColorTheme.Provider<IllustrativeColorThemeParams> = {
     label: 'Illustrative',
+    category: ColorTheme.Category.Misc,
     factory: IllustrativeColorTheme,
     getParams: getIllustrativeColorThemeParams,
     defaultValues: PD.getDefaultValues(IllustrativeColorThemeParams),
diff --git a/src/mol-theme/color/model-index.ts b/src/mol-theme/color/model-index.ts
index fd98c44f77c4797a3710b20f0313f8969e25b899..f7cc54bf7cdd7df506716c5e56f2239bc1d31c4f 100644
--- a/src/mol-theme/color/model-index.ts
+++ b/src/mol-theme/color/model-index.ts
@@ -61,6 +61,7 @@ export function ModelIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<Mod
 
 export const ModelIndexColorThemeProvider: ColorTheme.Provider<ModelIndexColorThemeParams> = {
     label: 'Model Index',
+    category: ColorTheme.Category.Basic,
     factory: ModelIndexColorTheme,
     getParams: getModelIndexColorThemeParams,
     defaultValues: PD.getDefaultValues(ModelIndexColorThemeParams),
diff --git a/src/mol-theme/color/molecule-type.ts b/src/mol-theme/color/molecule-type.ts
index 49f891381cf11888e0264233757fc4051bdc2707..668f8ccfe8b6fc9becc285f90490bb814433ee5d 100644
--- a/src/mol-theme/color/molecule-type.ts
+++ b/src/mol-theme/color/molecule-type.ts
@@ -78,6 +78,7 @@ export function MoleculeTypeColorTheme(ctx: ThemeDataContext, props: PD.Values<M
 
 export const MoleculeTypeColorThemeProvider: ColorTheme.Provider<MoleculeTypeColorThemeParams> = {
     label: 'Molecule Type',
+    category: ColorTheme.Category.Advanced,
     factory: MoleculeTypeColorTheme,
     getParams: getMoleculeTypeColorThemeParams,
     defaultValues: PD.getDefaultValues(MoleculeTypeColorThemeParams),
diff --git a/src/mol-theme/color/occupancy.ts b/src/mol-theme/color/occupancy.ts
index cf609f010a192f7adad85f8c1846d376b30e2627..7cfa1c4580b737c2c65a4349ec72e83ec553ebe0 100644
--- a/src/mol-theme/color/occupancy.ts
+++ b/src/mol-theme/color/occupancy.ts
@@ -60,6 +60,7 @@ export function OccupancyColorTheme(ctx: ThemeDataContext, props: PD.Values<Occu
 
 export const OccupancyColorThemeProvider: ColorTheme.Provider<OccupancyColorThemeParams> = {
     label: 'Occupancy',
+    category: ColorTheme.Category.Advanced,
     factory: OccupancyColorTheme,
     getParams: getOccupancyColorThemeParams,
     defaultValues: PD.getDefaultValues(OccupancyColorThemeParams),
diff --git a/src/mol-theme/color/operator-hkl.ts b/src/mol-theme/color/operator-hkl.ts
index 2469356eaa12799c0496bf2f27cad96a04184311..d08c290333e47d901e051a0e339a778063c7f9f5 100644
--- a/src/mol-theme/color/operator-hkl.ts
+++ b/src/mol-theme/color/operator-hkl.ts
@@ -119,6 +119,7 @@ export function OperatorHklColorTheme(ctx: ThemeDataContext, props: PD.Values<Op
 
 export const OperatorHklColorThemeProvider: ColorTheme.Provider<OperatorHklColorThemeParams> = {
     label: 'Operator HKL',
+    category: ColorTheme.Category.Advanced,
     factory: OperatorHklColorTheme,
     getParams: getOperatorHklColorThemeParams,
     defaultValues: PD.getDefaultValues(OperatorHklColorThemeParams),
diff --git a/src/mol-theme/color/operator-name.ts b/src/mol-theme/color/operator-name.ts
index 16d48b147f4833878b6bd90452f70ac5dbb5a06d..61b4e95c4e3c9704615e298547173aa6d7adc9cb 100644
--- a/src/mol-theme/color/operator-name.ts
+++ b/src/mol-theme/color/operator-name.ts
@@ -85,6 +85,7 @@ export function OperatorNameColorTheme(ctx: ThemeDataContext, props: PD.Values<O
 
 export const OperatorNameColorThemeProvider: ColorTheme.Provider<OperatorNameColorThemeParams> = {
     label: 'Operator Name',
+    category: ColorTheme.Category.Advanced,
     factory: OperatorNameColorTheme,
     getParams: getOperatorNameColorThemeParams,
     defaultValues: PD.getDefaultValues(OperatorNameColorThemeParams),
diff --git a/src/mol-theme/color/polymer-id.ts b/src/mol-theme/color/polymer-id.ts
index 46955e905c48bad6d951683869e8c9f3fb5f94ee..3e796d3d9aa2e4449bb203f54102619271c90421 100644
--- a/src/mol-theme/color/polymer-id.ts
+++ b/src/mol-theme/color/polymer-id.ts
@@ -128,6 +128,7 @@ export function PolymerIdColorTheme(ctx: ThemeDataContext, props: PD.Values<Poly
 
 export const PolymerIdColorThemeProvider: ColorTheme.Provider<PolymerIdColorThemeParams> = {
     label: 'Polymer Id',
+    category: ColorTheme.Category.Basic,
     factory: PolymerIdColorTheme,
     getParams: getPolymerIdColorThemeParams,
     defaultValues: PD.getDefaultValues(PolymerIdColorThemeParams),
diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts
index 02bfa5b44266b20e431980f35b4d78545a5b5dbd..ef37ce818edc5571e0e9a25e7a1e8a891065279a 100644
--- a/src/mol-theme/color/polymer-index.ts
+++ b/src/mol-theme/color/polymer-index.ts
@@ -88,6 +88,7 @@ export function PolymerIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<P
 
 export const PolymerIndexColorThemeProvider: ColorTheme.Provider<PolymerIndexColorThemeParams> = {
     label: 'Polymer Index',
+    category: ColorTheme.Category.Advanced,
     factory: PolymerIndexColorTheme,
     getParams: getPolymerIndexColorThemeParams,
     defaultValues: PD.getDefaultValues(PolymerIndexColorThemeParams),
diff --git a/src/mol-theme/color/residue-name.ts b/src/mol-theme/color/residue-name.ts
index 175518740b31ad358793378ecab7c42799e4bc7b..72259d10f211d7b9116dc81b684ea34d27f8b713 100644
--- a/src/mol-theme/color/residue-name.ts
+++ b/src/mol-theme/color/residue-name.ts
@@ -130,6 +130,7 @@ export function ResidueNameColorTheme(ctx: ThemeDataContext, props: PD.Values<Re
 
 export const ResidueNameColorThemeProvider: ColorTheme.Provider<ResidueNameColorThemeParams> = {
     label: 'Residue Name',
+    category: ColorTheme.Category.Basic,
     factory: ResidueNameColorTheme,
     getParams: getResidueNameColorThemeParams,
     defaultValues: PD.getDefaultValues(ResidueNameColorThemeParams),
diff --git a/src/mol-theme/color/secondary-structure.ts b/src/mol-theme/color/secondary-structure.ts
index 9eef3bb1c704290a78bd9cb9112104af87a1125a..6afa2dc1b3b038bc6b32472432ea68fe9542ddf2 100644
--- a/src/mol-theme/color/secondary-structure.ts
+++ b/src/mol-theme/color/secondary-structure.ts
@@ -113,6 +113,7 @@ export function SecondaryStructureColorTheme(ctx: ThemeDataContext, props: PD.Va
 
 export const SecondaryStructureColorThemeProvider: ColorTheme.Provider<SecondaryStructureColorThemeParams> = {
     label: 'Secondary Structure',
+    category: ColorTheme.Category.Basic,
     factory: SecondaryStructureColorTheme,
     getParams: getSecondaryStructureColorThemeParams,
     defaultValues: PD.getDefaultValues(SecondaryStructureColorThemeParams),
diff --git a/src/mol-theme/color/sequence-id.ts b/src/mol-theme/color/sequence-id.ts
index 66457c0b576b579c692cae88ab9ccdc728aec05b..90f5038eca3641248a6562dce33939ac2a15aa0f 100644
--- a/src/mol-theme/color/sequence-id.ts
+++ b/src/mol-theme/color/sequence-id.ts
@@ -101,6 +101,7 @@ export function SequenceIdColorTheme(ctx: ThemeDataContext, props: PD.Values<Seq
 
 export const SequenceIdColorThemeProvider: ColorTheme.Provider<SequenceIdColorThemeParams> = {
     label: 'Sequence Id',
+    category: ColorTheme.Category.Basic,
     factory: SequenceIdColorTheme,
     getParams: getSequenceIdColorThemeParams,
     defaultValues: PD.getDefaultValues(SequenceIdColorThemeParams),
diff --git a/src/mol-theme/color/shape-group.ts b/src/mol-theme/color/shape-group.ts
index 1c3166fafdadbefae4f83b7b9cd12d708a46ddf3..d5b5ba87ee925e22856186514992d09ed34c9a7a 100644
--- a/src/mol-theme/color/shape-group.ts
+++ b/src/mol-theme/color/shape-group.ts
@@ -37,6 +37,7 @@ export function ShapeGroupColorTheme(ctx: ThemeDataContext, props: PD.Values<Sha
 
 export const ShapeGroupColorThemeProvider: ColorTheme.Provider<ShapeGroupColorThemeParams> = {
     label: 'Shape Group',
+    category: ColorTheme.Category.Advanced,
     factory: ShapeGroupColorTheme,
     getParams: getShapeGroupColorThemeParams,
     defaultValues: PD.getDefaultValues(ShapeGroupColorThemeParams),
diff --git a/src/mol-theme/color/uncertainty.ts b/src/mol-theme/color/uncertainty.ts
index d7511cb0533f6554bf50d9d92797ef1b0df223f5..7e87f0127e065efc0c65a7b3615967a79590f257 100644
--- a/src/mol-theme/color/uncertainty.ts
+++ b/src/mol-theme/color/uncertainty.ts
@@ -64,6 +64,7 @@ export function UncertaintyColorTheme(ctx: ThemeDataContext, props: PD.Values<Un
 
 export const UncertaintyColorThemeProvider: ColorTheme.Provider<UncertaintyColorThemeParams> = {
     label: 'Uncertainty/Disorder',
+    category: ColorTheme.Category.Advanced,
     factory: UncertaintyColorTheme,
     getParams: getUncertaintyColorThemeParams,
     defaultValues: PD.getDefaultValues(UncertaintyColorThemeParams),
diff --git a/src/mol-theme/color/uniform.ts b/src/mol-theme/color/uniform.ts
index 6bc0e8bdc70be6be9be3c061eb5c7936ab8d270d..e018b914d22ad253040c4894c09549670239e49e 100644
--- a/src/mol-theme/color/uniform.ts
+++ b/src/mol-theme/color/uniform.ts
@@ -37,6 +37,7 @@ export function UniformColorTheme(ctx: ThemeDataContext, props: PD.Values<Unifor
 
 export const UniformColorThemeProvider: ColorTheme.Provider<UniformColorThemeParams> = {
     label: 'Uniform',
+    category: ColorTheme.Category.Basic,
     factory: UniformColorTheme,
     getParams: getUniformColorThemeParams,
     defaultValues: PD.getDefaultValues(UniformColorThemeParams),
diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts
index bb6bb9c5bbc40dead1edf85da2ec110fb3011d13..bcd5e7314f9bf66aaaa28bd0403cd8f991e8c1dd 100644
--- a/src/mol-theme/color/unit-index.ts
+++ b/src/mol-theme/color/unit-index.ts
@@ -73,6 +73,7 @@ export function UnitIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<Unit
 
 export const UnitIndexColorThemeProvider: ColorTheme.Provider<UnitIndexColorThemeParams> = {
     label: 'Unit Index',
+    category: ColorTheme.Category.Advanced,
     factory: UnitIndexColorTheme,
     getParams: getUnitIndexColorThemeParams,
     defaultValues: PD.getDefaultValues(UnitIndexColorThemeParams),
diff --git a/src/mol-theme/size.ts b/src/mol-theme/size.ts
index 71c79b8d22d463ca3b3efa0779c41e5b9d77f227..2283474f79175887aa15b56780d5c71b6c01fffa 100644
--- a/src/mol-theme/size.ts
+++ b/src/mol-theme/size.ts
@@ -32,7 +32,7 @@ namespace SizeTheme {
     }
 
     export interface Provider<P extends PD.Params> extends ThemeProvider<SizeTheme<P>, P> { }
-    export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true }
+    export const EmptyProvider: Provider<{}> = { label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true }
 
     export type Registry = ThemeRegistry<SizeTheme<any>>
     export function createRegistry() {
diff --git a/src/mol-theme/size/physical.ts b/src/mol-theme/size/physical.ts
index 4456ad2091c98280488f9c1dd34f1e42784efc6a..8622967d19f8e774b71b9446d580530e5f9ce01d 100644
--- a/src/mol-theme/size/physical.ts
+++ b/src/mol-theme/size/physical.ts
@@ -58,6 +58,7 @@ export function PhysicalSizeTheme(ctx: ThemeDataContext, props: PD.Values<Physic
 
 export const PhysicalSizeThemeProvider: SizeTheme.Provider<PhysicalSizeThemeParams> = {
     label: 'Physical',
+    category: '',
     factory: PhysicalSizeTheme,
     getParams: getPhysicalSizeThemeParams,
     defaultValues: PD.getDefaultValues(PhysicalSizeThemeParams),
diff --git a/src/mol-theme/size/shape-group.ts b/src/mol-theme/size/shape-group.ts
index 2e2f867d55c5910a8ca844a4cb42215c77607412..b7eaa993fe5d1afcf5af100b6c4fb2ce215f2c26 100644
--- a/src/mol-theme/size/shape-group.ts
+++ b/src/mol-theme/size/shape-group.ts
@@ -36,6 +36,7 @@ export function ShapeGroupSizeTheme(ctx: ThemeDataContext, props: PD.Values<Shap
 
 export const ShapeGroupSizeThemeProvider: SizeTheme.Provider<ShapeGroupSizeThemeParams> = {
     label: 'Shape Group',
+    category: '',    
     factory: ShapeGroupSizeTheme,
     getParams: getShapeGroupSizeThemeParams,
     defaultValues: PD.getDefaultValues(ShapeGroupSizeThemeParams),
diff --git a/src/mol-theme/size/uncertainty.ts b/src/mol-theme/size/uncertainty.ts
index 5f9da065b4b8331ac620db16e6e4b806446ac176..bbeec077745086a04cdb72d76cd9ef911cd0595f 100644
--- a/src/mol-theme/size/uncertainty.ts
+++ b/src/mol-theme/size/uncertainty.ts
@@ -54,6 +54,7 @@ export function UncertaintySizeTheme(ctx: ThemeDataContext, props: PD.Values<Unc
 
 export const UncertaintySizeThemeProvider: SizeTheme.Provider<UncertaintySizeThemeParams> = {
     label: 'Uncertainty/Disorder',
+    category: '',
     factory: UncertaintySizeTheme,
     getParams: getUncertaintySizeThemeParams,
     defaultValues: PD.getDefaultValues(UncertaintySizeThemeParams),
diff --git a/src/mol-theme/size/uniform.ts b/src/mol-theme/size/uniform.ts
index 4d82bef1048e7b01b74c711df38221f3fd3aafdd..32b2718744f145c5ec3540eefb8a7326f46f7d0a 100644
--- a/src/mol-theme/size/uniform.ts
+++ b/src/mol-theme/size/uniform.ts
@@ -32,6 +32,7 @@ export function UniformSizeTheme(ctx: ThemeDataContext, props: PD.Values<Uniform
 
 export const UniformSizeThemeProvider: SizeTheme.Provider<UniformSizeThemeParams> = {
     label: 'Uniform',
+    category: '',
     factory: UniformSizeTheme,
     getParams: getUniformSizeThemeParams,
     defaultValues: PD.getDefaultValues(UniformSizeThemeParams),
diff --git a/src/mol-theme/theme.ts b/src/mol-theme/theme.ts
index ce5350a5a696a2b2315415576755f1556667dea2..d654af18e25a59ea33a7fb09b4541c0d9abe9b09 100644
--- a/src/mol-theme/theme.ts
+++ b/src/mol-theme/theme.ts
@@ -60,7 +60,8 @@ namespace Theme {
 //
 
 export interface ThemeProvider<T extends ColorTheme<P> | SizeTheme<P>, P extends PD.Params> {
-    readonly label: string
+    readonly label: string    
+    readonly category: string
     readonly factory: (ctx: ThemeDataContext, props: PD.Values<P>) => T
     readonly getParams: (ctx: ThemeDataContext) => P
     readonly defaultValues: PD.Values<P>
@@ -69,7 +70,7 @@ export interface ThemeProvider<T extends ColorTheme<P> | SizeTheme<P>, P extends
 }
 
 function getTypes(list: { name: string, provider: ThemeProvider<any, any> }[]) {
-    return list.map(e => [e.name, e.provider.label] as [string, string]);
+    return list.map(e => [e.name, e.provider.label, e.provider.category] as [string, string, string]);
 }
 
 export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> {
@@ -79,16 +80,26 @@ export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> {
 
     get default() { return this._list[0] }
     get list() { return this._list }
-    get types(): [string, string][] { return getTypes(this._list) }
+    get types(): [string, string, string][] { return getTypes(this._list) }
 
     constructor(builtInThemes: { [k: string]: ThemeProvider<T, any> }, private emptyProvider: ThemeProvider<T, any>) {
         Object.keys(builtInThemes).forEach(name => this.add(name, builtInThemes[name]))
     }
 
+    private sort() {
+        this._list.sort((a, b) => {
+            if (a.provider.category === b.provider.category) {
+                return a.provider.label < b.provider.label ? -1 : a.provider.label > b.provider.label ? 1 : 0;
+            }
+            return a.provider.category < b.provider.label ? -1 : 1;
+        });
+    }
+
     add<P extends PD.Params>(name: string, provider: ThemeProvider<T, P>) {
         this._list.push({ name, provider })
         this._map.set(name, provider)
         this._name.set(provider, name)
+        this.sort();
     }
 
     remove(name: string) {
diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts
index b2ccbedced6a35e78831242833476f2cad94c435..064528cf1dcaed4fa8b74f2933ab496587071fe8 100644
--- a/src/mol-util/param-definition.ts
+++ b/src/mol-util/param-definition.ts
@@ -65,9 +65,9 @@ export namespace ParamDefinition {
     export interface Select<T extends string | number> extends Base<T> {
         type: 'select'
         /** array of (value, label) tuples */
-        options: readonly (readonly [T, string])[]
+        options: readonly (readonly [T, string] | [T, string, string])[]
     }
-    export function Select<T extends string | number>(defaultValue: T, options: readonly (readonly [T, string])[], info?: Info): Select<T> {
+    export function Select<T extends string | number>(defaultValue: T, options: readonly (readonly [T, string] | [T, string, string])[], info?: Info): Select<T> {
         return setInfo<Select<T>>({ type: 'select', defaultValue: checkDefaultKey(defaultValue, options), options }, info)
     }
 
@@ -201,7 +201,7 @@ export namespace ParamDefinition {
         select: Select<string>,
         map(name: string): Any
     }
-    export function Mapped<T>(defaultKey: string, names: [string, string][], map: (name: string) => Any, info?: Info): Mapped<NamedParams<T>> {
+    export function Mapped<T>(defaultKey: string, names: ([string, string] | [string, string, string])[], map: (name: string) => Any, info?: Info): Mapped<NamedParams<T>> {
         const name = checkDefaultKey(defaultKey, names);
         return setInfo<Mapped<NamedParams<T>>>({
             type: 'mapped',
@@ -406,7 +406,7 @@ export namespace ParamDefinition {
         return ret;
     }
 
-    function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string])[]) {
+    function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string] | [T, string, string])[]) {
         for (const o of options) {
             if (o[0] === k) return k;
         }