# AppearanceControls

> The "Appearance" settings panel from `@digitalcrew/ui`: density, button finish, motion, background effect and intensity, the splash cursor, and a live preview of the result.

## Facts

- **Product**: Crew OS
- **Family**: Appearance
- **Global**: `window.DigitalCrew.AppearanceControls`
- **Source**: `digitalcrew-orchestrator: packages/ui/src/appearance-controls.tsx`
- **Import in the app**: `import { AppearanceControls } from "@/packages/ui/src/appearance-controls";`
- **Live preview**: /design/components/appearance-controls/preview.html
- **Page**: /design/components/appearance-controls

## Guidelines

**Use it for** the personal preferences page of Crew OS (and Max): the signed-in user's choices, per product, in this browser.

**What you provide**: wrap it in `AppearanceProvider` with `product` (`"crew-os"` or `"max"`) and `userId` (`null` when signed out: nothing is read or saved). `AppearanceControls` takes only `className`. `useAppearance()` gives other components `preferences`, `updatePreferences`, `ready` and `reducedMotion`; `SettingsSection` is the bordered layout it is built on.

**Anatomy**: a `crew-settings-section` card (1px `border`, 12px radius, `card` background, 24px padding and gaps; 16px when density is compact) with a "Reset appearance" outline button. Five native selects, at least 44px tall, in a two-column grid (one column below 640px), each with a 13px help line. The splash cursor is a switch row. The preview is at least 272px (17rem) tall and runs the chosen [`BackgroundEffect`](/design/components/background-effect.md) behind a sample title, input and primary button.

**Behaviour**: preferences are stored under `digitalcrew:appearance:v1:<product>:<userId>` as `{ version: 1, preferences }` and saved only after an explicit change; other tabs follow via the `storage` event. The provider sets `data-density`, `data-button-finish` and `data-motion` on a `display: contents` root so primitives restyle. Reduced motion (the choice or the OS setting) disables the splash cursor and stills the background. (The preview seeds "Neon flow" for a first visit.)

**Don't** save preferences server-side through this component, or render it without a user id.

## API

```ts
type SettingsSectionProps = Omit<React.ComponentProps<"section">, "title"> & {
    title: string;
    description?: string;
    actions?: React.ReactNode;
};
/** Shared settings layout; applications retain save actions and authorization. */
export declare function SettingsSection({ title, description, actions, children, className, ...props }: SettingsSectionProps): any;
export declare function AppearanceControls({ className }: {
    className?: string;
}): any;
```

## Example

```html
<div id="root" class="p-6"></div>
<script>
(function () {
  var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
  var userId = "user_julie_martin";
  // Demo only: start this viewer on the "Neon flow" background unless they already chose something here.
  try {
    var key = "digitalcrew:appearance:v1:crew-os:" + encodeURIComponent(userId);
    if (!window.localStorage.getItem(key)) window.localStorage.setItem(key, JSON.stringify({ version: 1, preferences: { background: "neon-flow", intensity: "medium" } }));
  } catch (e) {}
  function App() { return h(DC.AppearanceProvider, { product: "crew-os", userId: userId }, h(DC.AppearanceControls)); }
  ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>
```

## More in Appearance

- [BackgroundEffect](/design/components/background-effect.md): A decorative canvas that fills a positioned region with one of seven pointer-reactive background effects, drawn in the current `--primary` colour.
