Solid Headless Versions Save

Headless UI for SolidJS

v0.13.0

1 year ago

Warning This release is a breaking change

v0.12.2

1 year ago
  • Fixes #8 (Thanks to @vincentfretin!)

v0.12.1

1 year ago
  • Fixes focus navigation for most of the components that utilizes it (e.g. Accordion) to properly navigate to the next focusable element. Previously, focus navigation would naively focus on the first element of a given query without checking if it's focusable. The criteria used for checking is if the state data-sh-disabled is assigned to the element.

v0.12.0

1 year ago

image

  • This release adds the Tabs implementation for solid-headless. You can check out the demo here.
  • Drops the use of JSX
    • The code is manually written so that props are properly optimized and applies DRY much better. This also means that solid-headless can now be used without building the package.
    • For Vite SSR, solid-headless is no longer needed to be added for ssr.noExternal.
  • Deprecated the use of data-sh-*={ownerID}. Components are now accompanied with data-sh={tag}, this allows querying components properly as well as writing better selectors. Components that previously do not have those tags also now have their own tags. Example:
[data-sh="tab-group"] {
  width: 100%;
  display: flex;
  align-items: stretch;
  justify-content: center;
}
  • Fix some components not strictly following proper hierarchy.
  • Fix some components with mismatching default constructor vs type constructor.
  • Rework for controllable components
    • multiple is now static for HeadlessSelect-based components (RadioGroup, Listbox, Select, etc.)
    • Dirty check for controllable detection is removed for future proof.
    • Better type inference for controlled vs uncontrolled usage (e.g. Modal will now complain if either defaultOpen or isOpen isn't used)
  • Fix components with focus lock (e.g. Modal) now also resume focus to last focus start point if the last focused element is no longer available.

v0.11.0

1 year ago
  • This release adds the <ColorSchemeProvider>, usePreferredColorScheme, useNativeColorScheme and useColorScheme. This set of utilities allows automatic management of color scheme preferences by both the user and the device. This also synchronizes across pages and persists in the local storage. <ColorSchemeProvider> can also be either controlled and uncontrolled through the use of initialValue, value and onChange.

See docs for example usage.

image

v0.10.0

2 years ago

This release changes how stateful components behave in an uncontrolled and controlled way.

Uncontrolled vs Controlled components

Uncontrolled components are components whose state is managed by its own instance. These states are usually received through event listeners/properties (e.g. onChange) that allows you to perform side-effects derived from these states.

Controlled components are components whose state is managed by another component. This is akin to 2-way binding which allows you to read and write the state of that component (e.g. value and onChange).

solid-headless has a handful of stateful components and most of them allows controlled state. However, there was no distinction on how to manage these states and so internally it's sort of turned into "spaghetti code". This release involves a rework on how states are managed in the components by introducing uncontrolled and controlled components.

When a component detects that you use the controlling property (e.g. Accordion with value), it opts in to controlled behavior where it doesn't create its own state and relies on the user implementation of the state that will control the component. This also means that the user is required to provide a listener (e.g. onChange) to receive the state update. If the controlling property is not detected, the component becomes "uncontrolled" and thus creates its own state.

Here's an example with Dialog:

// Controlled
const [isOpen, setIsOpen] = createSignal(true);

// The controlling property for `Dialog` is `isOpen`.
<Dialog isOpen={isOpen()} onChange={setIsOpen}>
  {children}
</Dialog>
// Uncontrolled

// `defaultOpen` provides the initial state.
<Dialog defaultOpen>
  {children}
</Dialog>

When managing initial states, uncontrolled components uses the initializing property (Dialog's defaultOpen) for initializing it's state. Controlled components must manage its initial state on its own since the initializing property will be ignored.

Check each component for further details.

Headless Components

HeadlessDisclosure

  • Change isOpen to become the controlling property. defaultOpen now defines the initial state when uncontrolled.

HeadlessSelect

  • Added defaultValue.
  • When multiple is set to true, value, defaultValue and onChange will use an array state instead of a value state.

HeadlessToggle

  • Change checked to become the controlling property.defaultChecked now defines the initial state when uncontrolled.

DOM Components

Accordion

  • Changes reflected from HeadlessSelect

AlertDialog

  • Added onOpen event.
  • Changes reflected from HeadlessDisclosure

Checkbox

  • Changes reflected from HeadlessToggle

ContextMenu

  • Added onOpen and onClose events. (Just to make it consistent with other Dialog-based components).
  • Changes reflected from HeadlessDisclosure.

Dialog

  • Added onOpen event.
  • Changes reflected from HeadlessDisclosure.

Disclosure

  • Changes reflected from HeadlessDisclosure.

Listbox

  • onSelectChange mimics the onChange event from HeadlessSelect (Uses array state when multiple is set to true.).
  • Changes reflected from HeadlessDisclosure and HeadlessSelect.

Popover

  • Added onOpen and onClose events. (Just to make it consistent with other Dialog-based components).
  • Changes reflected from HeadlessDisclosure.

RadioGroup

  • Changes reflected from HeadlessSelect.

Select

  • Changes reflected from HeadlessSelect.

CommandBar

Example

** Demo only. CommandBar is unstyled.

This release introduces the CommandBar aka kbar, a Dialog-like component for displaying dialogs through Cmd + K or Ctrl + K keyboard shortcuts. The feature introduces the same structure as a Dialog component (a root component, Panel, Title, Overlay and Description). Search component and command bar layout is up to the user implementation.

You can try the demo here.

Other news

I've now started working on the docs site for solid-headless although I don't see it getting launched up until the end of this year, but surely it would be already around once v1.0.0 is released 😅

v0.9.0

2 years ago
  • This release changes the bundle output of solid-headless. Previously, solid-headless is loaded in a single entrypoint for both ESM and CJS, however this proved problematic for runtimes that don't have process.env.NODE_ENV. This release removes those entrypoints, ESM now mimics CJS (it now has prod and dev bundles) and export maps now supports prod/dev conditions.

v0.8.0

2 years ago

This release introduces some breaking changes!

  • Tailwind prefix has been dropped.
  • Toaster class has been renamed to ToasterStore.
  • Adds Menu, ContextMenu (kind of Disclosure) and Feed.
  • Adds data-sh-disabled, data-sh-expanded, data-sh-active, data-sh-checked and data-sh-pressed properties.
  • Fixes Popover toggle conflict when clicking PopoverButton
  • Adds proper ref handling internally.

v0.7.0

2 years ago
  • Add HeadlessToggle.
  • Add TailwindAlert
  • Add TailwindAlertDialog
  • Add TailwindToaster, TailwindToast and Toaster
  • Add TailwindCheckbox
  • Drop outside-click mechanism for Popover, Dialog and Listbox.
  • Add TailwindDialogOverlay.
  • Add TailwindPopoverOverlay.
  • Remove enterDuration and leaveDuration from Transition
  • Remove state and render prop from Transition
  • Add beforeLeave, afterLeave, beforeEnter and afterEnter for Transition

v0.6.0

2 years ago
  • Add TailwindPopover, a TailwindDisclosure-like component with accessibility features similar to a TailwindDialog.
  • Fix focus navigation for Toolbar.
  • Fix focus navigation for Dialog.
  • Fix "click outside" behavior for Listbox when clicking on the ListboxButton.