Skip to content

Roadmap โ€‹

The component list is taken from Element Plus as a checklist of what an admin panel needs. Every component is implemented in-house; the library in brackets is what the behaviour leans on.

Legend: โœ… done ยท ๐Ÿšง in progress ยท โฌœ planned

Wave 1 โ€” basics โ€‹

Complete: every component below has a demo, tests and a page it is documented on โ€” the four typographic ones share Typography, since a page each would be four pages of the same paragraph.

ComponentStatus
Buttonโœ…
ButtonGroupโœ…
Iconโœ…
Inputโœ…
Textareaโœ…
InputNumberโœ…
Select (Reka Combobox)โœ…
Checkbox, CheckboxGroupโœ…
Radio, RadioGroupโœ…
Switchโœ…
Form, FormItemโœ…
Cardโœ…
Tag (as Badge)โœ…
TagsInputโœ…
Badge (count: Indicator)โœ…
Alertโœ…
Dividerโœ…
Layout (Container, Header, Aside, Main, Footer)โœ…
Grid (Row, Col)โœ…
Spaceโœ…
Tabs (Reka)โœ…
Menu / Sidebarโœ…
Breadcrumbโœ…
Linkโœ…
Text, Heading, Proseโœ…
Scrollbarโœ…

Wave 2 โ€” data and overlays โ€‹

Complete. Two notes on where this list stopped matching the one it was copied from:

  • Message and Notification are one component. The difference between them is a title and a corner, so both are Toast โ€” one queue, one WxToaster, a placement.
  • Upload is ours, rather than a wrapper around Uppy or FilePond. Those bring their own UI and their own theme, which is the one thing this library does not do; and since a component here never calls an API, there was no request logic to inherit either.
ComponentStatus
Table (Laravel Paginated)โœ…
Paginationโœ…
Dialog (Reka)โœ…
Drawer (Reka)โœ…
Dropdown (Reka)โœ…
Tooltipโœ…
Popover (Reka)โœ…
Popconfirmโœ…
Message (one line, Toast)โœ…
Notification / Toast (Reka)โœ…
Loadingโœ…
Skeletonโœ…
Emptyโœ…
Resultโœ…
Progressโœ…
Descriptionsโœ…
Avatarโœ…
Imageโœ…
Upload (ours)โœ…
DatePicker, TimePicker, DateTimePicker (@vuepic/vue-datepicker)โœ…
DateRangePickerโœ…
Stepsโœ…
Collapse (as Accordion)โœ…
Segmentedโœ…
Statistic, Countdownโœ…
Backtopโœ…
Affixโœ…

Wave 3 โ€” as needed โ€‹

ColorPicker โœ…, Slider โœ…, Rate โœ…, Autocomplete โœ…, Cascader โœ…, Timeline โœ… and Transfer โœ… are done.

Tree โœ… โ€” ours rather than he-tree-vue, because a drop is three zones on a row and a <mark> in a label, and neither survives being themed through somebody else's CSS. It brings the part most trees skip: Alt and the arrow keys move a node the same four ways a drag does, which is also the only way to rearrange one on a touch screen.

Table in tree mode โœ… โ€” the same nesting inside WxTable: indentation and a disclosure in the first column, the rest of the row still columns. Not a second component โ€” both run on useTreeNodes, so a drop means the same thing in each. It is the screen a pages or categories module wants: the tree and the data in one pane, instead of a sidebar tree beside a list of the same records.

It is lazy by design โ€” data is the roots, load(row) is one level โ€” and it gives up the two things a table does to a flat list, because both destroy a structure: sorting and pagination. Holding a dragged row over a closed branch opens it, fetching it if need be, so a move across the tree is one drag. What it does not have is a keyboard equivalent for the drag, the way Tree does; for that, and for a move across a long distance, a row wants a Move action and a picker.

TreeSelect โœ… โ€” the same tree as a form field, single or with checkboxes. It is the "parent category" field, so it reads a key and reports a key: parent_id is what the form sends, and the node comes along with the event for whatever the screen needs to show.

Still open: Carousel, Anchor, Splitter, Watermark, Marquee.

Some day, maybe โ€” wanted, but nothing is waiting on them:

  • Mention โ€” the @name picker inside a text field.

Dropped, so that the list stays a list of things somebody is going to write:

  • Calendar โ€” a month of boxes to pick a date out of is what DatePicker already does, and does with a keyboard. What a calendar would add is a month of events, which is a scheduler and a different component with a different name.
  • Tour โ€” the step-by-step walk over a screen. An admin panel earns its explanations in the screen itself; when one truly needs a tour, that is a sign to go back to the screen.

CMS-specific (not in Element Plus) โ€‹

