Changelog for MishkaChelekom 0.0.10

Copy Markdown View Source

Features:

  • Every Mob component template in priv/mob links to its page on mishka.tools in its moduledoc (**Documentation:** https://mishka.tools/chelekom/docs/mob/<name>), like the styled components
  • mix mishka.ui.gen.mob and mix mishka.ui.gen.mob.components declare the generated tags in the app's own config :mob, :extra_tags instead of writing into deps/mob/priv/tags/*.txt, which mix deps.get discarded and Mob's docs say not to edit. Only missing tags are added to a ~w() or plain list, the rest of the list is kept, and mix mishka.ui.uninstall removes just the removed tags. Igniter 0.8.5
  • The CMS bundle says which attributes also take a class string. Where every helper an attribute reaches ends in a defp helper(params) when is_binary(params) catch-all — size, rounded, padding, space, most variants — the template draws size="py-1 px-2" as readily as size="small", and the bundle now ships the named list as Phoenix's non-exhaustive opts.examples instead of a closed opts.values, so a consumer that validates against values stops refusing it. 311 attributes ship examples; an attribute this cannot read in full stays closed
  • The CMS bundle carries each attribute's own option list. A component's args: config already enumerates what variant, color, size, rounded and padding accept, and the exporter threw it away — a consumer had to recover the same lists from the <%= if %> gating around each helper clause, which is lossy (alert's fourteen colours came back as eleven). The list is now written onto the attribute as opts.values, where attr :color, :string, values: [...] would have put it, and is skipped for the few attributes whose own default contradicts it (default: ""), because a bundle whose components cannot be compiled is worse than one that says less about them. 23 attributes carried a value list before; 364 do now
  • The CMS bundle carries each component's doc_url, so a consumer can link to the page that explains the component it is offering
  • The daisyUI gallery paints all 92 headless components with daisyUI and Tailwind classes in the examples' own markup. Copying an example gives you the component and its look; there is no stylesheet to take with it. The design system itself stays your dependency
  • A *_class attribute for every part a component renders, so any part can be restyled from markup. This is what makes the class-only gallery possible, and it is enforced by a test that reads the components' own sources
  • Known divergence from the stylesheet it replaces: a few parts whose CSS declared color: var(--color-base-content) no longer declare it, so under a dark data-theme they inherit the surrounding colour instead of following the theme (slider and its descendants, pagination's ellipsis). Painting it back is not the fix — the declaration used to lose to daisyUI's own colour modifiers (range-primary and friends) from @layer components, and the same value written as a utility wins, flattening every coloured variant. Set the colour on your own container if you place these in a dark subtree
  • Add 17 headless components, taking the line from 75 to 92: alert, breadcrumb, button, calendar, card, carousel, countdown, dock, fab, file_input, pagination, rating, stepper, table, text_input, textarea and theme_controller
  • The headless switch takes :on_icon and :off_icon slots. Both render inside the track, after the thumb, and carry data-checked/data-unchecked, so a skin can cross-fade them rather than swapping one element for another

Bug fixes:

  • The headless chart keeps its styling with --lib billboard under a Content Security Policy that allows no inline style. The engine wrote billboard's stylesheet into a <style> element, which a style-src without 'unsafe-inline' or a nonce refuses, so lines filled in black and the axes and tooltips lost their look. It now adds the same rules once per page as an adopted constructable stylesheet, which no style-src governs, and adopts it again after a LiveView navigation only if the page dropped it. Its tooltip, unless the config names a template of its own, draws each series' swatch as an SVG circle filled through its fill attribute instead of billboard's style attribute. billboard: { injectStyles: false } in chart_extensions.js still turns both off; a browser without constructable stylesheets warns once and draws the charts unstyled. A test now fails on any hook in the library, or in the CMS kits, that writes a <style> element or a style attribute

  • The headless chart draws with --lib billboard. A bundler resolves billboard.js to its ESM build, which draws a chart type only after that type's module has been called, so every chart threw "Please, make sure if 'line' module has been imported" while mounting and the page's LiveView never connected. The engine now imports all twenty billboard type modules and replaces data.type and each value of data.types with its module's call; it also calls the grid module, and the zoom, subchart, data selection and regions modules when the config turns them on. The config keeps the string types the billboard docs show, and an unknown type warns once in the console and draws as a line

  • Generated components lay out the same on every Elixir. 31 helper clauses (21 in 16 styled templates, among them dock, blockquote, button and table, and 10 in the headless card, chart, dock, sparkline and stepper) were written defp name(args) when guard, do: value. Once that outgrows a line, Elixir 1.18 puts do: on a line of its own and 1.19 and later keep it after the guard, so a file generated on one failed mix format --check-formatted on the other. They are written with do ... end, which every version lays out alike, and TemplateFormatStabilityTest fails on a new guard clause that takes do: and does not fit on one line

  • The buttons in the demos and the usage rules show the pointer: 213 examples across priv/demos and usage-rules (the table, clipboard, collapse, navbar and dropdown demos, the component, headless and hook rules) name cursor-pointer, so what a reader copies keeps the cursor v3's preflight gave it. TailwindV4ClassesTest reads them as it reads the templates

  • The development showcase's own buttons show the pointer too: the alert preview's dismiss button, a button a page puts in a component's slot, the form-demo submit buttons and the rest — 101 of them. The templates' pointer test never saw them, since they are page markup, so a second test reads the pages. And the sidebar preview can be closed: it held translate-none! on its root, which the close command, removing translate-none, cannot take away; a test now holds the classes hide_sidebar, show_sidebar, hide_drawer and show_drawer add and remove against the roots they are rendered on and against the previews

  • Buttons keep the pointer cursor. Tailwind v3's preflight set cursor: pointer on button and [role=button]; v4's does not, so every clickable the templates render showed the arrow. Each of them carries cursor-pointer itself now: 31 elements across alert, badge, banner, carousel (arrows and indicators), clipboard, collapse, combobox (trigger and clear button), dock, drawer, file_field, gallery (filters), mega_menu, modal, password_field, search_field, sidebar, speed_dial and toast, plus the flash alert, which dismisses on click, and the trigger of a clickable popover. The collapse trigger also sets it on a button inside, which the arrow would otherwise reach through the wrapper. The examples in the component docs use it on their buttons too. The clipboard and collapsible hooks add the class to an element they mark role=button. TailwindV4ClassesTest fails on a button or role=button in a styled template that names no cursor-pointer, itself or in the helper that builds its classes

  • The daisyUI gallery's focus rings draw in v4. focus:outline-none sets the outline style to none and focus-visible:outline-2 only sets a width, so the breadcrumb links and the forced-colors fallbacks of the menu, select and tabs examples (48 classes) never drew a ring; each now has outline-solid under the same variants, as the Base UI examples do

  • The class names the kit ships are Tailwind v4's, not v3's. v4 kept most v3 names as aliases, so nothing failed to compile — a class just meant something other than what it was written for. Every class in the templates, demos, showcase examples, usage rules and hooks was compiled with Tailwind 4.3.3 and none is a name v4 dropped (bg-opacity-*, flex-shrink-*, overflow-ellipsis and the rest of that list are not in the kit); what was left is below, and TailwindV4ClassesTest reads every class string, the showcase examples and the exported bundles for any of it

  • The renamed scale takes its v4 names: shadow-sm is shadow-xs (39 base variants), a bare shadow is shadow-sm, blur is blur-sm, backdrop-blur-sm is backdrop-blur-xs, rounded-sm is rounded-xs and a bare rounded is rounded-sm, with every side and corner form (rounded-t is rounded-t-sm, rounded-s is rounded-s-sm, rounded-ee is rounded-ee-sm). 148 classes in the templates; the size each one draws does not change

  • focus:outline-none is focus:outline-hidden in the 38 places the templates use it. v4's outline-none removes the outline for forced-colors users too; outline-hidden is the v3 class, an invisible outline that still shows there. The checkbox and radio card focus ring drops the bare outline it set beside outline-2, which sets the style in v4

  • bg-gradient-to-* is bg-linear-to-* in the 371 gradient classes of the buttons, badges, alerts, banners, cards, pagination, progress, stepper, chat and mega menu, with their hover:, rtl: and arbitrary-variant forms. The from-, via- and to- stops are as they were

  • The important modifier is written at the end (top-0!, [&_.indicator-top-left]:translate-x-0!, size-2!), v4's spelling; the leading ! is only accepted as a deprecated form. 187 classes, most of them the avatar indicator positions

  • The drawer and the sidebar bring a panel back into view with translate-none where they added transform-none. v4 moves a panel with the translate property, which transform-none does not reset, so a custom position class that survived the removal of -translate-x-full would have stayed in place

  • A border or divider has a colour of its own. Tailwind v4 draws border, border-* and divide-* in currentColor where v3 drew gray-200, so a width class with no colour followed the text colour. Every component was rendered with each variant and colour and its widths matched to colours: the bordered white and dark accordion draw their item separators in the wrapper's border colour, as every other colour does; a button group's separators are base-border-light / base-border-dark (through :where(), so a button with its own border colour keeps it); the default combobox trigger takes the same pair; the dropdown gradient variant draws no border, like the gradient variant of every other component; the sidebar toggle, the file field's upload item and the blockquote's caption divider take a colour. A render test of the generated components fails on a border or divider that has none

  • extra_small and small are two sizes again. Tailwind v4 moved the scale of rounded, shadow, blur, drop-shadow and backdrop-blur down one step, so rounded-sm and a bare rounded are both 0.25rem, and 50 components mapped extra_small to the first and small to the second: a banner at either size measured 4px. extra_small is rounded-xs now, with its side forms (rounded-t-xs, rounded-b-xs, rounded-s-xs, rounded-e-xs, rounded-es-xs, rounded-ee-xs), the 0.125rem that rounded-sm was in v3. The same fix is shadow-xs in the avatar, gallery and image shadow sizes and blur-xs in the image blur filter. small is as it was; the sizes from medium up did not move. drop-shadow and backdrop-blur have no size helper in the kit. A test reads every helper for two sizes whose classes are one value in v4, with a table of the known pairs

  • A form field renders without name, value or label. <.email_field name="x" /> raised KeyError :value, because name and value had no default and nothing read from a field supplied them. name and value default to nil on email_field, text_field, number_field, password_field, tel_field, url_field, search_field, textarea_field, range_field, input, checkbox_field, group_checkbox, radio_field, group_radio and date_time_field (and label on the last); name on checkbox_card, radio_card, color_field, file_field, native_select and toggle_field; for on form_wrapper; options on input. The field clause takes field.name and field.value when the caller gave none, since a default that is there already is never replaced by assign_new/3. A toggle_field bound to a true field is checked, and a color_field bound to a field shows its color, where both ignored the field's value. A test renders every generated component with only its required attributes

  • The banner's border_position and rounded_position name the edge: top draws border-t (and rounds the top corners, rounded-t), bottom draws border-b (and rounds the bottom corners, rounded-b). top drew border-b, and rounded_position was inverted, so top rounded the bottom corners. border_position defaults to bottom, which is what top drew, so a banner with neither attribute looks as before; an explicit top or bottom on either attribute now names the edge it says. A test reads every border_position and rounded_position clause for the edge it names

  • rounded="none" draws no radius on footer, form_wrapper, gallery, image, mega_menu, navbar, popover, progress, table, table_content, toggle_field, tooltip, video and the base tabs; it was printed as the class none. The catalogs that lacked none list it, so the CLI offers it. A test fails on a rounded helper with no clause for none

  • The image ismap attribute is a boolean (<.image ismap />), not a string, and is off by default

  • dropdown_trigger no longer declares trigger_id, which nothing read

  • The dropdown, popover and navbar examples put space, rounded, width, padding, id and trigger_id on the :trigger and :content slots, which take only class, and left out the id the component needs. They are attributes of the component now, and a test fails on a slot attribute in a documented example that no component declares. The same fix is in the dropdown and popover usage rules, where the popover's content is the :content slot, not the inner block

  • variant="unbordered" is bordered in the drawer, footer, jumbotron, menu, speed_dial, tel_field and toast docs, the demos and the usage rules, and variant="ghost" is transparent; the accordion in the menu example is transparent, not menu. A test fails on a variant in a template or usage rule that no catalog or color_variant/2 clause has

  • The progress docs give the semi-circle defaults its attributes declare (200 and 12) and name the ring's color, not a progress_color it never took. The jumbotron usage rules name its border_size and its top, bottom and vertical border positions

  • The usage_rules setup in usage-rules.md is the 1.2 one: usage_rules: [file: "CLAUDE.md", usage_rules: [:mishka_chelekom]] in project/0, then mix usage_rules.sync, and {:mishka_chelekom, sub_rules: ["components/button"]} for one component's rules

  • A carousel slide without an image renders its title and description, and no picture; it raised KeyError :image

  • A range_field <:range_value> without a position sits at the start; it raised FunctionClauseError

  • A combobox with no id takes one from its name (name="user[role]" is combo-user_role), the same on every render, and a random one only with neither. It was -combo, because the attribute's nil default left assign_new/3 nothing to fill in

  • The native_select option slot's disabled is a boolean (<:option disabled>)

  • The catalogs of accordion, checkbox_card, checkbox_field, color_field, combobox, date_time_field, gallery and radio_card list the none and full rounded values their templates have a clause for, and a test fails on a clause the catalog does not list

  • The file_field docs and usage rules say what live and dropzone need (upload, or uploads and target); the dropzone examples in the usage rules passed upload alone

  • The popover demo docs and the navbar and popover demo samples no longer give a slot a trigger_id, and the menu demo's accordion variant is transparent

  • The usage_rules sync test runs the 1.2 configuration (usage_rules: in mix.exs) instead of the 0.1 command-line form

  • The headless editor adds no inline <style> of its own, so it draws under a strict Content Security Policy (style-src-elem 'self' 'nonce-…') without a console error. TipTap 3 appends a <style data-tiptap-style> to <head> by default, and the policy blocks it; the TipTap engine now passes injectCSS: config.injectCSS ?? false. The ProseMirror base rules that style carried (position, overflow-wrap, ligatures off, contenteditable="false" spans, pre, the separator image, the gap cursor, the hidden selection) are Tailwind classes on the editor's surface, merged with surface_class, so TipTap and Milkdown keep them. The editor's own rules in mishka_chelekom_headless.css (the surface fill, no outline, white-space, the empty-document placeholder) are surface classes too and left the stylesheet, so the editor is styled once; every other headless component keeps its stylesheet rules. The gap cursor draws in the current text colour rather than black and pulses with Tailwind's animate-pulse instead of a hard blink. injectCSS: true and injectNonce in editor_extensions.js bring TipTap's own stylesheet back, with a nonce. CodeMirror cannot run without the <style> it mounts, so the same injectNonce key reaches its EditorView.cspNonce; Lexical and Milkdown inject none. Generate the editor again after upgrading, since the stylesheet no longer carries its rules

  • The headless editor's toolbar marks a mark toggled at a collapsed cursor at once. Bold with nothing selected only sets the stored marks, a transaction that changes neither the document nor the selection, so the TipTap engine, which repainted data-active from onUpdate and onSelectionUpdate, showed it one keystroke late. It repaints on every transaction now, once per keystroke. Milkdown, Lexical and CodeMirror have no toolbar commands, so nothing lags there

  • A display utility in a component's class replaces the component's own. Tailwind writes display utilities in name order, not in class-list order, so the button's default inline-flex beat a caller's hidden and class="hidden md:flex" never hid it. Where a component's own display sits on the element that takes the caller's class, it now steps aside when that class names one (hidden, block, grid, …); a display behind a variant (max-md:hidden) leaves it in place, and the button's display attribute steps aside the same way. Changed: avatar_group, badge (and its dismiss button), button, button_group, button_link, input_button, card_title, chat, checkbox_card, group_checkbox, the combobox option, gallery, indicator, flex, grid, header, pagination (and its buttons), the progress sections, group_radio, shape, spinner, stat, stat_group, stepper, stepper_section, tr, tabs, timeline_section, and the labels of file_field, radio_field, range_field, rating and toggle_field. The modal's hidden is its closed state, not a display, and stays

  • An avatar keeps its size in a flex row. Its root clips its content, which lets a flex parent shrink it, so the initials of an avatar without an image (+20, SB) were cut off in a narrow row

  • A breadcrumb wraps to the next line in a narrow parent instead of overlapping its items; its icons and separators keep their size, and a separator stays at the end of the item before it

  • button_link, the headless button and the headless anchor take navigate or patch only when it is a string. A key that was present but nil chose its clause anyway, so a destination that came out empty turned the headless button into a link, and sent button_link and the anchor to href="#" instead of their href

  • The headless rating reads a whole star as 3 of 5, not 3.0 of 5; a half star still reads 2.5 of 5

  • The headless stylesheet hides a closed fab dial, as it hides every other popup. The dial stayed on the page unless the skin added data-closed:hidden

  • The CMS bundle names every row the way a CMS stores it, and every reference by that name. A CMS slugifies each component, hook and stylesheet name as it saves the row and rewrites nothing that refers to one; the exporter slugified only the part after the kit's name, so the headless kit shipped chelekom_headless-button calling chelekom_headless-button-content, stored as chelekom-headless-button-content, and every headless button failed to render its label. The same rule missed dependencies: chelekom-scroll_area (tabs, combobox) and chelekom_headless-tree (tree_select) named rows that do not exist. One function now gives the name a row is written under, a template calls, a dependency lists and a hook key is built from, and a test fails on a row not in its stored form or a reference to a component its kit does not have

  • The CMS bundle names a hook by the key a CMS registers it under wherever a template names one, not only in a literal phx-hook="…" or an attribute's default. The headless textarea shipped phx-hook={@autosize && "Autosize"}, so on a CMS page the browser logged unknown hook found for "Autosize" and the textarea never grew; it ships GlobalChelekomHeadlessAutosize. Every string inside a phx-hook={…}, and the default of every attribute one reads, is rewritten, and the shipped-kits test fails on any hook a component names that its kit does not register

  • The icon docs describe what it renders: a hero- name, class and global attributes. They listed variant, size, color, animate, aria_label and non-Heroicon names it never took. Its doc_url is its docs page instead of internal

  • The floating hook (dropdown, popover, tooltip) measures its content out of the flow. The content is moved to <body> and was measured as a static block there, as wide as the page, before it was made absolute, so the viewport clamp pushed a menu opening under its trigger to the left edge of the page. It is made absolute, and given its width, before it is measured; the first open of a menu whose classes stretch it to the page's width was still measured page-wide

  • The CMS bundle's value lists come from the axis an attribute is gated on, not only from its name. alert and flash take their colour through kind, which carried no list, so a consumer that casts values dropped kind="danger" and every alert drew natural; kind now carries the color list. type and only in a component's args choose which functions the generator writes, and that list no longer reaches an attribute: input_button's HTML type shipped ["button_group", "button", …]

  • Classes Tailwind drew nothing for: ease-in-ou (button), ::flex-1 (pagination), flex-start (stepper), fill-opacity-* (rating), sm:font-inherit (ten fields, now sm:text-[length:inherit]), bordered-text-… (text_field), and theme colours the theme never defined — *-bordered-hover-* (accordion, now in the theme for every colour), progress-bg (gradient progress, now the track's own colour), table-* (table), default-white-bg (card), natural-bordered-dark (footer), primary-inverted-gradient-indicator-dark (button), custom-black-100 (file_field) and the *-bg-* / *-ring-* / dark-* set of date_time_field's bordered variant. A test now holds every theme colour a template names to the theme

  • The floating hook (dropdown, tooltip, popover) reads no layout while it mounts. It read the page's direction and placed its hidden content on mount, and each of those reads, right after the previous hook moved its content to <body>, made the browser restyle the whole page: a page with 142 tooltips took about three seconds to show after a LiveView navigation, and about 0.4 seconds now. The direction is read and the content placed when it is shown, and a scroll or a resize places only the content that is open

  • A styled generation no longer wipes a project's own @theme tokens (#511). Chelekom's tokens are set in the plain @theme with igniter_css 1.1's ensure_at_rule_declarations — a token it already has only changes value, a missing one is appended — and the project's --font-* / --color-* and their comments stay; a project's @theme inline is left alone

  • mix mishka.ui.uninstall --include-css takes back only what the install set: the vendor @import and Chelekom's tokens. It deleted every @theme block, the project's own and @theme inline included, and rewrote the whole file even when nothing in it was Chelekom's. A generation followed by an uninstall now gives app.css back byte for byte; a token the project changed stays

  • The first JS hook generated into a project with no assets/vendor/mishka_components.js was never registered — the registry was created from its empty template and the update skipped — so a lone headless chart never mounted

  • A css_overrides value that is not CSS stops the generation and names the override, instead of being dropped while the default shipped

  • The MCP list_css_variables resource reads the variables and their defaults from the stylesheet; its hand-kept copy (and the sample config.exs) had lost --opacity-base and --overlay-opacity

  • The chart's docs named an --engine option the generator rejects; it is --lib chartjs / --lib billboard

  • --cms export no longer crashes on a helper written defp x without parentheses

  • The headless radio_group never went horizontal. Its root hardcoded data-orientation="vertical" while the JS engine was already reading that attribute to decide which arrow keys move the selection, so the option was unreachable: there is an orientation attribute now, and the keyboard follows it

  • Breaking: id is required on the headless avatar. It was optional, but the hook that tracks the image's loading state keys off it, so an avatar without one silently never resolved its fallback. Phoenix reports the missing attribute at compile time, so an affected call site is a warning rather than something to hunt for at runtime

  • A guarded helper clause keeps its discriminators. Discriminators.extract_head/1 stripped the when guard when building its lookup key while the exporter wrote that guard INTO the clause's args, so the two signatures could never match and all 867 guarded clauses in the kit shipped with an empty discriminators list — most of the option lists a consumer needs to build a picker

  • Add headless Editor component (TipTap 3 parity) — rich-text editing via an Editor JS engine (hook on an inner phx-update="ignore" surface, hidden textarea mirror so it submits as an ordinary form field, toolbar buttons wired by data-editor-command), with a Phoenix form demo

  • Add npm dependency support to the generators — a component can declare npm: in its catalog and mix mishka.ui.gen.headless <name> installs it (npm/bun/yarn auto-detected, falling back to the {:bun, ...} hex binary so no system Node is required), gitignores assets/node_modules and prepends the install to the assets.setup/build/deploy aliases so CI and Docker builds work. --no-npm skips the install; npm-backed components are excluded from mix mishka.ui.gen.*.components unless named explicitly or --with-npm is passed

  • Add headless Tree component — Mantine's Tree converted to a Phoenix headless component, with expand/collapse, single/multiple and shift-range selection, cascading checkboxes (with indeterminate) or check_strictly, WAI-ARIA treeview keyboard navigation, drag & drop, and server-driven async child loading

  • Add Base UI gallery example and live server-driven examples (controller, form, single event, async, drag & drop, search) for the Tree component

  • Add headless EmptyState component — Mantine's EmptyState converted to a Phoenix headless component: an optional indicator, title/description shorthands, extra body content and an actions row, aligned via data-align (left/center/right); ships no colors, spacing or role (presentational — add role="status" for dynamically shown states)

  • Add headless CloseButton component (Mantine parity) — an icon-only button with a required aria-label, custom-icon slot and data-disabled

  • Add headless Burger component (Mantine parity) — a hamburger navigation toggle with aria-expanded/aria-controls and data-opened

  • Add headless Chip component (Mantine parity) — a selectable pill backed by a native checkbox/radio input, checked styling via :has(:checked)

  • Add headless Pill component (Mantine parity) — a compact tag/token with an optional accessible remove button and data-disabled

  • Add headless TagsInput component (Mantine parity) — removable tokens plus a draft input; add via a form phx-submit or on_add, remove via on_remove, click-to-focus via JS.focus, no JS hook

  • Add headless Spoiler component (Mantine parity) — clamp long content behind a Show more / Show less toggle via JS.toggle_attribute, no JS hook

  • Add headless ColorSwatch component (Mantine parity) — display a single color as a labelled role="img" swatch with optional overlay

  • Add headless Code component (Mantine parity) — inline <code> or a <pre><code> block

  • Add headless Mark component (Mantine parity) — highlight an inline run of text with <mark>

  • Add headless VisuallyHidden component (Mantine parity) — hide content visually while keeping it available to screen readers

  • Add headless ThemeIcon component (Mantine parity) — a container that wraps an icon, decorative or labelled

  • Add headless ActionIcon component (Mantine parity) — an icon-only action button with a required accessible label

  • Add headless Anchor component (Mantine parity) — a plain, themeable link

  • Add headless Marquee component (Mantine parity) — seamless CSS-only scrolling row (content duplicated, second copy aria-hidden), no JS hook

  • Add headless NumberFormatter component (Mantine parity) — render-time number formatting with thousands/decimal separators and prefix/suffix, no JS

  • Add headless HueSlider component (Mantine parity) — a 0–360° hue picker reusing the shared Slider engine, no new JS

  • Add headless AlphaSlider component (Mantine parity) — a 0–100 opacity picker reusing the shared Slider engine, no new JS

  • Add headless Splitter component (Mantine parity) — two resizable panes via a Splitter JS engine (pointer drag + keyboard, role="separator")

  • Add headless Scroller component (Mantine parity) — horizontal scroll row with prev/next controls via a Scroller JS engine (ResizeObserver end-detection)

  • Add headless RollingNumber component (Mantine parity) — animate a number to its value via a RollingNumber JS engine (rAF, reduced-motion aware)

  • Add headless ColorPicker component (Mantine parity) — saturation/value drag area + hue slider via a ColorPicker JS engine (HSV↔hex, hidden input for forms)

  • Add headless Highlight component (Mantine parity) — wrap case-insensitive matches of one or more query terms in <mark> at render time, no JS

  • Add headless SemiCircleProgress component (Mantine parity) — a half-circle SVG gauge (role="progressbar") computed at render time, no JS

  • Add headless NavLink component (Mantine parity) — a nav item that's a <.link> leaf or a native <details> disclosure with nested children (data-active/aria-current), no JS

  • Add headless JsonInput component (Mantine parity) — a JSON textarea with a server-validated data-invalid state (parse/format via Jason in LiveView), no JS

  • Add headless SegmentedControl component (Mantine parity) — a row of native radios with :has(:checked) selection and Arrow-key navigation, no JS

  • Add headless LoadingOverlay component (Mantine parity) — an absolute role="status" loader overlay toggled by visible (CSS fade), no JS

  • Add headless PillsInput component (Mantine parity) — an input-shaped container for pills + a text field, click-to-focus via JS.focus, no JS hook

  • Add headless MaskInput component (Mantine parity) — format-as-you-type text field driven by a MaskInput JS engine (9/a/* pattern), with a Phoenix form demo

  • Add headless AngleSlider component (Mantine parity) — circular 0–360° dial driven by an AngleSlider JS engine (pointer + arrow keys, --angle fill var), with a Phoenix form demo

  • Add headless OverflowList component — single-row list that collapses overflow into a +N counter via an OverflowList ResizeObserver engine, with an on_change server round-trip demo

  • Add headless FloatingIndicator component (Mantine parity) — a highlight box that measures and slides over the active target via a FloatingIndicator JS engine, with an on_change server round-trip demo

  • Add headless FloatingWindow component (Mantine parity) — a draggable, clamped panel via a FloatingWindow JS engine (on_move server round-trip, non-drag handle controls), with a demo

  • Add headless ColorInput component (Mantine parity) — hex field + swatch opening a color picker popover (reuses the ColorPicker engine with two-way hex editing, JS-command popover), with a Phoenix form demo

  • Add headless TreeSelect component (Mantine parity) — a JS-command disclosure that opens a tree in a popover to pick a value, with a Phoenix form demo wiring the tree's on_select

  • Add Mishka Tools documentation button to headless component pages, and point ARIA pattern at the component's spec_url instead of its docs URL

  • Add per-option tagged, base-first examples to mix mishka.ui.export --cms: every component now ships at least one example, ordered base-first, with extra.examples[] carrying label/section/base/requires so a consumer can hide an example whose variant was not installed Commit

  • Add ## Examples docs to label/1, error/1, header/1 and simple_form/1, so every public component function documents its usage

  • Add headless Chart component — one charting API over three swappable engines: Apache ECharts by default, Chart.js or billboard.js on request. Each engine installs under a single file name, so switching engines replaces the vendored file instead of stacking them, and every engine is exact-pinned and permissively licensed

  • Add headless Sparkline component — a server-rendered SVG trend line with no npm package, no scripts and no JS hook, so it renders in a table cell, a stat card or an email, whichever chart engine (if any) you generated

  • Add decode_atom_map/1 beside the __atom_map__ encoder, so a consumer can read a bundle's encoded atom keys back without reimplementing the format

Mob (native Android and iOS):

Mob renders native Jetpack Compose and SwiftUI from Elixir. Every component below is a native port of its headless counterpart — the same props and the same event contract, with no styling of its own — generated by mix mishka.ui.gen.mob and written as a tag, <Accordion />, exactly like the Phoenix component it mirrors.

  • Add mix mishka.ui.gen.mob, mix mishka.ui.gen.mob.components and mix mishka.ui.gen.mob.kit to generate native Mob components into a Mob application, honouring --module-prefix and carrying each component's kit dependencies with it
  • Add Mob support to mix mishka.ui.uninstall
  • Add mix e2e to run the on-device Compose test suites against a connected emulator or handset
  • Add usage rules for every generated Mob component, alongside the existing headless ones
  • Add Accordion component for Mob
  • Add ActionIcon component for Mob
  • Add AlertDialog component for Mob
  • Add AlphaSlider component for Mob
  • Add Anchor component for Mob
  • Add AngleSlider component for Mob
  • Add Autocomplete component for Mob
  • Add Avatar component for Mob
  • Add Burger component for Mob
  • Add Checkbox component for Mob
  • Add CheckboxGroup component for Mob
  • Add Chip component for Mob
  • Add CloseButton component for Mob
  • Add Code component for Mob
  • Add Collapsible component for Mob
  • Add ColorInput component for Mob
  • Add ColorPicker component for Mob
  • Add ColorSwatch component for Mob
  • Add Combobox component for Mob
  • Add ContextMenu component for Mob
  • Add Dialog component for Mob
  • Add Drawer component for Mob
  • Add EmptyState component for Mob
  • Add Field component for Mob
  • Add Fieldset component for Mob
  • Add FloatingIndicator component for Mob
  • Add FloatingWindow component for Mob
  • Add Highlight component for Mob
  • Add HueSlider component for Mob
  • Add JsonInput component for Mob
  • Add LoadingOverlay component for Mob
  • Add Mark component for Mob
  • Add Marquee component for Mob
  • Add MaskInput component for Mob
  • Add Menu component for Mob
  • Add Menubar component for Mob
  • Add Meter component for Mob
  • Add NavLink component for Mob
  • Add NavigationMenu component for Mob
  • Add NumberField component for Mob
  • Add NumberFormatter component for Mob
  • Add OtpField component for Mob
  • Add OverflowList component for Mob
  • Add Pill component for Mob
  • Add PillsInput component for Mob
  • Add Popover component for Mob
  • Add PreviewCard component for Mob
  • Add Progress component for Mob
  • Add Radio component for Mob
  • Add RadioGroup component for Mob
  • Add RollingNumber component for Mob
  • Add ScrollArea component for Mob
  • Add Scroller component for Mob
  • Add SegmentedControl component for Mob
  • Add Select component for Mob
  • Add SemiCircleProgress component for Mob
  • Add Separator component for Mob
  • Add Skeleton component for Mob
  • Add Slider component for Mob
  • Add Splitter component for Mob
  • Add Spoiler component for Mob
  • Add Switch component for Mob
  • Add Tabs component for Mob
  • Add TagsInput component for Mob
  • Add ThemeIcon component for Mob
  • Add Toast component for Mob
  • Add Toggle component for Mob
  • Add ToggleGroup component for Mob
  • Add Toolbar component for Mob
  • Add Tooltip component for Mob
  • Add Tree component for Mob
  • Add TreeSelect component for Mob
  • Add VisuallyHidden component for Mob

Refactors:

  • Refactor the --cms export example pipeline into CmsBundle.{DocExamples, DocsPage, Examples, Sanitize}, harvesting from each function's @doc fences and the docs pages' code_string/1 snippets rather than the demo markup
  • Update phoenix_live_view to 1.2.7 Commit
  • Point doc_url at mishka.tools and preserve the specification URLs under spec_url Commit
  • Add the Headless section to the README Commit
  • Tighten all 116 usage rules, fix the Kit doc, bump versions and add the v0.0.9 roadmap Commit
  • Shorten every usage rule Commit
  • Generated components pass mix credo --strict: the --import macro carries a @moduledoc and lists its imports as {module, opts} entries in imports/0 instead of one long quote block (mix mishka.ui.uninstall edits both this shape and the older one), and the styled and headless templates credo flagged are refactored without changing their rendered markup

Bugs:

  • Fix missing component_prefix in components Commit
  • Fix Tabs not showing a pointer cursor on hover over tab triggers #491
  • Fix avatar not forwarding standard img attributes (alt, srcset, loading, width…) via :global include Commit
  • Fix Elixir 1.20 type-checker warnings in stepper and table_content Commit
  • Fix dev harness headless CSS copy drifting from the priv source Commit
  • Fix --cms export shipping no examples for 53 of 136 components: the form components' docs pages were never vendored, nested-only components (card_title, td, progress_section…) were skipped by the extractor, and the literal-only filter discarded every snippet that referenced a demo assign (pagination harvested 111 examples and shipped 0)
  • Fix DemoHarness not passing extra.clauses, extra.prelude and extra.module_attributes to the component compiler, so every multi-clause component was compiled from its first clause only and guarded clauses were never exercised
  • Fix component compiler dropping multi-clause guards, which made all nine form-field components raise FunctionClauseError on render with their default floating value
  • Fix file_field dropzone never opening the file picker: live_file_input/1 identifies its input by the upload ref and ignores a caller id, so the label's for resolved to nothing and the label lost its control entirely. The label now points at @upload.ref, the caller's id moves to the wrapper, and the previously undeclared upload attribute is declared #496

Changelog for MishkaChelekom 0.0.9

Features:

  • Add Components prefix name in CLI and config file #454
  • Add Module prefix name in CLI and config file #459
  • Add --no-save flag to control prefix config saving #459
  • Add Usage rules for all components and JS Hooks #461
  • Add uninstall Mix task and its tests #464
  • Add Entry-level MCP for Mishka Chelekom components, docs and CLIs #466
  • Add server push event for Combobox component Issue with help
  • Add Disabled State, Half-Star Precision, Form integration into rating component Issue with help
  • Add dock (bottom-navigation) component Issue with help
  • Add Shape component
  • Add Stat component
  • Add harness demo driven kit test for dynamic CMS generator (Private APIs) #479
  • Add stdio transport + mix mishka.mcp.setup --stdio Issue with help
  • Add entry-level headless components ported from Base UI for Phoenix #489
  • Add creatable option support to Combobox component Commit
  • Add scrollable trigger list (scroll_area) for Tabs in vertical orientation Issue with help
  • Add --headless flag to mix mishka.ui.uninstall and make --all remove both styled and headless components
  • Add MishkaChelekom.Kit — a Spark DSL (customize/from) to reuse and restyle existing styled and headless components without editing their files
  • Add mix mishka.ui.gen.kit to vendor the Kit engine into your app (self-contained catalog + spark dep), so the Kit works in production with no mishka_chelekom runtime dependency

Refactors:

  • Refactor accordion to auto-generate item IDs (Explicit and open dynamic identifiers) Commit and Issue with help
  • Change :class attr type from :string to :any in components Commit
  • Refactor server-render active state so it works on static mount and reacts to assign changes Issue with help - Issue with help
  • Refactor generators and asset handling for the headless CLI, with unified per-command banners and improved headless CSS import Commit
  • Bump minimum Elixir to 1.18 and add compile-time JSON/Jason fallback Commit
  • Refactor uninstall to restore CoreComponents import #465
  • Center the banner subtitle and give every mix task its own title
  • Add a consistent Owl loading spinner to every Igniter mix task (export, gen.component, gen.headless, gen.kit, css.config, assets.deps, mcp.setup)

Bugs:

  • Remove stopPropagation from Floating hook to allow phx-click event bubbling Commit and Issue with help
  • Fix menu sub_items and sidebar hide_position crashes Issue with help
  • Use native browser date picker icons and remove custom calendar icon Issue with help
  • Fix Misplaced dropdown when content has min-width Issue with help
  • Fix some missing lables conditions #469
  • Fix CSS typos, wrong border classes, swapped docs, and Gettext template bug #468
  • Delete dead label code from fieldset component
  • Fix readd floating content back to original parent before update#475
  • Fix MCP runtime error Commit
  • Update and fix version conflict with other Mishka Project Commit
  • Fix Only use Owl.Spinner when TTY available #477
  • Fix dropdown content slot class attribute concatenation Commit
  • Fix Combobox field attribute not sending values to form params Commit
  • Fix Elixir 1.19 and not ... in ... deprecation warnings Commit
  • Fix false cross-kind dependency warning when uninstalling a headless component that shares a name with a styled one
  • Fix uninstall --all component discovery for path and umbrella dependencies
  • Fix :owl application not started before the spinner in mix mishka.ui.gen.headless.components
  • Fix active mode of Outline Radio Card and Checkbox Card #488 #481
  • Fix show_checkbox prop not applying in Checkbox Card and Radio Card #487
  • Fix component colors and gradients across form and menu components, including form_wrapper default variant/color/border and mega_menu gradient rendering #485
  • Align component catalog (.exs) variant and color lists with their implementations (unbordered→bordered, gradeint→gradient, corrupted color token, missing table/tabs variants) Commit
  • Fix Combobox dropdown color not matching the selected variant/color and theme the option highlight to follow the chosen color Commit
  • Migrate remaining Tailwind v3 utilities to v4 (video track captions, opacity, flex-shrink) #486
  • Fix color_field circle option having no effect and migrate it to Tailwind v4 #483

Tests:

  • Add retire-js and semgrep security scanning #460
  • Add Elixir 1.20.2 (OTP 29) to the CI test matrix Commit
  • Add direct end-to-end tests for every mix command in the development harness

Changelog for MishkaChelekom 0.0.8

Refactors:

  • Update to Tailwind 4 phoenix 1.8 and new cli options for 0.0.8 #439
  • Update dependencies
  • Update IgniterJS source #40
  • Update IgniterCss (but not using in this version, still we have some problems) #14
  • Improve floating.js to accept update request and better UX
  • Refactor Tooltip and Popover components
  • Refactor Combobox component

Features:

  • Add mix mishka.ui.css.config
  • Add CSS file to have all components colors and another configs
  • Add Config file to override default configs (for example custom css)
  • Add simple CSS utilities helper and delete IgniterCss for this version
  • Add exclude components option for mix mishka.ui.gen.components
  • Add Collapse component
  • Add Collapsible JS Hook
  • Add Github action for testing

Tests:

Bugs:

  • Fix some bugs of mix mishka.ui.add and mix mishka.ui.export
  • Fix some problems of new changes of Phoenix and LiveView
  • Fix typos
  • Fix Owl error conflict version with Ash generator Discord
  • Fix duplicated IDs in dropdown component
  • Fix installation issues of Ash Igniter

Changelog for MishkaChelekom 0.0.7

Refactors:

  • Flash group restriction for Phoenix version 1.8 #424

Changelog for MishkaChelekom 0.0.6

Features:

Bugs:

  • Add temporary patch for fixing Phoenix 1.8 Flash group

Changelog for MishkaChelekom 0.0.5

Features:

  • Add layouts flex and grid components #330
  • Add filterable gallery to the Gallery component #332
  • Add Circular and Semicircle Progress bar to progress component #333
  • Add support for fractional values to the rating component #334
  • Add tooltip to progress section #335
  • Add Clipboard component and hook integration #337
  • Add ability to to Minimize and Maximize Sidebar #339
  • Adding basic accessibility support to all components

Refactors:

  • Fix Dropdown Bugs and Enhance Dynamic Behavior #328
  • Add conditional styling to divider and buttons #329
  • Add Custom Hook, Loading State, and Bug Fixes of Carousel Component #336
  • Replace custom icon functions with shared icon component #338
  • Implement Toast and Alert components to support z-index prop #399
  • Update Igniter to last version

Changelog for MishkaChelekom 0.0.4

Bugs:

  • Fix Stepper icon display issue #338

Features:

  • Add on_select attribute on tab slot
  • Add scroll area component #296 #300
  • Add missing features of Phoenix core components #296
  • Add global components installing support and JS formatter #304
  • Add radio card component #305
  • Add checkbox card component #306
  • Add combobox component #321

Bugs:

  • Add missing slot to gallery component #294
  • fix typo in tab, checkbox field, radio field components #295
  • Fix missing ids in table and Flash assign_new to create new id from pattern #313
  • Fix color and variants functions of stepper component #338

Refactors:

  • Refactor some Phoenix CoreComponent backward compatibility issues for Ash #312
  • Refactor and Use more generous dependency on igniter #317
  • Reset line height of alert #320
  • Skipping Color in the Base Variant #322
  • Fix color of radio and checkbox fields #324

Changelog for MishkaChelekom 0.0.3

Features:

  • Support JS community cli version (beta) #254
  • Support Export community cli version (beta) #256
  • Add paddings and width fit to alert #287
  • Add badge to tab component #290
  • Add Igniter installer mix task

Bugs:

  • Fix alert title type #288
  • Fix some issues about windows PowerShell

Changelog for MishkaChelekom 0.0.2

Features:

  • Support community cli version (beta) #92
  • Supports cli helpers import #93
  • Update all templates for new syntax {} (Phoenix LiveView 1.0.0)

Refactors:

  • Fix Adjust spacing for checkbox and radio fields #73
  • Add dark mode and fix issues of gradient variants of Button component #91
  • Add dark mode and fix issues of gradient variants of Badge component #94
  • Add dark mode and fix issues of Overlay of Drawer component #96
  • Add dark mode of Divider component #97
  • Add dark mode of Avatar component #98
  • Add dark mode of Alert component #99
  • Add dark mode of Spinner component #100
  • Add dark mode of Banner component #101
  • Add dark mode of Breadcrumb component #102
  • Add dark mode of Blockquote component #103
  • Add dark mode of Dropdown component #104
  • Add dark mode of Overlay component #106
  • Add dark mode of Card component #107
  • Add dark mode and add show_arrow prop of Popover component #121
  • Add dark mode of Rating component #123
  • Add dark mode of Chat component #125
  • Add dark mode of Modal component #126
  • Add dark mode of Keyboard component #127
  • Add dark mode of Jumbotron component #128
  • Add dark mode of Indicator component #129
  • Add dark mode of Carousel component #130
  • Add dark mode of Footer component #132
  • Add dark mode of MegaMenu component #133
  • Add dark mode of Navbar component #134
  • Add dark mode of Progress component #136
  • Add dark mode of email, url, search, number, password, textarea, tel, text fields components #138
  • Add dark mode of FormWrapper component #140
  • Add dark mode of RadioField component #143
  • Add dark mode of CheckboxField component #144
  • Add dark mode of Sidebar component #145
  • Add dark mode of DateTimeField component #146
  • Add dark mode of Tooltip component #147
  • Add dark mode of Video component #148
  • Add dark mode of Typography component #149
  • Add dark mode of ToggleField component #150
  • Add dark mode of SpeedDial component #151
  • Add dark mode of Skeleton component #152
  • Add dark mode of TableOfContent component #153
  • Add dark mode of Timeline component #154
  • Add dark mode of Table component #155
  • Add dark mode of Tabs component #156
  • Add dark mode of NativeSelect component #158
  • Add dark mode of RangeField component #159
  • Add dark mode of Toast component #160
  • Add dark mode of List component #161
  • Add dark mode of Fieldset component #162
  • Add dark mode of FileField component #163
  • Add dark mode of Stepper component #165
  • Add dark mode of Accordion component #166
  • Add dark mode of DeviceMockup component #167
  • Add dark mode of pagination component #168
  • Add full width to button #170
  • Add filter props to image component #171
  • Add other line styles to timeline #172
  • Add loader to slot to button component #173
  • Add radius to toggle component #174
  • Add space based on sizes to pagination component #175
  • Add label slot to each chunk of progress #176
  • Add separated variant to table #178
  • Refactor: Fix issue of zooming inputs #185
  • Modify structure of popover and dropdown components #189
  • Add animations to gallery #190
  • Stop spinner when an image is in done #194
  • Modify styles of form fields, add new prop to badge #192
  • Modify card and overlay components styles #193
  • Modify table content component #195
  • Add variant to stepper, add loading state to stepper #196
  • add hoverable prop to listdd #197
  • Add classes to badge #257
  • Add new styles to tabs #273
  • change structure of tooltip #277
  • Add and remove unnecessary classes textarea field #276
  • Add and remove unnecessary classes text field #275
  • Add and remove unnecessary classes tel field #274
  • Add new variants to table #272
  • Change styles in stepper #271
  • Add and remove unnecessary classes of search #270
  • Add line height class to rating button #269
  • Change styles of progress #268
  • Change structure of popover #267
  • Add and remove unnecessary classes number field #265
  • Add new props and fix color issues, remove extra functions from list #263
  • Add and remove unnecessary classes from email field #261
  • Add and remove unnecessary classes from date field #260
  • change chat section styles #259
  • Add new prop to card media #258

Bugs:

  • Fix un-CSP progress mounted #72
  • Fix modal title default: nil value #76
  • Correct typo separated across the project #81
  • Revision and fix some missing part of some fields (version 0.0.1) #84
  • Fix without --import option error of components task CLI b0b7492
  • Fix issue of breadcrumb RTL mode #170
  • Remove space-y-0 classes from Menu, Footer, Navbar, Tooltip components #183
  • Delete none pattern functions from all components #246
  • Fix issues of password field #266
  • Fix issues of shadow in native select #264
  • Fix style issues of fieldset #262
  • Fix some global issues

Changelog for MishkaChelekom 0.0.1

We are delighted to introduce our new version of MishkaChelekom fully featured components and UI kit library for Phoenix & Phoenix LiveView. Kindly ensure that the MishkaChelekom Library is updated as quickly as feasible.

For more information please see: https://mishka.tools/chelekom

Features:

  • Add generator mix CLI task for creating component

  • Add generator mix CLI task for creating components

  • Add basic components (light mode version)

    <details>

    <summary>Components list</summary>

    • [x] accordion
    • [x] alert
    • [x] avatar
    • [x] badge
    • [x] banner
    • [x] blockquote
    • [x] breadcrumb
    • [x] button
    • [x] card
    • [x] carousel
    • [x] chat
    • [x] chekbox_field
    • [x] color_field
    • [x] date_time_field
    • [x] device_mockup
    • [x] divider
    • [x] drawer
    • [x] dropdown
    • [x] email_field
    • [x] fieldset
    • [x] file_field
    • [x] footer
    • [x] form_wrapper
    • [x] gallery
    • [x] image
    • [x] indicator
    • [x] input_field
    • [x] jumbotron
    • [x] keyboard
    • [x] list
    • [x] mega_menu
    • [x] menu
    • [x] modal
    • [x] native_select
    • [x] navbar
    • [x] number_field
    • [x] overlay
    • [x] pagination
    • [x] password_field
    • [x] popover
    • [x] progress
    • [x] radio_field
    • [x] range_field
    • [x] rating
    • [x] search_field
    • [x] sidebar
    • [x] skeleton
    • [x] speed_dial
    • [x] spinner
    • [x] stepper
    • [x] table
    • [x] table_content
    • [x] tabs
    • [x] tel_field
    • [x] text_field
    • [x] textarea_field
    • [x] timeline
    • [x] toast
    • [x] toggle_field
    • [x] tooltip
    • [x] typography
    • [x] url_field
    • [x] video

    </details>

  • Add white primary secondary dark success warning danger info light misc dawn colors

  • Add common sizes

  • Add common variants

  • Add common positions

Docs

  • Add generator docs
  • Add basic components docs