# devaction_ui v0.1.0 - Table of Contents

> Phoenix function components and LiveView hooks, themed with light-dark() tokens.

## Pages

- [DevactionUI](readme.md)

## Modules

- [DevactionUI.Accordion](DevactionUI.Accordion.md): Sections that open and close. Built on `<details>`, so it works with the keyboard, in assistive
technology and with no JavaScript. In `exclusive` mode (the default) opening one closes the others, which
the browser does itself through the shared `name` of the `<details>`.
- [DevactionUI.AiPrompt](DevactionUI.AiPrompt.md): The field that talks to the AI: a pill in ink with the amber dot, a text field and a round send button.
It is a form, so Enter sends; the LiveView gets `event` with the text under `name`.

- [DevactionUI.Alert](DevactionUI.Alert.md): A short message under a form or at the top of a screen: it worked, the AI did something, here is how it
is, this failed. Smaller than a `Callout`: one line of title and a line or two of text, with an icon.
`kind: :risk` is announced as an alert; the others as a status.

- [DevactionUI.Aura](DevactionUI.Aura.md): A turning ring of light around something, for the AI at work. It wraps its content, which keeps its own
surface; the ring is the wrapper's padding, painted by a conic gradient whose angle is animated.
- [DevactionUI.AuthCard](DevactionUI.AuthCard.md): The card of a sign-in screen: a header with a soft grid and an amber glow behind an icon tile, a title and a
line of text, then the form, and optionally a quieter strip at the bottom for the other way in ("No account?
Create one"). One screen is one card, or a card and a note under it.
- [DevactionUI.AuthLayout](DevactionUI.AuthLayout.md): The page around a sign-in screen: a framed panel with two columns. On the left the product (its mark and name,
a headline and a few reasons to sign in); on the right whatever the screen needs, usually an `AuthCard`; along
the bottom a copyright line and a few links. The columns wrap on a narrow screen, the product above the form.
- [DevactionUI.Autocomplete](DevactionUI.Autocomplete.md): Suggestions while you type, in groups (lessons, pull requests, tasks), with the part that matched in bold
and an optional last row that asks the AI. The server owns the search: the field sends `event` (debounced)
with the text, and the caller answers with `groups`; this component draws the field and the list and
moves the active row with ↑ ↓, opens it with Enter (the row is a link) and runs the AI row with ⌘ + Enter
(or Ctrl + Enter). Esc closes the list, typing opens it again.
- [DevactionUI.Avatar](DevactionUI.Avatar.md): A person as two letters in a circle, and the stack of them overlapping by 8px. The letters come from the
name (`initials/1`); the tone only tells people apart, it never carries meaning. A circle with no name is
decoration, so a stack names its people for assistive technology once, as a group.
- [DevactionUI.Badge](DevactionUI.Badge.md): Two small signals: `count/1`, the round bubble with a number (4 pull requests waiting), and `dot/1`, the
status dot (connected, running). A dot can pulse, and stops under `prefers-reduced-motion`.

- [DevactionUI.Breadcrumb](DevactionUI.Breadcrumb.md): Where the page is: `Today / SGE / PR #142`. The items are `%{label: ..., to: path}`; the last one has no
`to` and is the current page (`aria-current="page"`).

- [DevactionUI.Button](DevactionUI.Button.md): The buttons of the canvas, as a button or as a link, in the same colors and sizes.
- [DevactionUI.Calendar](DevactionUI.Calendar.md): A month or a week of days with their events, as an agenda of deliveries: each event is a coloured chip by kind
(risk, warning, ok, info, neutral). It is a `grid` (`role="grid"`, rows, column headers, cells) with one cell in
the tab order and the arrows, Home, End and Page keys moving between days (`DevactionUI.Calendar` hook);
pressing a day, or Enter on it, sends `select_event` with `phx-value-date`, and the previous and next buttons
send `prev_event` and `next_event`.
- [DevactionUI.Callout](DevactionUI.Callout.md): A tinted block that says something to the reader: a note, what the AI did, a tip, a warning, a decision.
Color is never alone: it always carries a title or an `icon` slot, and an `:alert` role when it is urgent.
- [DevactionUI.Chart](DevactionUI.Chart.md): Light charts in plain SVG, drawn on the server: a line with two series, horizontal bars, columns, a ring and
the sparkline of a number card. No library and no script: the hover is CSS (and keyboard focus shows the same).
- [DevactionUI.Chart.Geometry](DevactionUI.Chart.Geometry.md): The arithmetic of the charts, with no markup: where a value sits on an axis, the path of a line, an area, a
column with a rounded top and a slice of a ring. Every function is pure, so the charts can be drawn on the
server and tested without a browser.

- [DevactionUI.ChatBubble](DevactionUI.ChatBubble.md): One message of the conversation with the AI. The AI speaks on the left, with its mark beside the bubble
and the corner nearest the mark squared; the person speaks on the right in ink. A message that did
something (a lesson sent, a task made) is drawn `:highlight`, in the amber of "the AI did this".

- [DevactionUI.Choice](DevactionUI.Choice.md): Boxes to tick and options to pick, as the canvas draws them: the checkbox (with the partial state of "select
all"), the radio with its description and the choice card. They are real `<input>`s, so the browser, the form
and the keyboard do the work; the look comes from the `checkbox`, `radio` and `choice-card` classes.

- [DevactionUI.CodeBlock](DevactionUI.CodeBlock.md): A block of code in mono, given as the `code` attribute. `lang: :heex` colours it (components, slots, attributes,
strings, expressions, comments) through `DevactionUI.Highlight`. `tone: :dark` is the ink block of a suggestion; `:risk` and `:ok` are the
"your code" and "idiomatic" blocks of a lesson, tinted red and green. It keeps its own line breaks and
scrolls sideways instead of widening the page.

- [DevactionUI.ColorPicker](DevactionUI.ColorPicker.md): A colour field with a panel: a square for saturation and brightness, a hue strip, an optional opacity strip, a
row of preset colours and, in a browser that has one, the eyedropper. It always sends hex (`#RRGGBB`, or
`#RRGGBBAA` with `alpha`) in the text field named `name`, so a form reads it like any other field and
`phx-change` hears every change.
- [DevactionUI.Combobox](DevactionUI.Combobox.md): A select with a search box: the button shows the choice, the panel has a field that filters the list while
you type (ignoring case and accents), ↑ ↓ move, Enter chooses, Esc closes, and an empty result says so.
The value goes in a hidden input named `name`, and the hook fires `input` on it so `phx-change` hears it.
Options are `%{value: ..., label: ..., hint: ...}`; `hint` is a small mono text at the right.
- [DevactionUI.CommandPalette](DevactionUI.CommandPalette.md): The ⌘K palette as a library piece: a dialog near the top with a large field, an optional row of scopes
(all, pull requests, tasks...), the results in groups with their hints, an "ask the AI" action with the typed
text and a footer that teaches the keys. ↑ ↓ move the active row, ↵ opens it, ⌘↵ asks the AI and Esc closes it.
- [DevactionUI.ConfirmDialog](DevactionUI.ConfirmDialog.md): A modal that asks before something that cannot be taken back, such as publishing a review to GitHub.
The LiveView decides when it is there (`:if={@confirming}`); it takes the focus in, keeps it inside
(`Phoenix.Component.focus_wrap/1`), closes with Esc or the close button, and gives the focus back to
what opened it. The two buttons are the caller's, so the confirming one can say what it does
("Publish", not "OK").

- [DevactionUI.DangerDialog](DevactionUI.DangerDialog.md): The dialog before something that cannot be undone: stop monitoring a repository, delete a project. The red
button stays locked until the person types the name of the thing, so it is never a reflex. A click outside does
not close it, only Esc, Cancel and the close button do.
- [DevactionUI.DataTable](DevactionUI.DataTable.md): A table for lists that are worked on: sticky header, sortable columns (`aria-sort`, the server sorts and
the table only draws the arrows), optional row selection with a tri-state header checkbox and a bulk
bar that appears while something is selected, two densities and an empty state.
- [DevactionUI.DatePicker](DevactionUI.DatePicker.md): A month calendar that picks one day or a range, and the small chip that says how near a deadline is.
- [DevactionUI.Divider](DevactionUI.Divider.md): A thin line, or a line with a short word in the middle (the "OR" between a social button and a form). The word is
in mono capitals and is given by the caller. A divider with a word is a `separator` for assistive technology, and
the word is read out.

- [DevactionUI.Drawer](DevactionUI.Drawer.md): A panel at the side of the screen to edit without leaving it: a profile, a task, an item of a contract. The
default is floating (12 px from the edges, rounded, with a footer that stays); it can sit docked against the
edge, come from the left, and on a phone it is a sheet that rises from the bottom, with a handle.
- [DevactionUI.Dropdown](DevactionUI.Dropdown.md): A button that opens a menu of actions or a choice (sort by deadline, by value, by risk). The menu opens
under the button; ↑ ↓ Home End move between items, Enter or Space chooses, Esc closes and returns to the
button, a click outside closes it (`DevactionUI.Dropdown` hook).
- [DevactionUI.Dropzone](DevactionUI.Dropzone.md): The place to drop a file: a dashed area with an icon, what it takes and the limits. It wraps a LiveView
upload (`allow_upload/3`), so the same area takes a drop and a click, and highlights while a file is
over it (`DevactionUI.Dropzone` hook). What went wrong with a file is shown under it, from `errors`.

- [DevactionUI.Editor](DevactionUI.Editor.md): A rich text editor for delivery notes, scope and long comments: a toolbar over a TipTap (ProseMirror)
surface, the way the canvas draws it (`.editor`, `.editor-toolbar`, `.editor-btn`, `.editor-content`).
- [DevactionUI.EmptyState](DevactionUI.EmptyState.md): What a list or a screen shows when there is nothing in it yet. Every empty one says what the area is, why it
is empty and the one next step.
- [DevactionUI.FilterMenu](DevactionUI.FilterMenu.md): A button that opens a menu of filter groups; a group opens a submenu of ticks, checkboxes or radios. Ticking
does not close the menu. The menu is a form: it sends on Apply (`phx-submit`), or on every tick with
`phx-change`, as `%{"filters" => %{"status" => ["progress"], "who" => ["CA"]}}`. A count on each group and on the
button follows the ticks, except for an option marked `default`, which is what the filter already means.
- [DevactionUI.Highlight](DevactionUI.Highlight.md): Splits HEEx source into tokens a code block can colour: `{kind, text}` pairs whose texts, joined, are the
source again. It reads the shapes of a template (tags, components, slots, attributes, strings, `{}` and
`<% %>` expressions, comments), not the Elixir inside them, so it is cheap and never fails: what it does not
know is plain `:text`.
- [DevactionUI.InputGroup](DevactionUI.InputGroup.md): A text field with what the canvas puts around it: an icon at the start, an action at the end (show the
password, clear, copy) and add-ons on either side (`R$`, `https://`, `.devaction.app`). The frame carries
the focus ring, the error and the disabled look, so the field inside stays a plain `<input>`.
- [DevactionUI.Kanban](DevactionUI.Kanban.md): A board of columns with cards that move: drag a card to another column or to another place in its own,
or focus it and press Alt + arrow keys (←→ between columns, ↑↓ within one). The hook moves the card in the
page at once and tells the LiveView, which stays the source of truth: it receives the event with
`%{"card" => id, "from" => column, "to" => column, "index" => position}` and re-renders. To refuse a move,
answer with `{:reply, %{rejected: true}, socket}` and the hook puts the card back where it was.
- [DevactionUI.Kbd](DevactionUI.Kbd.md): A key cap: ⌘K, ESC, ↵. Mono 11px with a thicker bottom edge, as the canvas draws the keyboard hints.
- [DevactionUI.Modal](DevactionUI.Modal.md): A dialog for a decision that interrupts: confirm, tell that something worked, fill a short form. To edit
without losing the context use `DevactionUI.Drawer`; to ask before something that cannot be undone use
`danger_dialog/1`.
- [DevactionUI.MoneyInput](DevactionUI.MoneyInput.md): A field for Brazilian money: the person types digits and the field shows `R$ 1.234,56`, the last two
digits being the cents (`DevactionUI.MoneyMask` in `assets/js/devaction_ui`). What is sent is the text as
shown; the server reads it with `parse/1`.

- [DevactionUI.NumberInput](DevactionUI.NumberInput.md): A number field with a minus and a plus, for a quantity that is changed a step at a time (hours, seats, days):
the buttons are disabled at the limits, the field is a `spinbutton` that says its value and its limits, and
typing in it works as well. The LiveView keeps the value: it learns of a press in `event` (with `phx-value-step`
`-1` or `1`) and of typing in the field's own `phx-change`.
- [DevactionUI.PageHeader](DevactionUI.PageHeader.md): The head of a screen as the canvas lays it out: the breadcrumb above, then the title with its status tag and
the actions at the end, an optional line of text, and the tabs under it. It only places the pieces; each one is
the caller's (a `DevactionUI.Breadcrumb`, a `DevactionUI.Tag`, buttons, tabs).

- [DevactionUI.Pagination](DevactionUI.Pagination.md): Page links: previous, a window of numbers around the current one with the first and last page and an
ellipsis where it skips, and next. `path` is a function from a page number to the URL (or `patch` target).

- [DevactionUI.Panel](DevactionUI.Panel.md): The canvas card: a soft wrap around a bordered white panel.
- [DevactionUI.PasswordStrength](DevactionUI.PasswordStrength.md): The meter under a new-password field: four bars that fill as the password meets the rules, a line saying how
strong it is, and the rules with a mark for each that is met. The server computes it from the text
(`evaluate/2`) and the field sends it on `phx-change`; nothing is kept in the browser.
- [DevactionUI.Pillbox](DevactionUI.Pillbox.md): A field of removable pills, for labels, e-mails, stacks: type and press Enter (or a comma) to add one,
Backspace on an empty field removes the last, the × on a pill removes that one. Each pill is a hidden
input named `name[]`, so the form submits the list as it stands; the hook fires `input` on the box so
`phx-change` hears every change. The browser owns the pills after mount (`phx-update="ignore"`): give
it a new `id` to reset it from the server.

- [DevactionUI.Popover](DevactionUI.Popover.md): A panel anchored to a button, with an arrow: the trigger opens and closes it, Esc and a click outside
close it, focus goes into it when it opens and back to the trigger when it closes. It sits under (or over)
the trigger inside the same box, so it is for a card, a form or a menu, not for something that has to
escape a scrolling container.
- [DevactionUI.Progress](DevactionUI.Progress.md): A progress bar (`role="progressbar"`) with a value from 0 to 100 and the tone it fills with: ink by default,
amber for what the AI did, green when it is done. `:segmented` shows the same value in `segments` pieces (the
steps of a job), `:thin` is the 2 px line of the work in the background, and `indeterminate` is for what
has no end in sight: it shimmers (still, under reduced motion) and gives no value.

- [DevactionUI.ProgressToast](DevactionUI.ProgressToast.md): A notice for a job that takes a while: it fills as the job advances (`progress`, 0 to 100), with a ring of
light while it runs. When the LiveView sets `state` to `:done` it waits a moment (1.6 s, paused while the
pointer or the focus is on it), leaves, and tells the LiveView (`on_dismiss`, with `phx-value-id`) to drop
it. An `:error` never leaves by itself: the person reads it and closes it.
- [DevactionUI.Segmented](DevactionUI.Segmented.md): A control to pick one of a few options that change the view at once (list or board, week or month): a pill with
a segment per option. It is a `group` of toggle buttons with `aria-pressed`; the caller keeps the value and
learns of a choice through `event` (`phx-value-value`). A segment can have an icon, a count, or only an icon
(the label is then read by assistive technology). `full` stretches it to the width of its box.

- [DevactionUI.Sidebar](DevactionUI.Sidebar.md): The side menu of an app: 236 px wide, or 64 px when collapsed, where each item keeps its icon and shows its
name in a tooltip on hover and on keyboard focus. The current item has `aria-current="page"`. The caller keeps
whether it is collapsed (`collapsed`) and gets the press of the toggle in `on_toggle`; it is hidden on small
screens, where the app has its own navigation.

- [DevactionUI.SignatureField](DevactionUI.SignatureField.md): A field to sign: draw with the mouse, the finger or the pen, or type the name; clear and start again. It
writes what was signed into hidden inputs for the form: the method, the typed name or the SVG of the stroke
(`DevactionUI.Signature` hook, `exportSvg`). The SVG is the drawing only, in its own coordinates, so it can be
kept and drawn back at any size. A drawing is accepted by the server only after `safe_path?/1`.

- [DevactionUI.Skeleton](DevactionUI.Skeleton.md): A placeholder for what is loading: a bar (`:line`), a round shape (`:circle`) or a block (`:block`),
with a shimmer that stops under `prefers-reduced-motion`. Size it with `class` (`h-4 w-40`).

- [DevactionUI.Slider](DevactionUI.Slider.md): A slider for a value inside a range, and a range slider for two (a from and a to). Both are native
`<input type="range">`, so the keyboard (arrows, Home, End, Page keys) and assistive technology work as the
browser does them; the look is the canvas's. The value is shown beside the track and is the LiveView's, sent
by the form's `phx-change`.
- [DevactionUI.Spinner](DevactionUI.Spinner.md): A spinning ring for work in progress. The label is read by screen readers and never drawn.
- [DevactionUI.Stat](DevactionUI.Stat.md): A number with its name: the mono caption over a large value, optionally with a small `trend` tag beside
it. `highlight` is the inverted version, white on ink, for the one number a screen is about. The value
is the slot, so it can carry a unit (`7<span>/12</span>`).

- [DevactionUI.Stepper](DevactionUI.Stepper.md): The steps of an onboarding or of a creation wizard, with the state of each: `:done`, `:current`, `:error` and
`:todo`. Horizontal, each step is a bar over a dot, a label and a line of help; vertical, it is a checklist with
a rail. The current step carries `aria-current="step"`, and the state is also written (not only coloured) for
assistive technology.

- [DevactionUI.Steps](DevactionUI.Steps.md): A row of steps with connectors: done (ink, with a check), the current one (amber ring) and those still
to come (a thin outline). `current` counts from 1; the labels are the caller's text.

- [DevactionUI.Switch](DevactionUI.Switch.md): A switch for what takes effect at once, with no save button (for a choice that only counts after saving, use a
checkbox). It is a `<button role="switch">`: `aria-checked` says the state, the keyboard toggles it and the
caller does the work in its own `phx-click`. While the change is being kept, `saving` makes the thumb pulse and
the control ignore presses; `saved_note/1` is the "saved now" the caller shows after.
- [DevactionUI.Tabs](DevactionUI.Tabs.md): Tabs that switch panels without a round trip: `variant: :boxed` is the pill group, `:line` the underlined
row. A small hook moves the selection with ← → Home End (roving `tabindex`, `aria-selected`) and shows
the panel of the selected tab. Each tab may carry a `count`.
- [DevactionUI.Tag](DevactionUI.Tag.md): The small mono label of the canvas: EM RISCO, AGUARDANDO, EM DIA, APRENDIZADO, PLANEJADO.
- [DevactionUI.Textarea](DevactionUI.Textarea.md): A text area as the canvas draws it: it grows with its text (`field-sizing: content`, up to 12 lines), has an
optional footer for actions (attach, mention, improve with the AI) and a counter that turns red near the
limit. The label and the help text are the caller's; this is the field.

- [DevactionUI.Timeline](DevactionUI.Timeline.md): Things that happened, in order, on a thin line: each item has a dot in a tone, a title, a time and optional text.
- [DevactionUI.Timer](DevactionUI.Timer.md): A timer of hours for a task: a small caption of its state, the time in large mono digits, what is being timed, and two round buttons: start or pause, and stop and log. The
LiveView owns the truth (it is not lost on a reload): the seconds already counted (`base`) and, while it runs,
the moment it started (`started_at`, in seconds since the epoch). The browser only draws the passing seconds
between two updates (`DevactionUI.Timer` hook); `elapsed/3` is what the server counts when it logs.

- [DevactionUI.ToastGroup](DevactionUI.ToastGroup.md): Notices that pile up without covering the screen: while there is more than one they sit as a stack of
layers with a count, and a click (or the button) opens them into a list with "Collapse" and "Clear".
Each toast closes by itself after `duration` milliseconds (0 keeps it), pausing while the pointer or the
focus is in the group or the list is open. Closing one, or clearing all, is sent to the LiveView
(`on_dismiss`, `on_clear`), which is the source of truth: it removes the toast from what it renders.
- [DevactionUI.Tone](DevactionUI.Tone.md): The five tones of the canvas (`:risk`, `:warn`, `:ok`, `:info`, `:neutral`) as class strings, so every
component that tints something (a callout, a finding, an alert, a progress bar) takes the same colors
from the same tokens and flips with the theme.
- [DevactionUI.Tooltip](DevactionUI.Tooltip.md): A short hint on hover and on keyboard focus, drawn by CSS only. The trigger is the slot; `text` is what it
says, tied to the trigger with `aria-describedby`. It is for a name or a short explanation, never for
something the person must read to continue.