RichText (Tiptap) โœ… โ€” see RichText. It edits one language at a time under localized, its toolbar takes its words as props, and a picture it takes from a library carries that library's key into the document rather than an address that will not survive the next deployment. On a screen it is wx-rich-text, from module-admin โ€” see Screens. CodeEditor (CodeMirror 6) โœ… โ€” the same field for code: JSON with a linter, HTML, CSS, PHP, YAML and the rest, see CodeEditor. The screens mechanism needs its patches written somewhere better than a textarea. IconPicker โœ… โ€” the icon set, picked from rather than typed into, see IconPicker. A name the set does not have draws nothing and says nothing, so anywhere an editor names an icon โ€” a block type, a menu entry โ€” the name has to come out of the set rather than out of a keyboard. EntityCard โœ… โ€” one record as a row, see EntityCard. Actions โœ… โ€” the icon buttons at the end of a row, see Actions. ActionBar โœ… โ€” the same screen's buttons along the bottom of it, see Layout. A panel's screens scroll natively, so the head goes with the scroll and takes the save button with it; the bar is where the button waits. Kanban โœ… โ€” a board of columns cards are dragged between, see Kanban. ListDetail โœ… โ€” filters, records, the open one, and the rule for when there is room for all three: see ListDetail. An inbox and an orders screen are the same furniture.

SelectionArea โœ… โ€” the rubber band over a grid or a list, see SelectionArea. A media library is unusable without it.

FileCard โœ… โ€” one file in that library: a preview or a glyph, the name, and the few things that can be done to it, see FileCard. It does none of them โ€” renaming reports a name, deleting reports a wish โ€” so the same card sits in a library, in a picker and in a form field. The icon set gained a file-<extension> family to go with it, and an extension nobody has drawn gets the plain page with its own name written underneath.

ImageEditor โœ… โ€” what the card's edit action asks for: a crop with the eight grips everybody knows, aspect ratios, quarter turns, mirrorings, an output size, and a blob at the end of it. See ImageEditor. It is deliberately not folded into the card, which is a tile and should stay one โ€” the card asks, openImageEditor() answers.

It uploads nothing, the way nothing here does: the answer is a blob, its measurements and the crop it was cut from, so the same editor crops an avatar before a form is submitted and re-cuts a file that is already in a library. Everything on screen is geometry, and the picture is drawn exactly once โ€” at the end, under one transform โ€” because a chain of canvases softens a photograph at every link.

SortableList โœ… โ€” a list whose order is the point, dragged by a grip or moved with the arrow keys: see SortableList.

Repeater โœ… โ€” the same list once every row is a form: a set of fields, repeated, in an order that is part of the answer. See Repeater. It is SortableList underneath, with the two things a form needs on top โ€” rows that fold to a name taken from their own fields, and a key of its own per row, so writing a field, removing the row above or dragging one elsewhere never rebuilds the form under the caret. In a described screen it is wx-repeater, the one type whose model is nested.

Gantt โฌœ โ€” the other way to look at the same work: a task per row, a bar across a timeline. Decided, not started. It will be ours rather than a wrapper around frappe-gantt or vis-timeline, because a Gantt is a header of dates and bars placed along it โ€” a CSS grid, in other words โ€” and a wrapper would mean styling somebody else's SVG through their theme instead of our tokens, which is the one thing this library does not do. The first pass reads: a sticky column of task names, a scale of days, weeks or months, bars with progress, a marker on today, and hovering or clicking a bar reported as an event. Dragging the dates and the arrows between dependent tasks come after that, once the first pass has been lived with.

MediaLibrary / Gallery โœ… โ€” the library itself, and the fields that reach into it: wx-media for one picture, wx-gallery for a grid of them in an order somebody dragged them into, wx-file and wx-files for documents. See Media fields. Markdown, LinkPicker and BlockPicker are still open.

Not components โ€‹

Two things here are reached from code rather than from a template, and are easy to miss in a list of components:

  • Toast โ€” toast.success('Saved') from anywhere, including an HTTP interceptor or a store, with one WxToaster on the page to show them.
  • Dialogs from code โ€” confirm(), and openModal / createModal for mounting any component and awaiting its answer. A picker reached as await productBrowser().

Beyond components โ€‹

  1. @webx-ui/adapter-laravel โ€” paginator, 422 validation errors, sort/filter query parameters.
  2. CMS building blocks on top of core: the panel's sections, each a pair of packages โ€” the file manager, administrators, settings, SEO, the block constructor and, newest, pages โ€” the first entity that puts the tree, the address registry, the blocks, the drafts and the SEO card together on something real. Each of them is also a set of MCP tools, so an agent reaches the panel through the same doors an editor does.
  3. An in-admin component editor: fields defined as JSON plus a Blade template and CSS, generated into files by Laravel.

Released under the MIT License.