@rcarls/rc-app-bar 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +221 -0
- package/dist/custom-elements.json +582 -0
- package/dist/demo.css +85 -0
- package/dist/demo.js +40 -0
- package/dist/rc-app-bar-DcYvkEsy.js +388 -0
- package/dist/rc-app-bar-DcYvkEsy.js.map +1 -0
- package/dist/rc-app-bar-define.js +6 -0
- package/dist/rc-app-bar-define.js.map +1 -0
- package/dist/rc-app-bar.js +5 -0
- package/dist/rc-app-bar.js.map +1 -0
- package/dist/types/packages/rc-app-bar/src/define.d.ts +1 -0
- package/dist/types/packages/rc-app-bar/src/index.d.ts +1 -0
- package/dist/types/packages/rc-app-bar/src/rc-app-bar.d.ts +105 -0
- package/dist/types/packages/rc-app-bar/src/rc-app-bar.styles.d.ts +2 -0
- package/dist/types/packages/rc-app-bar/src/rc-app-bar.test.d.ts +0 -0
- package/package.json +69 -0
package/README.md
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# `@rcarls/rc-app-bar`
|
|
2
|
+
|
|
3
|
+
A headless app bar with leading, title, exact-center, and trailing regions.
|
|
4
|
+
It uses a single consumer-owned title element and supports pinned, continuously
|
|
5
|
+
collapsing, and direction-sensitive hide-on-scroll behavior.
|
|
6
|
+
|
|
7
|
+
Material 3 and Apple HIG inform the available structures and behaviors, but the
|
|
8
|
+
default appearance remains deliberately UA-like: system colors, a thin
|
|
9
|
+
scrolled divider, and no supplied action controls or decorative icons.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @rcarls/rc-app-bar
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import '@rcarls/rc-app-bar/define';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Basic usage
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<header>
|
|
25
|
+
<rc-app-bar scroll-target="#content">
|
|
26
|
+
<button slot="leading" aria-label="Back">←</button>
|
|
27
|
+
<span>Inbox</span>
|
|
28
|
+
<rc-toolbar slot="trailing" label="Actions">...</rc-toolbar>
|
|
29
|
+
</rc-app-bar>
|
|
30
|
+
</header>
|
|
31
|
+
<div id="content" class="scroll-area">...</div>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The default slot is the single title region. It may contain a title, subtitle,
|
|
35
|
+
or any other consumer markup. The title node remains connected and is never
|
|
36
|
+
duplicated while the bar changes layout.
|
|
37
|
+
|
|
38
|
+
## Expanded and scroll behaviors
|
|
39
|
+
|
|
40
|
+
`variant="expanded"` places the title in a flexible second row. Its height
|
|
41
|
+
comes from the title content rather than a Material-specific fixed size.
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<rc-app-bar
|
|
45
|
+
variant="expanded"
|
|
46
|
+
scroll-behavior="collapse"
|
|
47
|
+
scroll-target="#content"
|
|
48
|
+
>
|
|
49
|
+
<button slot="leading" aria-label="Back">←</button>
|
|
50
|
+
<div>
|
|
51
|
+
<strong>Slow-Roasted Tomato Pasta</strong>
|
|
52
|
+
<small>Summer recipes</small>
|
|
53
|
+
</div>
|
|
54
|
+
<button slot="trailing" aria-label="Edit">Edit</button>
|
|
55
|
+
</rc-app-bar>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Scroll behaviors are exclusive:
|
|
59
|
+
|
|
60
|
+
- `pinned` keeps the current structure visible and only exposes scrolled state.
|
|
61
|
+
- `collapse` continuously shrinks an expanded title row over its measured
|
|
62
|
+
height, then keeps the compact row visible.
|
|
63
|
+
- `hide` hides the complete bar while scrolling down past `scroll-threshold`
|
|
64
|
+
and reveals it when scrolling up or returning near the top.
|
|
65
|
+
|
|
66
|
+
The component never consumes, stops, or rewrites the document's scroll.
|
|
67
|
+
|
|
68
|
+
## Exact-center composition
|
|
69
|
+
|
|
70
|
+
The optional `center` slot remains at the host's geometric midpoint even when
|
|
71
|
+
leading and trailing controls have different widths. This is useful for
|
|
72
|
+
desktop controls or an [`rc-search-bar`](../rc-search-bar/):
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<rc-app-bar>
|
|
76
|
+
<button slot="leading">Back</button>
|
|
77
|
+
<span>Recipes</span>
|
|
78
|
+
<rc-search-bar slot="center" placeholder="Search recipes">
|
|
79
|
+
<input type="search" aria-label="Search recipes" />
|
|
80
|
+
</rc-search-bar>
|
|
81
|
+
<button slot="trailing" aria-label="Account">Account</button>
|
|
82
|
+
</rc-app-bar>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Title and center content may coexist. The title is constrained before it can
|
|
86
|
+
overlap the centered content. Without center content, the title uses all space
|
|
87
|
+
between leading and trailing controls; consumers may apply
|
|
88
|
+
`rc-app-bar::part(title) { text-align: center; }`.
|
|
89
|
+
|
|
90
|
+
## Controlled state
|
|
91
|
+
|
|
92
|
+
`scrolled` follows the library's controlled/uncontrolled convention:
|
|
93
|
+
|
|
94
|
+
- Set `scrollTarget` or `scroll-target` for uncontrolled observation.
|
|
95
|
+
- Assign `scrolled` to control the endpoint silently.
|
|
96
|
+
- Assign `undefined` to release control back to observation.
|
|
97
|
+
|
|
98
|
+
In controlled collapse mode, `true` snaps to compact and `false` restores the
|
|
99
|
+
expanded row. Controlled hide mode remains visible because a boolean value
|
|
100
|
+
cannot express scroll direction.
|
|
101
|
+
|
|
102
|
+
State output is available as `data-scrolled`, `data-collapsed`, and
|
|
103
|
+
`data-hidden`, with equivalent `:state(scrolled)`, `:state(collapsed)`, and
|
|
104
|
+
`:state(hidden)` custom states.
|
|
105
|
+
|
|
106
|
+
## View Transitions
|
|
107
|
+
|
|
108
|
+
Document View Transitions are consumer-owned progressive enhancement. Assign a
|
|
109
|
+
unique `view-transition-name` to the light-DOM title element, not
|
|
110
|
+
`::part(title)` or the shadow-owned slot wrapper:
|
|
111
|
+
|
|
112
|
+
```html
|
|
113
|
+
<rc-app-bar id="recipe-bar" variant="expanded" scroll-behavior="collapse">
|
|
114
|
+
<h1 class="recipe-title">Slow-Roasted Tomato Pasta</h1>
|
|
115
|
+
</rc-app-bar>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```css
|
|
119
|
+
.recipe-title {
|
|
120
|
+
view-transition-name: recipe-app-bar-title;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
::view-transition-old(recipe-app-bar-title) {
|
|
124
|
+
animation: 180ms ease-out both title-out;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
::view-transition-new(recipe-app-bar-title) {
|
|
128
|
+
animation: 180ms 120ms ease-in both title-in;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@keyframes title-out {
|
|
132
|
+
to {
|
|
133
|
+
opacity: 0;
|
|
134
|
+
translate: 0 -1rem;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@keyframes title-in {
|
|
139
|
+
from {
|
|
140
|
+
opacity: 0;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
const bar = document.querySelector('#recipe-bar');
|
|
147
|
+
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)');
|
|
148
|
+
|
|
149
|
+
async function setCollapsed(collapsed) {
|
|
150
|
+
const update = async () => {
|
|
151
|
+
bar.scrolled = collapsed;
|
|
152
|
+
await bar.updateComplete;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
if (!document.startViewTransition || reduceMotion.matches) {
|
|
156
|
+
await update();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
document.startViewTransition(update);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The app bar never starts a document transition itself because the API is
|
|
165
|
+
global and may conflict with navigation or unrelated components. Unsupported
|
|
166
|
+
browsers receive the immediate endpoint change. Give concurrently rendered
|
|
167
|
+
titles unique transition names.
|
|
168
|
+
|
|
169
|
+
## Styling
|
|
170
|
+
|
|
171
|
+
The component supplies no controls or action icons. The default scrolled
|
|
172
|
+
separator is the `scroll-shadow` part, despite being rendered as a system-color
|
|
173
|
+
border by default:
|
|
174
|
+
|
|
175
|
+
```css
|
|
176
|
+
rc-app-bar::part(scroll-shadow) {
|
|
177
|
+
border-block-end: 0;
|
|
178
|
+
box-shadow: 0 1px 4px rgb(0 0 0 / 0.2);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
rc-app-bar.glass::part(root) {
|
|
182
|
+
background: color-mix(in srgb, Canvas 70%, transparent);
|
|
183
|
+
backdrop-filter: blur(18px);
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### CSS custom properties
|
|
188
|
+
|
|
189
|
+
| Property | Default | Description |
|
|
190
|
+
| --- | --- | --- |
|
|
191
|
+
| `--rc-app-bar-bg` | `Canvas` | Bar background |
|
|
192
|
+
| `--rc-app-bar-color` | `CanvasText` | Bar text color |
|
|
193
|
+
| `--rc-app-bar-compact-min-height` | `3rem` | Compact row minimum height |
|
|
194
|
+
| `--rc-app-bar-expanded-padding-block` | `0.75em` | Expanded title block padding |
|
|
195
|
+
| `--rc-app-bar-padding-inline` | `0.75em` | Horizontal padding |
|
|
196
|
+
| `--rc-app-bar-gap` | `0.5em` | Gap between regions |
|
|
197
|
+
| `--rc-app-bar-transition-duration` | `200ms` | Endpoint and hide transition duration |
|
|
198
|
+
| `--rc-app-bar-scroll-shadow` | `1px solid GrayText` | Scrolled separator border |
|
|
199
|
+
|
|
200
|
+
### CSS parts
|
|
201
|
+
|
|
202
|
+
`root`, `leading`, `title`, `center`, `trailing`, `scroll-shadow`
|
|
203
|
+
|
|
204
|
+
## Breaking migration
|
|
205
|
+
|
|
206
|
+
- Replace `variant="small"` with `variant="compact"`.
|
|
207
|
+
- Replace `variant="medium"` with `variant="expanded"`.
|
|
208
|
+
- Remove `slot="expanded-title"` and keep one title in the default slot.
|
|
209
|
+
- Replace old fixed height/title-font tokens and the `title-row`/`expanded`
|
|
210
|
+
parts with the structural API documented above.
|
|
211
|
+
|
|
212
|
+
## Accessibility
|
|
213
|
+
|
|
214
|
+
- The host has no implicit landmark role. Wrap a page-level instance in
|
|
215
|
+
`<header>` when appropriate.
|
|
216
|
+
- Consumer-provided controls retain their native semantics and keyboard
|
|
217
|
+
behavior.
|
|
218
|
+
- The single title remains connected and exposed to assistive technology in
|
|
219
|
+
every visual state.
|
|
220
|
+
- Movement and fades are disabled under `prefers-reduced-motion: reduce`.
|
|
221
|
+
- The default divider uses `GrayText` and remains visible in forced colors.
|