React
LoadingLoading React…
No event yet
Early previewhamur is not on npm yet. The components are being built in the open, follow along on GitHub.
CompareInputs
The same example, live in each framework. One core underneath, so they should behave the same.
Loading React…
No event yet
Loading Vue…
No event yet
Loading Svelte…
No event yet
Loading Solid…
No event yet
Loading Angular…
No event yet
The attributes each framework puts on the open popup, read from the page.
| Attribute | React | Vue | Svelte | Solid | Angular |
|---|---|---|---|---|---|
role | Closed | Closed | Closed | Closed | Closed |
aria-modal | Closed | Closed | Closed | Closed | Closed |
aria-labelledby | Closed | Closed | Closed | Closed | Closed |
data-open | Closed | Closed | Closed | Closed | Closed |
Nothing open. Open a tile to fill its column.
Each tile sets modal to false, so five popups can be open at once; that is why aria-modal reads absent.
Each tile above runs this file.
import { Cascader } from '@hamur/react/cascader'
const labels: Record<string, string> = {
asia: 'Asia',
japan: 'Japan',
tokyo: 'Tokyo',
osaka: 'Osaka',
kyoto: 'Kyoto',
korea: 'Korea',
seoul: 'Seoul',
busan: 'Busan',
europe: 'Europe',
france: 'France',
paris: 'Paris',
lyon: 'Lyon',
germany: 'Germany',
berlin: 'Berlin',
munich: 'Munich',
americas: 'Americas',
canada: 'Canada',
toronto: 'Toronto',
vancouver: 'Vancouver',
brazil: 'Brazil',
'sao-paulo': 'São Paulo',
rio: 'Rio de Janeiro',
}
const children: Record<string, string[]> = {
asia: ['japan', 'korea'],
japan: ['tokyo', 'osaka', 'kyoto'],
korea: ['seoul', 'busan'],
europe: ['france', 'germany'],
france: ['paris', 'lyon'],
germany: ['berlin', 'munich'],
americas: ['canada', 'brazil'],
canada: ['toronto', 'vancouver'],
brazil: ['sao-paulo', 'rio'],
}
const roots = ['asia', 'europe', 'americas']
export default function CascaderExample() {
return (
<Cascader.Root
items={roots}
getItemChildren={(value: string) => children[value]}
itemToStringLabel={(value: string) => labels[value]}
>
<div className="field">
<Cascader.Label className="select-label">
Location
</Cascader.Label>
<div className="cascader-control">
<Cascader.Trigger className="select">
<Cascader.Value
className="select-value cascader-value"
placeholder="Choose a city"
/>
<Cascader.Icon className="select-icon" />
</Cascader.Trigger>
<Cascader.Clear className="cascader-clear" aria-label="Clear">
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
<path d="M4 4l8 8M12 4l-8 8" />
</svg>
</Cascader.Clear>
</div>
</div>
<Cascader.Portal>
<Cascader.Positioner className="select-positioner" sideOffset={6}>
<Cascader.Popup className="select-popup cascader-popup">
<Cascader.Columns className="cascader-columns" aria-label="Places">
{(column) => (
<Cascader.Column
key={column.level}
column={column}
className="cascader-column"
>
{(value: string) => (
<Cascader.Item
key={value}
value={value}
className="cascader-item"
>
<Cascader.ItemText className="cascader-item-text" />
<Cascader.ItemIndicator
className="cascader-item-indicator"
>
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
<path d="M3 8.5l3 3 7-7" />
</svg>
</Cascader.ItemIndicator>
<Cascader.ItemIcon className="cascader-item-icon">
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
<path d="M6 4l4 4-4 4" />
</svg>
</Cascader.ItemIcon>
</Cascader.Item>
)}
</Cascader.Column>
)}
</Cascader.Columns>
</Cascader.Popup>
</Cascader.Positioner>
</Cascader.Portal>
</Cascader.Root>
)
}
The frameworks against each other only, on the same machine and the same example.
| Framework | Tests | Size | Open | Close | Memory |
|---|---|---|---|---|---|
| React | Not measured yet | Not measured yet | Not measured yet | Not measured yet | Not measured yet |
| Vue | 349 | Not measured yet | Not measured yet | Not measured yet | Not measured yet |
| Svelte | 349 | Not measured yet | Not measured yet | Not measured yet | Not measured yet |
| Solid | 349 | Not measured yet | Not measured yet | Not measured yet | Not measured yet |
| Angular | 351 | Not measured yet | Not measured yet | Not measured yet | Not measured yet |
Size is the gzip of the component's entry with core and dom. Open, Close and Memory are medians in Chromium 156 on Apple M3 Max; Memory is what one open and close leaves on the heap. Tests are Cascader's passing tests in each framework's suites. [N] is a value not measured yet.
The Cascader.Root names in each framework's own syntax.
| Prop | React | Vue | Svelte | Solid | Angular |
|---|---|---|---|---|---|
| children | children | #default | children | children | ng-content |
| id | id | id | id | id | [id] |
| items | items | items | items | items | [items] |
| getItemChildren | getItemChildren | get-item-children | getItemChildren | getItemChildren | [getItemChildren] |
| value | value | value | value | value | [value] |
| defaultValue | defaultValue | default-value | defaultValue | defaultValue | [defaultValue] |
| onValueChangeevent | onValueChange | @value-change | onValueChange | onValueChange | (valueChange) |
| multiple | multiple | multiple | multiple | multiple | [multiple] |
| cascade | cascade | cascade | cascade | cascade | [cascade] |
| cascadeValue | cascadeValue | cascade-value | cascadeValue | cascadeValue | [cascadeValue] |
| disallowEmptySelection | disallowEmptySelection | disallow-empty-selection | disallowEmptySelection | disallowEmptySelection | [disallowEmptySelection] |
| allowParentSelection | allowParentSelection | allow-parent-selection | allowParentSelection | allowParentSelection | [allowParentSelection] |
| isItemSelectable | isItemSelectable | is-item-selectable | isItemSelectable | isItemSelectable | [isItemSelectable] |
| isItemDisabled | isItemDisabled | is-item-disabled | isItemDisabled | isItemDisabled | [isItemDisabled] |
| itemToStringLabel | itemToStringLabel | item-to-string-label | itemToStringLabel | itemToStringLabel | [itemToStringLabel] |
| itemToStringValue | itemToStringValue | item-to-string-value | itemToStringValue | itemToStringValue | [itemToStringValue] |
| isItemEqualToValue | isItemEqualToValue | is-item-equal-to-value | isItemEqualToValue | isItemEqualToValue | [isItemEqualToValue] |
| loadChildren | loadChildren | load-children | loadChildren | loadChildren | [loadChildren] |
| onLoadChildrenErrorevent | onLoadChildrenError | @load-children-error | onLoadChildrenError | onLoadChildrenError | (loadChildrenError) |
| highlightedValue | highlightedValue | highlighted-value | highlightedValue | highlightedValue | [highlightedValue] |
| onHighlightChangeevent | onHighlightChange | @highlight-change | onHighlightChange | onHighlightChange | (highlightChange) |
| onItemHighlightedevent | onItemHighlighted | @item-highlighted | onItemHighlighted | onItemHighlighted | — |
| expandOnHover | expandOnHover | expand-on-hover | expandOnHover | expandOnHover | [expandOnHover] |
| expandDelay | expandDelay | expand-delay | expandDelay | expandDelay | [expandDelay] |
| loopFocus | loopFocus | loop-focus | loopFocus | loopFocus | [loopFocus] |
| separator | separator | separator | separator | separator | [separator] |
| inputValue | inputValue | input-value | inputValue | inputValue | [inputValue] |
| defaultInputValue | defaultInputValue | default-input-value | defaultInputValue | defaultInputValue | [defaultInputValue] |
| onInputValueChangeevent | onInputValueChange | @input-value-change | onInputValueChange | onInputValueChange | (inputValueChange) |
| filter | filter | filter | filter | filter | [filter] |
| filteredItems | filteredItems | filtered-items | filteredItems | filteredItems | [filteredItems] |
| virtualized | virtualized | virtualized | virtualized | virtualized | [virtualized] |
| open | open | open | open | open | [open] |
| defaultOpen | defaultOpen | default-open | defaultOpen | defaultOpen | [defaultOpen] |
| onOpenChangeevent | onOpenChange | @open-change | onOpenChange | onOpenChange | (openChange) |
| onOpenChangeCompleteevent | onOpenChangeComplete | @open-change-complete | onOpenChangeComplete | onOpenChangeComplete | (openChangeComplete) |
| actionsRef | actionsRef | actions-ref | actionsRef | actionsRef | [actionsRef] |
| modal | modal | modal | modal | modal | [modal] |
| disabled | disabled | disabled | disabled | disabled | [disabled] |
| readOnly | readOnly | read-only | readOnly | readOnly | [readOnly] |
| required | required | required | required | required | [required] |
| name | name | name | name | name | [name] |
| form | form | form | form | form | [form] |
| inputRef | inputRef | input-ref | inputRef | inputRef | [inputRef] |
| labels | labels | labels | labels | labels | [labels] |