`:
+
+```rust
+div().id("my-element") // ElementId from &str
+div().id(42usize) // ElementId from usize
+div().id(ElementId::from(idx)) // Explicit
+```
+
+Without `.id()`, a div cannot receive mouse events or store state.
+
+## Accepted Types
+
+```rust
+impl Into
for &str // "my-id"
+impl Into for String // String::from("my-id")
+impl Into for usize // 0, 1, 2, ...
+impl Into for u64
+impl Into for SharedString
+```
+
+## Uniqueness Rules
+
+IDs must be unique within the same **stateful parent's scope** — not globally. GPUI builds a `GlobalElementId` by chaining parent IDs:
+
+```rust
+div().id("app").child(
+ div().id("list1").children(vec![
+ div().id(1usize).child("Item 1"), // GlobalId: ["app", "list1", 1]
+ div().id(2usize).child("Item 2"), // GlobalId: ["app", "list1", 2]
+ ])
+).child(
+ div().id("list2").children(vec![
+ div().id(1usize).child("Item 1"), // GlobalId: ["app", "list2", 1] — no conflict
+ ])
+)
+```
+
+Items in different parent scopes can reuse simple IDs (integers, short strings).
+
+## In Component Structs
+
+Components always store `id: ElementId` and pass it in `new()`:
+
+```rust
+#[derive(IntoElement)]
+pub struct Button {
+ id: ElementId,
+ base: Stateful,
+ // ...
+}
+
+impl Button {
+ pub fn new(id: impl Into
) -> Self {
+ let id = id.into();
+ Self {
+ id: id.clone(),
+ base: div().id(id), // id applied to base
+ // ...
+ }
+ }
+}
+
+impl RenderOnce for Button {
+ fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
+ self.base // already has .id() applied
+ .on_click(/* ... */)
+ }
+}
+```
+
+## Usage at Call Sites
+
+```rust
+// Use unique string IDs for named components
+Button::new("save-btn").label("Save")
+Button::new("cancel-btn").label("Cancel")
+
+// Use index-based IDs in lists
+for (i, item) in items.iter().enumerate() {
+ div().id(i) // unique within this parent
+}
+
+// Use descriptive IDs for debugging
+Input::new("search-input")
+Select::new("country-select")
+```
diff --git a/.agents/skills/gpui-kit/references/gpui/element-patterns.md b/.agents/skills/gpui-kit/references/gpui/element-patterns.md
new file mode 100644
index 0000000..31c9e2f
--- /dev/null
+++ b/.agents/skills/gpui-kit/references/gpui/element-patterns.md
@@ -0,0 +1,509 @@
+# Common Element Patterns
+
+**Contents:** [Text Rendering Elements](#text-rendering-elements) · [Container Elements](#container-elements) · [Interactive Elements](#interactive-elements) · [Composite Elements](#composite-elements) · [Scrollable Elements](#scrollable-elements) · [Pattern Selection Guide](#pattern-selection-guide)
+
+## Text Rendering Elements
+
+Elements that display and manipulate text content.
+
+### Pattern Characteristics
+
+- Use `StyledText` for text layout and rendering
+- Handle text selection in `paint` phase with hitbox interaction
+- Create hitboxes for text interaction in `prepaint`
+- Support text highlighting and custom styling via runs
+
+### Implementation Template
+
+```rust
+pub struct TextElement {
+ id: ElementId,
+ text: SharedString,
+ style: TextStyle,
+}
+
+impl Element for TextElement {
+ type RequestLayoutState = StyledText;
+ type PrepaintState = Hitbox;
+
+ fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
+ -> (LayoutId, StyledText)
+ {
+ let styled_text = StyledText::new(self.text.clone())
+ .with_style(self.style);
+ let (layout_id, _) = styled_text.request_layout(None, None, window, cx);
+ (layout_id, styled_text)
+ }
+
+ fn prepaint(&mut self, .., bounds: Bounds, styled_text: &mut StyledText,
+ window: &mut Window, cx: &mut App) -> Hitbox
+ {
+ styled_text.prepaint(None, None, bounds, &mut (), window, cx);
+ window.insert_hitbox(bounds, HitboxBehavior::Normal)
+ }
+
+ fn paint(&mut self, .., bounds: Bounds, styled_text: &mut StyledText,
+ hitbox: &mut Hitbox, window: &mut Window, cx: &mut App)
+ {
+ styled_text.paint(None, None, bounds, &mut (), &mut (), window, cx);
+ window.set_cursor_style(CursorStyle::IBeam, hitbox);
+ }
+}
+```
+
+### Use Cases
+
+- Code editors with syntax highlighting
+- Rich text displays
+- Labels with custom formatting
+- Selectable text areas
+
+## Container Elements
+
+Elements that manage and layout child elements.
+
+### Pattern Characteristics
+
+- Manage child element layouts and positions
+- Handle scrolling and clipping when needed
+- Implement flex/grid-like layouts
+- Coordinate child interactions and event delegation
+
+### Implementation Template
+
+```rust
+pub struct ContainerElement {
+ id: ElementId,
+ children: Vec,
+ direction: FlexDirection,
+ gap: Pixels,
+}
+
+impl Element for ContainerElement {
+ type RequestLayoutState = Vec;
+ type PrepaintState = Vec>;
+
+ fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
+ -> (LayoutId, Vec)
+ {
+ let child_layout_ids: Vec<_> = self.children
+ .iter_mut()
+ .map(|child| child.request_layout(window, cx).0)
+ .collect();
+
+ let layout_id = window.request_layout(
+ Style {
+ flex_direction: self.direction,
+ gap: self.gap,
+ ..default()
+ },
+ child_layout_ids.clone(),
+ cx
+ );
+
+ (layout_id, child_layout_ids)
+ }
+
+ fn prepaint(&mut self, .., bounds: Bounds, layout_ids: &mut Vec,
+ window: &mut Window, cx: &mut App) -> Vec>
+ {
+ let mut child_bounds = Vec::new();
+
+ for (child, layout_id) in self.children.iter_mut().zip(layout_ids.iter()) {
+ let child_bound = window.layout_bounds(*layout_id);
+ child.prepaint(child_bound, window, cx);
+ child_bounds.push(child_bound);
+ }
+
+ child_bounds
+ }
+
+ fn paint(&mut self, .., child_bounds: &mut Vec>,
+ window: &mut Window, cx: &mut App)
+ {
+ for (child, bounds) in self.children.iter_mut().zip(child_bounds.iter()) {
+ child.paint(*bounds, window, cx);
+ }
+ }
+}
+```
+
+### Use Cases
+
+- Panels and split views
+- List containers
+- Grid layouts
+- Tab containers
+
+## Interactive Elements
+
+Elements that respond to user input (mouse, keyboard, touch).
+
+### Pattern Characteristics
+
+- Create appropriate hitboxes for interaction areas
+- Handle mouse/keyboard/touch events properly
+- Manage focus and cursor styles
+- Support hover, active, and disabled states
+
+### Implementation Template
+
+```rust
+pub struct InteractiveElement {
+ id: ElementId,
+ content: AnyElement,
+ on_click: Option>,
+ hover_style: Option