Repository navigation
Replies: 1 comment
|
The important idea is that
The primitive should not know about the domain meaning of the values. A possible structure: Select
├── SelectTrigger
└── SelectContent
├── SelectGroup
│ ├── SelectLabel
│ └── SelectItem
└── SelectItemSimilar to shadcn/ui, composition should be preferred over configuration. For example: Select::new(state)
.trigger(
SelectTrigger::new()
.placeholder("Select timezone")
)
.content(
SelectContent::new()
.group(
SelectGroup::new("Asia")
.item("China Standard Time")
.item("Japan Standard Time")
)
)The primitive
The events should be semantic: SelectEvent::Change {
value: T
}
SelectEvent::Open
SelectEvent::Close
SelectEvent::Focus
SelectEvent::BlurIt should not expose: KeyDown
MouseMove
ClickedItemIndexbecause these are GPUI implementation details. For example, the timezone selector from the desktop settings should not be implemented by adding timezone-specific options into This keeps |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
UI Design Principles for Primitive Components
Motivation
As Chitin evolves into an AI-native scientific computing platform, the UI layer needs to remain maintainable and extensible across different domains, including computational chemistry, bioinformatics, materials science, and future workflow-driven applications.
Primitive UI components are the foundation of the entire UI system. Components such as
Button,TextInput,Select,Checkbox, andNumberInputwill be reused throughout the application and will become long-lived APIs.This discussion proposes design principles for primitive components to keep the UI architecture stable, composable, and easy to extend.
Core Principle
Primitive components should own interaction behavior, while appearance should remain customizable.
Primitive components should provide reliable behavior and semantic events. Composite components and applications should control composition, layout, and domain-specific meaning.
1. Primitive Components Own Interaction Behavior
Primitive components should encapsulate their own interaction logic, internal state, and semantic events.
For example,
TextInputshould own:Buttonshould own:Users of these components should not need to handle raw GPUI events such as keyboard or mouse events to implement normal behavior.
For example, consumers should react to semantic events such as:
rather than interpreting low-level events themselves. And composite components should use
cx.subscribeto subscribe and react to the events.
Raw GPUI events are implementation details of primitive components.
2. Primitive APIs Should Remain Small and Stable
Primitive components should avoid accumulating scenario-specific configuration flags.
Avoid designs like:
or:
These usually indicate that the component boundary is incorrect.
Instead, specialized use cases should be implemented through composition.
For example, a window control button should be a composite component built using the
Buttonprimitive, rather than adding window-specific behavior intoButton.3. Appearance Should Be Customizable Through Styles
Primitive components should provide predefined theme-based styles for common cases.
Examples:
PrimarySecondaryTransparentand predefined sizes:
SmallMediumLargeHowever, users should also be able to provide custom styles when needed.
For example:
Styles should control appearance only:
Styles should not change component behavior.
4. State and Events Belong to Primitive Components
Primitive components should own their interaction state.
For example:
TextInputStatemay contain:The state should be the source of truth for the component.
Events should describe semantic changes caused by user interaction.
Examples:
Events should not expose implementation details such as:
5. Focus Should Be a Shared Capability
Focus management is a common behavior across many interactive components.
Components such as:
ButtonTextInputSelectTreeViewEditorshould share a common focus abstraction.
However, focus behavior and focus appearance should remain separate.
A component may support focus behavior but choose a different visual representation.
For example:
This difference should be represented through styling rather than additional boolean flags.
6. Primitive Components Should Be Domain-Agnostic
Primitive components should not contain scientific or application-specific concepts.
Examples that do not belong in primitive UI:
ProteinSequenceInputTemperatureInputMoleculeSelectorSimulationParameterEditorThese should be composite or domain-level components built on top of primitives.
For example:
TemperatureInputcan be built usingNumberInput, adding:while
NumberInputonly provides numeric editing behavior.7. Prefer Composition Over Configuration
When a primitive component accumulates many options, it usually means a composite component should be introduced.
Prefer creating:
SearchBoxbuilt fromTextInputCommandPaletteInputbuilt fromTextInputWindowControlButtonbuilt fromButtoninstead of continuously extending the primitive API.
Composition keeps primitives reusable and prevents API growth from becoming unmanageable.
8. Long-Term Goal
Primitive components should form a small, stable foundation for building complex interfaces.
Their responsibilities should remain limited:
This separation allows Chitin UI to support complex scientific workflows while keeping the underlying component system maintainable over the long term.
All reactions