Skip to content

Commit 22119c2

Browse files
fix animations
1 parent 8c07ff7 commit 22119c2

File tree

14 files changed

+97
-92
lines changed

14 files changed

+97
-92
lines changed

.changeset/two-glasses-fix.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ The entire Qwik UI library now does not execute code until interaction.
1010

1111
#### Accordion.Root
1212

13-
- The `behavior="multi"` prop has been replaced with `multiple` on the `<Accordion.Root />` component.
13+
- The `behavior="multi"` prop has been deprecated with `multiple` on the `<Accordion.Root />` component.
1414

1515
- The default behavior is a single item open at a time.
1616

17-
- The `animated` prop has been deprecated. Animation entry and exit are now automatically handled by the component.
17+
- The `animated` prop has been deprecated in favor of `heightAnimation`.
1818

19-
- `onSelectIndexChange$` has been deprecated in favor of `onChange$`.
19+
- `onSelectIndexChange$` has been deprecated and removed in favor of `onChange$`.
2020

21-
- `onFocusIndexChange$` has been deprecated
21+
- `onFocusIndexChange$` has been deprecated and removed. Let us know if you have a use case for this.
2222

2323
- Reactively control the accordion with the `bind:value` prop.
2424

apps/website/src/routes/docs/headless/accordion/examples/animation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default component$(() => {
66
const items = [1, 2, 3];
77

88
return (
9-
<Accordion.Root>
9+
<Accordion.Root heightAnimation>
1010
{items.map((item) => (
1111
<Accordion.Item class="collapsible" key={item}>
1212
<Accordion.Header>

apps/website/src/routes/docs/headless/accordion/examples/multiple.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ export default component$(() => {
88
return (
99
<Accordion.Root multiple>
1010
{items.map((item) => (
11-
<Accordion.Item class="accordion-item" key={item}>
11+
<Accordion.Item class="collapsible" key={item}>
1212
<Accordion.Header>
13-
<Accordion.Trigger class="accordion-trigger">
13+
<Accordion.Trigger class="collapsible-trigger">
1414
<span>Trigger {item}</span>
1515
<LuChevronDown />
1616
</Accordion.Trigger>
1717
</Accordion.Header>
18-
<Accordion.Content class="accordion-content">
18+
<Accordion.Content class="collapsible-content-outline collapsible-content">
1919
Inside Content {item}
2020
</Accordion.Content>
2121
</Accordion.Item>

apps/website/src/routes/docs/headless/accordion/index.mdx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ Listen to when a new item is selected by passing a callback function to the `onC
103103

104104
<Showcase name="on-change" />
105105

106+
### Multiple items
107+
108+
To allow multiple items to be open at the same time, set the `multiple` prop to `true`.
109+
110+
<Showcase name="multiple" />
111+
106112
### Non-collapsible
107113

108114
To disable collapsible behavior, set the `collapsible` prop to `false`.
@@ -127,14 +133,32 @@ The component itself can also be disabled by setting the `disabled` prop to true
127133

128134
## Advanced
129135

130-
### Animation
136+
### Height Animation
131137

132-
Animations can also be added using the `--qwikui-collapsible-content-height` variable.
138+
To animate the height of the content, set the `heightAnimation` prop to `true`.
133139

134140
<Showcase name="animation" />
135141

142+
> In the near future, you won't need JavaScript at all to animate the height of content! Here's the [CSS WG Proposal](https://github.com/w3c/csswg-drafts/blob/main/css-values-5/calc-size-explainer.md) for more info.
143+
144+
You can use the `--qwikui-collapsible-content-height` CSS variable in your keyframes.
145+
136146
<CodeSnippet name="animation.css" />
137147

148+
### Why does padding or border break the animation?
149+
150+
Padding or border applied to `Accordion.Content` breaks our keyframe animation above. This is because the content height has changed.
151+
152+
To fix this, add a child element to the content, and set the padding or border on that element.
153+
154+
```tsx
155+
<Accordion.Content class="collapsible-animation collapsible-content">
156+
<p class="collapsible-content-outline">Content</p>
157+
</Accordion.Content>
158+
```
159+
160+
> Rather than dealing with this under the hood, we thought it'd be appropriate to keep style management as simple as possible. Let us know if you have a better solution!
161+
138162
### CSR
139163

140164
The Accordion automatically renders based on its environment. This means that it works for both server-side and client-side rendering.

apps/website/src/routes/docs/headless/collapsible/examples/animation.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
1-
import { component$, useStyles$ } from '@builder.io/qwik';
1+
import { component$, useSignal, useStyles$ } from '@builder.io/qwik';
22
import { Collapsible } from '@qwik-ui/headless';
33
import { LuChevronDown } from '@qwikest/icons/lucide';
44

55
export default component$(() => {
66
useStyles$(styles);
7+
const isOpen = useSignal(true);
78

89
return (
9-
<Collapsible.Root class="collapsible">
10-
<Collapsible.Trigger class="collapsible-trigger">
11-
<span>Trigger</span>
12-
<LuChevronDown class="collapsible-transition" />
13-
</Collapsible.Trigger>
14-
<Collapsible.Content class="collapsible-animation collapsible-content">
15-
<p class="collapsible-content-outline">Content</p>
16-
</Collapsible.Content>
17-
</Collapsible.Root>
10+
<div>
11+
<Collapsible.Root class="collapsible" bind:open={isOpen} heightAnimation>
12+
<Collapsible.Trigger class="collapsible-trigger">
13+
<span>Trigger</span>
14+
<LuChevronDown class="collapsible-transition" />
15+
</Collapsible.Trigger>
16+
<Collapsible.Content class="collapsible-animation collapsible-content">
17+
<p class="collapsible-content-outline">Content</p>
18+
</Collapsible.Content>
19+
</Collapsible.Root>
20+
<button onClick$={() => (isOpen.value = !isOpen.value)}>Toggle Animation</button>
21+
</div>
1822
);
1923
});
2024

apps/website/src/routes/docs/headless/collapsible/index.mdx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ An interactive section that shows or hides its connected information.
3333
<AnatomyTable
3434
propDescriptors={[
3535
{
36-
name: 'Collapsible',
36+
name: 'Collapsible.Root',
3737
description: 'The root container for the Collapsible component.',
3838
},
3939
{
40-
name: 'CollapsibleTrigger',
40+
name: 'Collapsible.Trigger',
4141
description: 'A button that opens the Collapsible content when interacted with.',
4242
},
4343
{
44-
name: 'CollapsibleContent',
44+
name: 'Collapsible.Content',
4545
description: 'Contains the content associated with a Collapsible.',
4646
},
4747
]}
@@ -70,7 +70,7 @@ As much as we love the native elements, they come with a couple of problems:
7070

7171
### Uncontrolled / Initial value
7272

73-
We can select an initial uncontrolled value by passing the `open` prop to the `<Collapsible />` component.
73+
We can select an initial uncontrolled value by passing the `open` prop to the `<Collapsible.Root />` component.
7474

7575
<Showcase name="open" />
7676

@@ -82,7 +82,7 @@ This is because the content is rendered on the server. Animations applied to `da
8282
8383
### Controlled / Reactive value
8484

85-
We can pass reactive state by using the bind:open prop to the `<Collapsible />` component.
85+
We can pass reactive state by using the bind:open prop to the `<Collapsible.Root />` component.
8686

8787
<Showcase name="bind-open" />
8888

@@ -108,30 +108,36 @@ To do that, we can use the `onChange$` prop. A parameter is passed to the handle
108108

109109
<Showcase name="disabled" />
110110

111-
The collapsible can be disabled by adding the `disabled` prop to the `<Collapsible />` component.
111+
The collapsible can be disabled by adding the `disabled` prop to the `<Collapsible.Root />` component.
112112

113113
## Animating the content
114114

115115
To animate the height of the content, we can use a keyframe animation on the height property.
116116

117117
<Showcase name="animation" />
118118

119-
### Height animation
119+
### Height Animation
120120

121-
By default, the `--qwikui-collapsible-content-height` CSS variable will automatically be set to the height of the content.
121+
To animate the height of the content, set the `heightAnimation` prop to `true`.
122+
123+
<Showcase name="animation" />
124+
125+
> In the near future, you won't need JavaScript at all to animate the height of content! Here's the [CSS WG Proposal](https://github.com/w3c/csswg-drafts/blob/main/css-values-5/calc-size-explainer.md) for more info.
126+
127+
You can use the `--qwikui-collapsible-content-height` CSS variable in your keyframes.
122128

123129
<CodeSnippet name="animation.css" />
124130

125131
### Why does padding or border break the animation?
126132

127-
Padding or border applied to `CollapsibleContent` breaks our keyframe animation above. This is because the content height has changed.
133+
Padding or border applied to `Collapsible.Content` breaks our keyframe animation above. This is because the content height has changed.
128134

129135
To fix this, add a child element to the content, and set the padding or border on that element.
130136

131137
```tsx
132-
<CollapsibleContent class="collapsible-animation collapsible-content">
138+
<Collapsible.Content class="collapsible-animation collapsible-content">
133139
<p class="collapsible-content-outline">Content</p>
134-
</CollapsibleContent>
140+
</Collapsible.Content>
135141
```
136142

137143
> Rather than dealing with this under the hood, we thought it'd be appropriate to keep style management as simple as possible. Let us know if you have a better solution!
@@ -171,7 +177,7 @@ Some CSS variables are specific to the docs, feel free to plug in your own value
171177

172178
### Data Attributes
173179

174-
`Collapsible`, `CollapsibleTrigger`, and `CollapsibleContent` all have the following data attributes that are used to track state:
180+
`Collapsible.Root`, `Collapsible.Trigger`, and `Collapsible.Content` all have the following data attributes that are used to track state:
175181

176182
<AnatomyTable
177183
firstColumnLabel="Attribute"
@@ -191,7 +197,7 @@ Some CSS variables are specific to the docs, feel free to plug in your own value
191197
]}
192198
/>
193199

194-
### Collapsible (Root)
200+
### Collapsible.Root
195201

196202
<APITable
197203
propDescriptors={[

packages/kit-headless/src/components/accordion/accordion-context.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ export type AccordionContext = {
66
selectedIndexSig: Signal<number | null>;
77
initialIndex?: number;
88
givenValueSig: Signal<string | null> | undefined;
9-
multiple?: boolean;
9+
isMultipleSig: Signal<boolean>;
1010
onChange$: QRL<(value: string) => void> | undefined;
1111
itemsMapSig?: Signal<Map<number, boolean>> | undefined;
1212
triggerRefsArray: Signal<Array<Signal>>;
1313
disabled?: boolean;
1414
collapsible?: boolean;
15+
isAnimatedSig: Signal<boolean>;
1516
};
1617

1718
export const accordionItemContextId =

packages/kit-headless/src/components/accordion/accordion-inline.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ export type AccordionRootProps = PropsOf<'div'> & {
66
/** If true, multiple items can be open at the same time. */
77
multiple?: boolean;
88

9+
/**
10+
* @deprecated Use the multiple prop instead.
11+
*/
12+
behavior?: 'single' | 'multi';
13+
914
/** The reactive value controlling which item is open. */
1015
'bind:value'?: Signal<string | null>;
1116

@@ -26,6 +31,14 @@ export type AccordionRootProps = PropsOf<'div'> & {
2631

2732
/** If true, the accordion is collapsible. */
2833
collapsible?: boolean;
34+
35+
/** If true, the accordion is animated. */
36+
heightAnimation?: boolean;
37+
38+
/**
39+
* @deprecated Use the heightAnimation prop instead.
40+
*/
41+
animated?: boolean;
2942
};
3043

3144
export const HAccordionRoot: Component<AccordionRootProps> = (

packages/kit-headless/src/components/accordion/accordion-item.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const HAccordionItem = component$(
4040
useTask$(function internalState({ track }) {
4141
track(() => context.selectedIndexSig.value);
4242

43-
if (context.multiple || isServer) return;
43+
if (context.isMultipleSig.value || isServer) return;
4444

4545
if (context.selectedIndexSig.value !== localIndexSig.value) {
4646
isOpenSig.value = false;
@@ -105,6 +105,7 @@ export const HAccordionItem = component$(
105105
disabled={context.disabled || props.disabled}
106106
collapsible={context.collapsible}
107107
accordionItem
108+
heightAnimation={context.isAnimatedSig.value}
108109
{...props}
109110
>
110111
<Slot />

packages/kit-headless/src/components/accordion/accordion-root.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ export const HAccordionRootImpl = component$((props: AccordionRootProps) => {
1818
onChange$,
1919
disabled,
2020
collapsible = true,
21+
animated,
22+
heightAnimation,
2123
...rest
2224
} = props;
2325

2426
const selectedIndexSig = useSignal<number>(initialIndex ?? -1);
2527
const triggerRefsArray = useSignal<Array<Signal>>([]);
28+
const isAnimatedSig = useSignal<boolean>(animated === true || heightAnimation === true);
29+
const isMultipleSig = useSignal<boolean>(multiple || props.behavior === 'multi');
2630

2731
const itemsMapSig = useComputed$(() => {
2832
return props.itemsMap!;
@@ -31,13 +35,14 @@ export const HAccordionRootImpl = component$((props: AccordionRootProps) => {
3135
const context = {
3236
selectedIndexSig,
3337
givenValueSig,
34-
multiple,
38+
isMultipleSig,
3539
initialIndex,
3640
onChange$,
3741
itemsMapSig,
3842
triggerRefsArray,
3943
disabled,
4044
collapsible,
45+
isAnimatedSig,
4146
};
4247

4348
useTask$(({ track }) => {

0 commit comments

Comments
 (0)