# Semantic UI — Administrator & Architecture Guide

This guide is the technical reference for engineers, architects, and maintainers who integrate, build, customize, secure, or contribute to **Semantic UI**. Where the User Guide covers *how to use* the framework, this guide covers *how it is built* — the LESS theming pipeline, the JavaScript module architecture, the Gulp build system, the configuration surface, security considerations, and the contribution workflow. It is written against Semantic UI **2.5.0** (source commit `597843a`).

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [Architecture](#2-architecture)
3. [Requirements](#3-requirements)
4. [The Build System](#4-the-build-system)
5. [Configuration Reference](#5-configuration-reference)
6. [Customization Deep Dive (Theming)](#6-customization-deep-dive-theming)
7. [The JavaScript Module Architecture](#7-the-javascript-module-architecture)
8. [Security](#8-security)
9. [Testing Strategy](#9-testing-strategy)
10. [Operations & Performance](#10-operations--performance)
11. [Component Internals Reference](#11-component-internals-reference)
12. [Troubleshooting & Known Issues](#12-troubleshooting--known-issues)
13. [Improvements & Technical Debt](#13-improvements--technical-debt)
14. [Contributing](#14-contributing)
15. [Quick Reference](#15-quick-reference)

---

## 1. Executive Summary

Semantic UI is a **CSS-first front-end framework** whose value proposition is theming. It is built around three architectural pillars:

1. **A LESS source tree** organized by a five-category component taxonomy (Globals, Elements, Collections, Views, Modules). Roughly 50+ components are authored as LESS, exposing **~3000 CSS variables** for customization.
2. **A three-level theme-inheritance model** (default theme → packaged theme → site theme) wired together with LESS `@import (optional)` directives, selected per-component via a `theme.config` file. This is the framework's distinguishing design and the reason its README calls it "a UI framework designed for theming."
3. **A jQuery-based JavaScript layer** of 16 interactive **Modules** and 3 **Behaviors**, all following a uniform plugin pattern (initialize → invoke-behavior-by-string → settings object with callbacks and debug instrumentation).

The repository ships precompiled output in `dist/` (combined and per-component CSS/JS) plus a **Gulp 4 build system** that compiles a developer's themed LESS into a customized bundle. An **interactive installer** scaffolds project configuration on first `npm install`.

| Attribute | Value |
|---|---|
| Version | 2.5.0 (released Oct 6, 2022) |
| License | MIT |
| Source language | LESS (styles) + ES5 JavaScript / jQuery (modules) |
| Runtime dependency | jQuery `^3.5.1` (for Modules/Behaviors only) |
| Build system | Gulp 4 + LESS + autoprefixer + clean-css + uglify |
| Component count | 16 Elements + 6 Collections + 6 Views + 16 Modules + 3 Behaviors + 2 Globals |
| Packaged themes | 23 |
| Total source | ~526 files, ~320K source chars |

> [!NOTE]
> Semantic UI is the upstream "vanilla" framework. Several **official sibling distributions** are maintained as separate repositories: `semantic-ui-css` (precompiled), `semantic-ui-less` (LESS only), and framework integrations for React, Angular, Ember, and Meteor. Architectural decisions here (notably the jQuery dependency) explain why those wrappers exist.

---

## 2. Architecture

### 2.1 High-level structure

```text
                          ┌──────────────────────────────────────┐
                          │         src/  (authored source)       │
                          ├──────────────────────────────────────┤
   theme.config  ───────► │  definitions/   LESS + JS per         │
   (per-component theme   │    ├── globals/      component        │
    selection)            │    ├── elements/                      │
                          │    ├── collections/                   │
   site/  ──────────────► │    ├── views/                         │
   (your overrides)       │    ├── modules/   (LESS + .js)        │
                          │    └── behaviors/ (.js only)          │
   themes/  ────────────► │  themes/        23 packaged themes    │
   (default + packaged)   │    └── <theme>/<type>s/<comp>.variables
                          │                          + .overrides │
                          └───────────────┬──────────────────────┘
                                          │  gulp build
                       ┌──────────────────▼───────────────────┐
                       │   LESS compile → autoprefix →         │
                       │   concat → clean-css → uglify         │
                       └──────────────────┬───────────────────┘
                                          ▼
                       ┌──────────────────────────────────────┐
                       │   dist/                               │
                       │     semantic.css / .min.css           │
                       │     semantic.js  / .min.js            │
                       │     components/<comp>.css|js (+min)    │
                       │     themes/   (fonts + image assets)   │
                       └──────────────────────────────────────┘
```

### 2.2 The component taxonomy

The five categories are not cosmetic — they determine whether a component has JavaScript and where its files live.

| Category | Has LESS | Has JS | Semantics |
|---|---|---|---|
| **Globals** (`reset`, `site`) | Yes | `site` only | Page-wide reset + global site variables |
| **Elements** (16) | Yes | No | Atomic building blocks (button, icon, input…) |
| **Collections** (6) | Yes | No | Groups of elements (form, grid, menu, table…) |
| **Views** (6) | Yes | No | Content presentations (card, feed, comment…) |
| **Modules** (16) | Yes | **Yes** | Interactive widgets (dropdown, modal, popup…) |
| **Behaviors** (3) | No | **Yes** | JS-only helpers (api, form, visibility) |

This split is load-bearing for the build: CSS-only categories compile to stylesheet output only, while Modules emit both a `.css` and a `.js` in `dist/components/`, and Behaviors emit `.js` only.

### 2.3 The LESS import cascade

The heart of the theming architecture is `src/theme.less`, which every component imports. For a given component it resolves variables and overrides by importing up to four layers in priority order:

```less
/* Site (global) variables — default → packaged → component-theme → site */
@import "@{themesFolder}/default/globals/site.variables";
@import (optional) "@{themesFolder}/@{site}/globals/site.variables";
@import (optional) "@{themesFolder}/@{theme}/globals/site.variables";
@import (optional) "@{siteFolder}/globals/site.variables";

/* Component variables — default → packaged theme → site theme */
@import "@{themesFolder}/default/@{type}s/@{element}.variables";
@import (optional) "@{themesFolder}/@{theme}/@{type}s/@{element}.variables";
@import (optional) "@{siteFolder}/@{type}s/@{element}.variables";

/* Component overrides (custom rules) — packaged theme → site theme */
.loadUIOverrides() {
  @import (optional) "@{themesFolder}/@{theme}/@{type}s/@{element}.overrides";
  @import (optional) "@{siteFolder}/@{type}s/@{element}.overrides";
}
```

The `@theme` variable is resolved dynamically per component: `@theme: @@element;` reads the value of the per-component theme variable defined in `theme.config` (e.g. `@button: 'github'` makes `@theme` equal `'github'` while compiling the button). `@import (optional)` means a layer is silently skipped if that theme doesn't define the file — which is why a packaged theme only needs to ship the components it actually restyles.

> [!IMPORTANT]
> This cascade is the single most important architectural fact in the codebase. Variables flow `default → packaged → site` with **later winning**; `.overrides` files add raw CSS rules with access to all resolved variables. A maintainer reading or extending the theme system must understand `theme.less` before anything else.

### 2.4 The JavaScript module pattern

Every Module and Behavior is an IIFE that registers a jQuery plugin and follows an identical skeleton (illustrated with `dropdown`):

```javascript
(function ($, window, document) {
  $.fn.dropdown = function (parameters) {
    // for each matched element:
    //   - read merged settings (defaults ← $.fn.dropdown.settings ← call args ← data-* attrs)
    //   - build a `module` object with all methods
    //   - module.initialize() binds events, caches DOM
    //   - module.invoke(query) dispatches string method calls
    //   - instance stored via $.data(element, moduleNamespace)
  };
  $.fn.dropdown.settings = { /* defaults, callbacks, selectors, className, error, metadata */ };
})(jQuery, window, document);
```

Key shared sub-objects inside every `settings`:

| Sub-object | Role |
|---|---|
| (top-level keys) | Behavioral defaults (`on`, `transition`, `duration`, …) |
| `on*` callbacks | Lifecycle hooks the integrator overrides |
| `selector` | CSS selectors the module uses to find sub-parts |
| `className` | State class names the module toggles (`active`, `visible`, …) |
| `metadata` | `data-*` attribute names the module reads/writes |
| `error` | Human-readable error strings (logged on misuse) |
| `regExp` / `text` / `message` | Module-specific lookups and user-facing strings |

The `invoke` dispatcher is what makes `$('.ui.modal').modal('show')` work: the string `'show'` is resolved against the `module` object's methods. This pattern is uniform across all 19 JS files, so understanding one module's structure transfers to all of them.

---

## 3. Requirements

| Concern | Requirement | Notes |
|---|---|---|
| **Runtime (browser)** | jQuery 3.x (`^3.5.1`) | Required only for Modules + Behaviors. CSS components need nothing. |
| **Build (Node)** | Node.js 18+ | 2.5.0 updated scripts to build under Node 18. |
| **Build (Gulp)** | Gulp 4 | All tasks rewritten for Gulp 4 in 2.5.0 (was Gulp 3). |
| **Build (LESS)** | bundled via `gulp-less` | Source contains **no vendor prefixes**; autoprefixer runs in the build. |
| **Browser targets** | Last 2 FF/Chrome/Safari(Mac), IE 11+, Edge 12+, Android 4.4+, iOS Safari 7+ | Flexbox components (grid) unsupported on IE9. |

### Build-tool dependencies

The `package.json` declares a Gulp-centric toolchain (also mirrored in `peerDependencies`):

| Dependency | Role |
|---|---|
| `gulp`, `gulp-less` | Task runner + LESS compilation |
| `gulp-autoprefixer` | Adds vendor prefixes (source has none) |
| `gulp-clean-css` | CSS minification |
| `gulp-uglify` | JS minification |
| `gulp-concat`, `gulp-concat-css`, `gulp-rename`, `gulp-flatten`, `gulp-copy` | File assembly |
| `gulp-rtlcss` | RTL stylesheet generation |
| `gulp-header` | License banner injection |
| `yamljs` | Reads YAML build config |
| `jquery ^3.5.1` | Runtime dependency vendored for tests/dist |

> [!NOTE]
> Skipping a dependency-documentation lookup for these is intentional: they are well-known build tools, and the framework's own source is the authoritative description of *how it uses them*. The interesting integration is the `theme.less` cascade and the Gulp task graph, not the individual plugins' APIs.

---

## 4. The Build System

### 4.1 Gulp task graph

`gulpfile.js` wires the tasks defined under `tasks/`:

| Task | Source | Purpose |
|---|---|---|
| `build` | `tasks/build.js` | Full build: CSS + JS + assets |
| `build-css` | `tasks/build/css.js` | LESS → autoprefix → concat → minify → `dist/` |
| `build-javascript` | `tasks/build/javascript.js` | Concatenate + uglify module JS → `dist/` |
| `build-assets` | `tasks/build/assets.js` | Copy fonts + images to `dist/themes/` |
| `watch` | `tasks/watch.js` | Incremental rebuild on file change |
| `clean` | `tasks/clean.js` | Remove `dist/` |
| `version` | `tasks/version.js` | Print/stamp version |
| `install` | `tasks/install.js` | Interactive installer (see §4.3) |
| `check-install` | `tasks/check-install.js` | **Default task** — verifies setup, runs installer if unconfigured |
| `build-rtl` / `watch-rtl` | `tasks/rtl/` | RTL builds (enabled when `semantic.json.rtl` is true) |
| `serve-docs` / `build-docs` | `tasks/docs/` | Documentation site integration |

The `default` Gulp task is `check-install`, so a bare `gulp` on an unconfigured project triggers the installer rather than failing.

### 4.2 Build output

A full build produces, in `dist/`:

- `semantic.css` / `semantic.min.css` — every component, combined
- `semantic.js` / `semantic.min.js` — every module, combined
- `components/<name>.css|js` (+ `.min`) — per-component files for selective inclusion
- `themes/` — icon fonts and image assets referenced by the CSS

> [!TIP]
> The per-component output in `dist/components/` is the supported mechanism for shrinking payload: an integrator includes only the components their app uses instead of the full bundle. This is the framework's answer to tree-shaking, which LESS cannot do automatically.

### 4.3 The interactive installer

`tasks/install.js` runs a prompt-driven wizard (via the `prompt-sui` library). It:

1. Detects an existing `semantic.json` and offers to **extend** or **skip**.
2. Confirms the project root (or accepts a custom absolute path).
3. Asks where to place Semantic UI inside the project.
4. Offers three setup modes:
   - **Automatic** — default locations, all components.
   - **Express** — choose components + output folder.
   - **Custom** — customize all `src`/`dist` paths.
5. Presents a component **checkbox list** for selective installs.
6. Writes `semantic.json`, `theme.config`, and the `site/` folder from their `.example`/`_site` templates.

> [!NOTE]
> The installer is what renames `theme.config.example → theme.config` and `_site/ → site/`. For manual installs (no installer), these renames must be done by hand, as documented in `src/README.md`.

---

## 5. Configuration Reference

There are **three** configuration artifacts. They control *what theme each component uses*, *where build files live*, and *the values inside each theme*.

### 5.1 `theme.config` — per-component theme selection

A LESS file (from `theme.config.example`) assigning a theme name to every component, grouped by category, plus folder paths:

```less
/* Global */    @site: 'default';  @reset: 'default';
/* Elements */  @button: 'default'; @input: 'default'; …
/* Modules */   @dropdown: 'default'; @modal: 'default'; …
/* Folders */
@themesFolder : 'themes';   /* path to packaged themes */
@siteFolder   : 'site';     /* path to YOUR overrides  */
@import (multiple) "theme.less";
```

To restyle a component, set its variable to any theme name present in `src/themes/` (e.g. `@button: 'material';`). All 50+ component variables plus `@themesFolder` and `@siteFolder` are configurable here.

### 5.2 `semantic.json` — build paths and flags

A JSON file (from `semantic.json.example`) read by the build tools:

| Key | Default | Purpose |
|---|---|---|
| `base` | `""` | Base path prepended to all paths |
| `paths.source.config` | `src/theme.config` | Where the theme config lives |
| `paths.source.definitions` | `src/definitions/` | Component LESS+JS |
| `paths.source.site` | `src/site/` | Site overrides |
| `paths.source.themes` | `src/themes/` | Packaged themes |
| `paths.output.packaged` | `dist/` | Combined bundle output |
| `paths.output.uncompressed` | `dist/components/` | Per-component, unminified |
| `paths.output.compressed` | `dist/components/` | Per-component, minified |
| `paths.output.themes` | `dist/themes/` | Asset output |
| `paths.clean` | `dist/` | Directory cleaned by `gulp clean` |
| `permission` | `false` | File permission (chmod) to apply to output |
| `autoInstall` | `false` | Re-run install automatically |
| `rtl` | `false` | Enable RTL build tasks (`true`, `false`, or `'both'`) |

### 5.3 Global LESS variables (`site.variables`)

The most-changed global variables live in `themes/default/globals/site.variables`. Override them in `site/globals/site.variables`:

| Variable | Default | Controls |
|---|---|---|
| `@emSize` | `14px` | **The** base size; everything scales from it |
| `@fontSize` | `14px` | Body text size |
| `@fontName` | `'Lato'` | Primary font family |
| `@headerFont` / `@pageFont` | Lato stack | Header / body font stacks |
| `@importGoogleFonts` | `true` | Whether to fetch the font from Google Fonts at runtime |
| `@googleFontRequest` | derived | The exact Google Fonts URL query |
| `@primaryColor` | `@blue` | Primary brand color |
| `@secondaryColor` | `@black` | Secondary brand color |
| `@bold` / `@normal` | `bold` / `normal` | Font weights |
| `@defaultBorderRadius` | `@absoluteBorderRadius` (4px) | Corner rounding baseline |
| `@h1`–`@h5` | rem ratios | Heading sizes |

Each component additionally has its own `<component>.variables` file (e.g. `elements/button.variables` exposes `@backgroundColor`, `@verticalPadding`, `@horizontalPadding`, `@borderRadius`, shadow variables, and more). With ~3000 variables across the framework, the per-component variable file *is* that component's configuration reference — inspect `themes/default/<type>s/<component>.variables` to see every knob.

### 5.4 JavaScript module settings

Each Module/Behavior exposes `$.fn.<module>.settings`. All share a common instrumentation core:

| Setting | Default | Purpose |
|---|---|---|
| `silent` | `false` | Suppress all console output |
| `debug` | `false` | Log internal events |
| `verbose` | `false` | Verbose internal logging |
| `performance` | `true` | Emit a performance trace |
| `name` | (module) | Name shown in logs |
| `namespace` | (module) | Event/`data` namespace |

Module-specific keys, callbacks, selectors, className maps, metadata maps, and error strings are defined alongside these. The complete callback inventory per module is in [§11](#11-component-internals-reference).

---

## 6. Customization Deep Dive (Theming)

There are three layers of customization, in increasing specificity. A maintainer should steer integrators toward the highest-numbered layer that solves their problem.

### Layer 1 — Pick a packaged theme (`theme.config`)

Cheapest customization: set a component to one of the 23 shipped themes.

```less
@button : 'github';
@menu   : 'material';
```

### Layer 2 — Override variables (`site/**/<component>.variables`)

Change values without writing CSS. The site theme is always the last `@import` in the cascade, so it wins.

```less
/* site/globals/site.variables */
@primaryColor : @teal;
@fontName     : 'Inter';
@emSize       : 16px;

/* site/elements/button.variables */
@borderRadius : 0;
```

### Layer 3 — Custom CSS (`site/**/<component>.overrides`)

For rules no variable exposes. `.overrides` files are imported *after* variables and have access to all of them.

```less
/* site/elements/button.overrides */
.ui.button.brand {
  background: linear-gradient(@primaryColor, darken(@primaryColor, 10%));
}
```

> [!CAUTION]
> Do **not** customize by writing `!important` overrides against compiled `semantic.css`. That fights the cascade, breaks on upgrade, and discards the entire theming system. The supported path is variables → overrides → rebuild.

### Color system

Named colors (`@blue`, `@red`, `@green`, `@teal`, …) and `@primaryColor`/`@secondaryColor` are defined once and consumed everywhere. Overriding `@primaryColor` re-skins primary buttons, active menu items, focused inputs, progress bars, and more in one change — the framework's "shared vocabulary" applied to color.

---

## 7. The JavaScript Module Architecture

### 7.1 Settings resolution order

When `$('.ui.x').x(opts)` runs, settings are merged from (lowest to highest priority):

1. `$.fn.x.settings` (framework defaults)
2. A global override of `$.fn.x.settings` (set once at app start)
3. The `opts` object passed at the call site
4. `data-*` attributes on the element (per the module's `metadata`/attribute parsing)

### 7.2 Instance lifecycle

- **initialize** — caches DOM (`module.refresh`), binds namespaced events, optionally fires init callbacks (`fireOnInit`).
- **invoke** — the string-dispatch entry point; `x('method', args)` resolves `method` against the instance.
- **setting** — read/write any setting at runtime (`x('setting', 'debug', true)`).
- **destroy** — unbinds all namespaced events and clears `$.data`, leaving the DOM intact.

Because events are bound under a per-instance `namespace`, multiple instances and clean teardown are race-free — `destroy` removes exactly that instance's handlers.

### 7.3 Inter-module dependencies

| Module | Depends on |
|---|---|
| `dropdown`, `modal`, `dimmer`, `popup`, `sidebar`, etc. | `transition` (for show/hide animations) — emits the `noTransition` error if absent |
| `modal` | `dimmer` (creates the backdrop) |
| `dropdown` (remote), `search`, `tab` (remote) | `api` behavior (AJAX) |

> [!IMPORTANT]
> When building a custom per-component JS bundle, you must include the **transitive** dependencies. A `dropdown.js` without `transition.js` throws `This module requires ui transitions` at runtime. The safest minimal set for any animated module is `{ component, transition }`, plus `{ dimmer }` for modal and `{ api }` for remote data.

---

## 8. Security

Semantic UI is primarily CSS, but its JavaScript layer renders HTML and makes network requests, which creates a real (if narrow) security surface. Treat the items below as a checklist for any app embedding user-generated content.

### 8.1 HTML rendering / XSS

Several modules render content that *can* be HTML:

- **Dropdown** has `preserveHTML: true` by **default** — selected values, labels, and menu text are inserted as HTML, not escaped.
- **Popup** content (`data-content` / `content` / `html`) is rendered into the popup.
- **Search** renders result templates.

> [!CAUTION]
> If any of these render **user-supplied or server-reflected** strings, set `preserveHTML: false` (dropdown, popup, search) so values are escaped, or sanitize the input server-side before it reaches the DOM. The framework does **not** ship an HTML sanitizer of its own; escaping is the integrator's responsibility. This is the most important security control for Semantic UI apps.

### 8.2 The `api` behavior

The `api` behavior builds request URLs from templates with `{name}` placeholders filled from `urlData` and element `data-*` attributes. Risks and mitigations:

- **URL/template injection** — never place untrusted values into `url` templates without encoding; prefer server-side allowlists of endpoints (the `api` map) over client-built URLs.
- **CSRF** — `api` does not add CSRF tokens automatically; configure `beforeXHR`/headers to attach them.
- **Response handling** — `onSuccess` receives the parsed response; do not `.html()` it unescaped.

### 8.3 Network/privacy: Google Fonts

By default (`@importGoogleFonts: true`), compiled CSS contains `@import url(https://fonts.googleapis.com/...)`. This causes every visitor's browser to contact Google. For privacy regimes (GDPR), strict CSP, or offline deployments:

- Set `@importGoogleFonts: false` and **self-host** the font.
- Or pin a CSP `font-src`/`style-src` that permits the Google domains intentionally.

(See also GitHub #7146, where the Google requests surfaced as runtime errors.)

### 8.4 Dependency posture

- The runtime dependency is **jQuery `^3.5.1`**. Track jQuery security advisories and pin a patched 3.x in your own app; the framework's floor is 3.5.1.
- An open security report exists upstream (GitHub **#7154**, "Open vulnerability flagged by security team"). Maintainers and adopters should monitor it. Consistent with responsible disclosure, specifics are not reproduced here; review the upstream issue and apply any published guidance.

> [!WARNING]
> Because development cadence has slowed (see §13), do not assume timely upstream security patches. For long-lived deployments, budget for self-maintaining the dependency tree or evaluate an actively maintained community fork.

---

## 9. Testing Strategy

### 9.1 Framework

Tests run under **Karma + Jasmine** (`karma.conf.js`). The harness loads jQuery, the compiled CSS (from `docs/build`), all module source from `src/definitions/**/*.js`, shared helpers from `test/helpers/`, HTML fixtures from `test/fixtures/`, and the specs.

### 9.2 Coverage

Specs exist for the interactive modules where behavior is most testable:

```text
test/modules/
  accordion.spec.js   checkbox.spec.js   dropdown.spec.js
  modal.spec.js       popup.spec.js      search.spec.js
  shape.spec.js       sidebar.spec.js    tab.spec.js
  module.spec.js      (shared module-contract tests)
```

> [!NOTE]
> Coverage is concentrated on **Modules** (the JS surface). Pure-CSS Elements/Collections/Views are validated visually via the `examples/` HTML pages rather than by unit tests — a reasonable strategy for a CSS framework, but it means stylesheet regressions are caught by eye, not by CI assertion. There is a `test/meteor/` suite for the Meteor integration and a `test/coverage/` output directory.

### 9.3 Visual/manual testing

The `examples/` directory (`grid.html`, `responsive.html`, `sticky.html`, `theming.html`, `login.html`, etc.) doubles as a manual test surface. The `src/README.md` recommends running `gulp watch`, editing theme files, and refreshing an example page to inspect theme changes.

---

## 10. Operations & Performance

### 10.1 Payload management

| Lever | Effect |
|---|---|
| Use `dist/components/*` selectively | Ship only components in use — the primary size lever |
| Minified bundles (`*.min.css/js`) | Production default |
| Drop unused themes | Don't ship `dist/themes/<unused>` assets |
| Self-host / subset the icon font | The icon font is a notable fixed cost |
| Disable Google Fonts import | Removes a runtime network round-trip |

> [!TIP]
> The full `semantic.min.css` contains all ~50 components plus the icon font. Most applications use a fraction; the per-component build is how you avoid shipping the rest. There is no automatic dead-CSS elimination in the LESS pipeline.

### 10.2 Build performance

- `gulp watch` does incremental compilation — only the touched component and its dependents rebuild.
- A full `gulp build` recompiles every component's four-layer LESS cascade; on large custom theme sets this is the slow path. Run it for releases, not on every edit.

### 10.3 Caching & CDN

`dist/` output is fully static. Serve with long-lived cache headers and fingerprinted filenames. The CDN distributions (cdnjs / jsDelivr) are appropriate for the default theme.

---

## 11. Component Internals Reference

### 11.1 Module callback inventory

| Module | Callbacks |
|---|---|
| `accordion` | `onOpen`, `onOpening`, `onClose`, `onClosing`, `onChange`, `onChanging` |
| `checkbox` | `onChange`, `onChecked`, `onUnchecked`, `onIndeterminate`, `onDeterminate`, `onEnable`, `onEnabled`, `onDisable`, `onDisabled` |
| `dimmer` | `onShow`, `onHide`, `onChange`, `onStart`, `onComplete` |
| `dropdown` | `onChange`, `onAdd`, `onRemove`, `onLabelSelect`, `onLabelCreate`, `onLabelRemove`, `onNoResults`, `onShow`, `onHide` |
| `embed` | `onCreate`, `onDisplay`, `onPlaceholderDisplay`, `onEmbed`, `onPlay`, `onPause`, `onStop`, `onReset` |
| `modal` | `onShow`, `onVisible`, `onHide`, `onHidden`, `onApprove`, `onDeny`, `onStart`, `onComplete` |
| `nag` | (none — persistence via cookie/localStorage) |
| `popup` | `onCreate`, `onShow`, `onVisible`, `onHide`, `onHidden`, `onRemove`, `onUnplaceable` |
| `progress` | `onChange`, `onSuccess`, `onWarning`, `onError`, `onActive`, `onNumeric`, `onLabelUpdate` |
| `rating` | `onRate` |
| `search` | `onSelect`, `onResults`, `onResultsAdd`, `onSearchQuery`, `onResultsOpen`, `onResultsClose`, `onSuccess`, `onError`, `onFailure`, `onAbort`, `onComplete`, `onText`, `onURL` |
| `shape` | `onChange` |
| `sidebar` | `onShow`, `onVisible`, `onHide`, `onHidden`, `onChange` |
| `sticky` | `onStick`, `onUnstick`, `onTop`, `onBottom`, `onScroll`, `onReposition` |
| `tab` | `onLoad`, `onFirstLoad`, `onRequest`, `onSuccess`, `onVisible` |
| `transition` | `onStart`, `onShow`, `onHide`, `onComplete` |

### 11.2 Behavior callback inventory

| Behavior | Callbacks |
|---|---|
| `api` | `onRequest`, `onResponse`, `onSuccess`, `onComplete`, `onFailure`, `onError`, `onAbort` |
| `form` | `onValid`, `onInvalid`, `onSuccess`, `onFailure` |
| `visibility` | `onOnScreen`, `onOffScreen`, `onTopVisible`/`Reverse`, `onBottomVisible`/`Reverse`, `onPassing`/`Reverse`, `onPassed`, `onTopPassed`/`Reverse`, `onBottomPassed`/`Reverse`, `onFixed`, `onUnfixed`, `onLoad`, `onAllLoaded`, `onRefresh`, `onUpdate` |

### 11.3 Source layout

```text
src/
  semantic.less              # imports every component (build-tool-free path)
  theme.less                 # the import cascade (default→packaged→site)
  theme.config(.example)     # per-component theme selection
  definitions/
    globals/{reset,site}.{less,js}
    elements/<16>.less
    collections/<6>.less
    views/<6>.less
    modules/<16>.{less,js}
    behaviors/{api,form,visibility}.js
  themes/<23 themes>/<type>s/<component>.{variables,overrides}
  _site/                     # template for the site theme (rename to site/)
tasks/                       # Gulp build, install, rtl, docs, admin
dist/                        # precompiled output (committed)
examples/                    # manual/visual test pages
test/                        # Karma+Jasmine specs, fixtures, helpers
```

---

## 12. Troubleshooting & Known Issues

### Operational issues

| Symptom | Cause | Resolution |
|---|---|---|
| `$(...).modal is not a function` | jQuery missing or loaded after Semantic | Load jQuery first; include the module's JS |
| Icons render as boxes | Icon font not served at expected path | Ship `dist/themes/` assets; configure font loader/`@fontPath` |
| `Module parse failed: Unexpected character '@'` (#6771) | Bundler importing CSS with no CSS loader | Add `css-loader`/`style-loader` |
| `This module requires ui transitions` | Animated module without `transition` | Include `transition.js` |
| `googleProtocol`/`googleFonts` errors (#7146) | Google Fonts import failing/blocked | `@importGoogleFonts: false` + self-host |
| `semantic-ui-css` fails in CRA (#7073) | Missing CSS/font loaders | Use Semantic UI React, or configure loaders |
| Install fails (#7131, #7115) | Old Node/Gulp 3 | Node 18 + Gulp 4, or use `semantic-ui-css` |

### Confirmed upstream bugs (from the issue tracker)

| Issue | Component | Summary |
|---|---|---|
| #5341 | Modal | Not working in some mobile browsers |
| #7153 | Modal | Page won't scroll after closing modal |
| #3236 | Sidebar | Doesn't toggle correctly in RTL build |
| #5670 | Input | Missing right border with `action` + `error`/`focus` |
| #7128 | Segment | Rendering bug |
| #5758 | Dropdown | Items not clickable on some iPhones |
| #7125 | Dropdown | Screen-reader (NVDA/JAWS) gaps in multiple-search-selection |
| #7154 | Security | Open vulnerability flagged (see §8.4) |

> [!NOTE]
> The framework's bug board uses a `[Component]` title convention and a **`Confirmed Bug`** label. Browsing the `Confirmed Bug` tag is the maintainers' recommended way to track known issues — useful when triaging whether a report is new.

---

## 13. Improvements & Technical Debt

These are observations from the source and issue tracker, framed as the maintenance backlog an adopter should weigh.

- **Maintenance cadence.** The last release (2.5.0) is from October 2022 and primarily modernized the build for Node 18 / Gulp 4. The project's future has been discussed openly (issue **#7108**). Adopters of a new long-lived project should evaluate activity and actively maintained community forks before committing.
- **jQuery dependency.** The interactive layer is tied to jQuery, which is increasingly out of step with modern component frameworks. This is the structural reason the official React/Angular/Vue ecosystems use *separate wrapper repos*. A web-components or framework-agnostic rewrite would be a major architectural shift.
- **ES5 JavaScript.** Modules are pre-ES6 (`var`, function expressions, IIFE). Modernizing to ES modules would enable real tree-shaking, which the LESS-only build cannot provide today.
- **No automatic CSS dead-code elimination.** Payload control is manual (per-component imports). A PurgeCSS-style step is left to integrators.
- **HTML escaping defaults.** `preserveHTML: true` on dropdown is a foot-gun for user-content apps; a safer default (or a built-in sanitizer) would reduce XSS risk (§8.1).
- **Google Fonts on by default.** The runtime Google dependency is a privacy/CSP liability that many teams must remember to disable (§8.3).
- **Test coverage is module-only.** CSS components rely on visual inspection; there are no stylesheet regression assertions in CI.
- **RTL edge cases.** Some components (e.g. sidebar, #3236) have known RTL defects; the RTL build is a generated transform, not hand-verified per component.

---

## 14. Contributing

The contribution workflow is defined in `CONTRIBUTING.md`:

1. **Usage questions** go to Gitter / forums / StackOverflow — **not** GitHub Issues.
2. **Bug reports** require a reproducible test case, ideally forked from the project's JSFiddle boilerplate. Bugs confirmed by a maintainer receive the **`Confirmed Bug`** label.
3. **Issue titles** follow the `[Component] Sub-type Should Do Correct Behavior` convention in title case; enhancements use `[Component] Add new feature`.
4. **Pull requests** target the **`next`** branch (not `master`/`main`).
5. **Framework-integration bugs** (Ember/Meteor/Angular/React) should be filed against those projects' boards, not the core repo.

### Build/dev loop for contributors

```bash
git clone https://github.com/Semantic-Org/Semantic-UI.git
cd Semantic-UI
npm install          # runs the installer; choose Automatic
gulp watch           # rebuild on change
# edit src/definitions/** or src/themes/**, refresh examples/*.html
```

Admin/release tasks live under `tasks/admin/` and `tasks/collections/admin.js` and are enabled only when `config.admin` is set — these handle distribution repos (the `semantic-ui-css`, `-less`, component repos) and are not needed for normal contributions.

---

## 15. Quick Reference

### Gulp commands

| Command | Purpose |
|---|---|
| `gulp install` | Interactive setup wizard |
| `gulp build` | Full CSS + JS + assets build |
| `gulp build-css` / `build-javascript` / `build-assets` | Partial builds |
| `gulp watch` | Rebuild on change |
| `gulp clean` | Delete `dist/` |
| `gulp build-rtl` / `watch-rtl` | RTL builds (needs `rtl: true`) |
| `gulp version` | Version info |

### Configuration files

| File | From template | Purpose |
|---|---|---|
| `theme.config` | `theme.config.example` | Per-component theme selection |
| `semantic.json` | `semantic.json.example` | Build paths + `rtl`/`autoInstall`/`permission` |
| `site/` | `_site/` | Your variable + override files |

### Customization layers (least → most specific)

1. `theme.config` — pick a packaged theme per component
2. `site/**/*.variables` — override variable values
3. `site/**/*.overrides` — add custom CSS rules

### JS API cheat sheet

```javascript
$('.ui.x').x();                       // initialize
$('.ui.x').x({ setting: value });     // initialize with settings
$('.ui.x').x('behavior', arg);        // invoke a behavior
$('.ui.x').x('setting', 'k', v);      // set a setting at runtime
$('.ui.x').x('destroy');              // teardown
```

### Component categories

| Category | Count | JS? |
|---|---|---|
| Globals | 2 | site only |
| Elements | 16 | No |
| Collections | 6 | No |
| Views | 6 | No |
| Modules | 16 | Yes |
| Behaviors | 3 | Yes (JS-only) |

---

_Generated June 2026 from Semantic-Org/Semantic-UI at 597843a. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
