# Company access

A React block (a whole screen) in [Beamline](https://beamline.io/)'s [Construction](https://beamline.io/components/apps/construction) app. Live demo: https://beamline.io/components/company-access

A project's companies as one board: No company first (office access waits for a company, and says so), then each company with its code and its people, the lead company marked with a crown and the word Lead. Each person has two access pickers that never mix: Field for the site and Office for the documents. Move people by hand (drag a card, with the others chosen, onto a company) or with Move to…: the cards travel at once, and the app answers per person, so a refused card travels back with its reason. Add or edit a company (a name and a code of up to five capital letters, unique on the project) and see which document numbers a code change renames before saving; choose the lead company after comparing what the lead and the other companies may route.

## Use it for

- Who belongs to which company on a project, with site and office access as separate roles: builders, consultancies, multi-company programmes.
- Moving people between organisations in bulk where each move can be refused on its own.

## Not for

- One role per person in a single organisation ([team-members](https://beamline.io/components/team-members), [roles-permissions](https://beamline.io/components/roles-permissions)).
- Tasks on a board ([project-board](https://beamline.io/components/project-board)).

## Anatomy

- head: title, project, Add company; with people chosen: how many, Move to… (every company and No company), Clear
- board: No company first with why office access waits, then one column per company with its name, code, Lead (crown and word) for the lead, how many people and its menu (Edit company, Make lead company or Remove as lead)
- person: name (the choose checkbox's label; the box shows on hover, focus, when chosen and while anyone is chosen; "you" for the signed-in person), email or Invitation pending, the access line (Field level · Office level, No access in the second ink) which, pressed or focused, opens Field (No access, Member, Manager) and Office (No access, Contributor, Manager) as two labelled pickers in place, one card at a time (a chosen card shows its pickers too); Office held at No access in No company; a note with the reason when a move or a role change was refused
- company form: name, code (two to five capital letters, unique on the project), what a code change renames (count and an example) before save, a refusal kept with the draft
- lead change: what the lead company and the other companies may route, side by side, the current lead named; the mark moves only when the app confirms

## States

- at rest: people, each with one access line; no pickers
- unassigned people (No company, office access held back and said)
- a chosen subset (any columns), Move to…
- carried: the card follows the hand, the company it would land in is outlined; Escape or a drop on its own company puts it back
- moving: the cards wait in their new company until the app answers
- partial move failure: the moved cards settle, the refused ones travel back with the reason
- pending invitation
- role change refused: the old role back and the reason on the card; the other scope untouched
- no companies (Add company)
- create draft; duplicate name or code; invalid code; editing with impact; saving; save refused with the draft kept
- no lead; proposed lead with the route comparison; changing; change refused (the current lead kept); lead removed

## Keyboard

- the access line is a button: focusing it opens the pickers and moves focus into Field; Escape closes them and returns to the person
- each person's checkbox, pickers and the company menus are standard controls; Move to… is a menu of the companies (the keyboard and touch route for a move)
- dialogs trap focus and return it to the menu that opened them

## Motion

A carried card follows the hand in the same frame; on a drop or a Move to… every moved card travels from where it stood (or was dropped) into its company, and a refused card travels back, both on the shared FLIP engine with the standard duration. Nothing moves at rest; reduced motion places at once.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `companies` | `ProjectCompany[]` | — |  |
| `defaultCompanies` | `ProjectCompany[]` | — |  |
| `onCompaniesChange` | `((companies: ProjectCompany[]) => void)` | — |  |
| `people` | `ProjectPerson[]` | — |  |
| `defaultPeople` | `ProjectPerson[]` | — |  |
| `onPeopleChange` | `((people: ProjectPerson[]) => void)` | — |  |
| `lead` | `string \| null` | — | The lead company's id; null for none. |
| `defaultLead` | `string \| null` | — |  |
| `onLeadChange` | `((id: string \| null) => void)` | — |  |
| `me` | `string` | — | The signed-in person (their card says "you"). |
| `project` | `string` | — |  |
| `onMove` | `((ids: string[], company: string \| null) => Promise<Record<string, string \| true>>)` | — | Move people to a company (null: no company). Resolve with each person's outcome: true when moved, or the reason they were kept where they were. The cards travel at once and settle on this answer. |
| `onRoleChange` | `((id: string, scope: "field" \| "office", role: string) => void \| Promise<unknown>)` | — | A role changed (only the one scope given). Reject with the reason to put the old role back. |
| `onCompanySave` | `((company: CompanyDraft) => void \| Promise<void \| ProjectCompany>)` | — | Save a new or edited company. Reject with the reason to keep the draft open. |
| `codeImpact` | `((companyId: string, code: string) => { count: number; from: string; to: string; } \| null)` | — | How many document numbers a new code renames, with one example; null when none use it. |
| `onLeadSave` | `((id: string \| null) => void \| Promise<unknown>)` | — | Make a company the lead (null: no lead). Reject with the reason to keep the current lead. |
| `leadRoutes` | `LeadRoutes` | — | What the lead and the other companies may route (for the comparison before a lead change). |
| `className` | `string` | — | Classes on the documented visual root; no override by default. |
| `style` | `CSSProperties` | — | Inline styles on the documented visual root; no overrides by default. |
| `ref` | `Ref<HTMLDivElement>` | — | Receives the documented native target or imperative handle; omitted by default. |

## Built from

- checkbox
- select
- [dropdown-menu](https://beamline.io/components/dropdown-menu)
- dialog
- input
- alert
- badge
- button
- [empty-state](https://beamline.io/components/empty-state)

## Dependencies

`lucide-react`

## Import

```tsx
import { CompanyAccess } from "@beamline/company-access";
```

## Get it

Company access is part of Beamline UI. Install the parts you need in your React app as compiled packages or editable source. [Get Beamline](https://beamline.io/checkout?pack=complete) · [Connect your agent](https://beamline.io/connect)

## More in Construction

- [Submittal register](https://beamline.io/components/submittal-register): The documents a trade owes a project before its material is bought, on the clocks that matter: a log whose rows each draw their way to site on one shared…
- [Change orders](https://beamline.io/components/change-orders): Change orders against a contract, with the money drawn where it stands: one bar of the original contract, each approved change, a line at the current…
- [Inspection review](https://beamline.io/components/inspection-review): A unit's inspection, reviewed in three views. Findings: rooms and features with their condition, answers, notes and photos, and each feature's…
- [Work orders](https://beamline.io/components/work-orders): A maintenance work order that coordinates subtasks: the children's progress drawn by status with cancelled ones counted apart, the parent completed on…
- [Action center](https://beamline.io/components/action-center): Everything waiting on a person across projects: a strip of every open item on the days ahead, one lane per kind of owing (You submit, You answer, Tasks…
- [Condition checklist](https://beamline.io/components/condition-checklist): An inspection by area. Each item marked good (success), soon (warning) or needs work now (danger), or not checked yet and kept apart below; what was…
- [Corrective actions](https://beamline.io/components/corrective-actions): A corrective action raised from a failed inspection answer, for food safety, facilities or quality teams. The answer, its photo and note are pinned above…
- [Quality checks](https://beamline.io/components/quality-checks): Quality checks by picture and the control points that make them. A check asks for one photo: an upload that fails keeps its file with Try again, and…
- [Maintenance plan](https://beamline.io/components/maintenance-plan): Maintenance of shared equipment. The instruments, most urgent first, each with its most pressing kind and how due it is (overdue, due soon, fine, never…
- [Maintenance plans](https://beamline.io/components/maintenance-plans): An operations team's maintenance plans. The queue lists every asset-plan pair (one machine can appear under two plans) with its last service, next due…
- [Equipment register](https://beamline.io/components/equipment-register): A business's machines and vehicles: a register filtered by status (in use, in repair, sold, each counted) with each machine's photo or type icon…
- [Asset workspace](https://beamline.io/components/asset-workspace): One physical asset: a machine, vehicle or piece of plant. Its header keeps the system id apart from the name and serial, with type, site, status and the…
- [Asset packs](https://beamline.io/components/asset-packs): Packs of assets (sounds, presets, fonts), the providers they come from and the storage they take. Download and install are two phases with their own…
- [Instrument use](https://beamline.io/components/instrument-use): Shared instruments. The slot search reads as one sentence (how long, which instrument type, the dates and the working hours with the lab's time zone)…
- [Job booking](https://beamline.io/components/job-booking): A customer books a home or field-service job on the company's own site, phone first. Services with how many units, each unit adding its time and price…
- [Job booking setup](https://beamline.io/components/job-booking-setup): Online booking for a field-service company, set up from three sides that feed one booking form. Services: each priced and timed per unit with whether it…
- [Rental availability](https://beamline.io/components/rental-availability): A rental shop's availability: a product's month for the quantity a customer wants (each day available, some left with the count, booked out or not known…
- [Rooms & equipment](https://beamline.io/components/resource-setup): A salon's or clinic's rooms and equipment and what its services need of them: resources by group at each location, how many appointments each holds at…
- [System pages](https://beamline.io/components/system-page): The four pages a product shows when the normal one cannot: page not found (search and the likely places), something broke (try again, an error id to…

Part of [Beamline UI: polished, editable React components and complete screens for custom applications](https://beamline.io/). [Build your own style from any look; tokens, fonts, radii, motion; not only colours](https://beamline.io/docs/customize).
