Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions src/components/Layout/HomeContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -766,9 +766,7 @@ function CommunityGallery() {
}, []);

return (
<div
ref={ref}
className="relative flex overflow-x-hidden overflow-y-visible w-auto">
<div ref={ref} className="relative flex overflow-x-clip w-auto">
<div
className="w-full py-12 lg:py-20 whitespace-nowrap flex flex-row animate-marquee lg:animate-large-marquee"
style={{
Expand All @@ -795,21 +793,26 @@ const CommunityImages = memo(function CommunityImages({isLazy}) {
<div
key={i}
className={cn(
`group flex justify-center px-5 min-w-[50%] lg:min-w-[25%] rounded-2xl relative`
`group flex justify-center px-5 min-w-[50%] lg:min-w-[25%] rounded-2xl`
)}>
<div
className={cn(
'h-auto relative rounded-2xl overflow-hidden before:-skew-x-12 before:absolute before:inset-0 before:-translate-x-full group-hover:before:animate-[shimmer_1s_forwards] before:bg-gradient-to-r before:from-transparent before:via-white/10 before:to-transparent transition-all ease-in-out duration-300',
'h-auto rounded-2xl before:rounded-2xl before:absolute before:pointer-events-none before:inset-0 before:transition-opacity before:-z-1 before:shadow-lg lg:before:shadow-2xl before:opacity-0 before:group-hover:opacity-100 transition-transform ease-in-out duration-300',
i % 2 === 0
? 'rotate-2 group-hover:rotate-[-1deg] group-hover:scale-110 group-hover:shadow-lg lg:group-hover:shadow-2xl'
: 'group-hover:rotate-1 group-hover:scale-110 group-hover:shadow-lg lg:group-hover:shadow-2xl rotate-[-2deg]'
? 'rotate-2 group-hover:rotate-[-1deg] group-hover:scale-110'
: 'group-hover:rotate-1 group-hover:scale-110 rotate-[-2deg]'
)}>
<img
loading={isLazy ? 'lazy' : 'eager'}
src={src}
alt={alt}
className="aspect-[4/3] h-full w-full flex object-cover rounded-2xl bg-gray-10 dark:bg-gray-80"
/>
<div
className={cn(
'overflow-clip relative before:absolute before:inset-0 before:pointer-events-none before:-translate-x-full group-hover:before:animate-[shimmer_1s_forwards] before:bg-gradient-to-r before:from-transparent before:via-white/10 before:to-transparent transition-transform ease-in-out duration-300'
)}>
<img
loading={isLazy ? 'lazy' : 'eager'}
src={src}
alt={alt}
className="aspect-[4/3] h-full w-full flex object-cover rounded-2xl bg-gray-10 dark:bg-gray-80"
/>
</div>
</div>
</div>
))}
Expand Down
134 changes: 124 additions & 10 deletions src/content/reference/react-dom/components/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,23 +162,137 @@ Similar to the [DOM standard,](https://developer.mozilla.org/en-US/docs/Web/API/

### Custom HTML elements {/*custom-html-elements*/}

If you render a tag with a dash, like `<my-element>`, React will assume you want to render a [custom HTML element.](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) In React, rendering custom elements works differently from rendering built-in browser tags:

- All custom element props are serialized to strings and are always set using attributes.
- Custom elements accept `class` rather than `className`, and `for` rather than `htmlFor`.
If you render a tag with a dash, like `<my-element>`, React will assume you want to render a [custom HTML element.](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements)

If you render a built-in browser HTML element with an [`is`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/is) attribute, it will also be treated as a custom element.

<Note>
#### Setting values on custom elements {/*attributes-vs-properties*/}

Custom elements have two methods of passing data into them:

1) Attributes: Which are displayed in markup and can only be set to string values
2) Properties: Which are not displayed in markup and can be set to arbitrary JavaScript values

By default, React will pass values bound in JSX as attributes:

```jsx
<my-element value="Hello, world!"></my-element>
```

Non-string JavaScript values passed to custom elements will be serialized by default:

```jsx
// Will be passed as `"1,2,3"` as the output of `[1,2,3].toString()`
<my-element value={[1,2,3]}></my-element>
```

React will, however, recognize an custom element's property as one that it may pass arbitrary values to if the property name shows up on the class during construction:

<Sandpack>

```js src/index.js hidden
import {MyElement} from './MyElement.js';
import { createRoot } from 'react-dom/client';
import {App} from "./App.js";

customElements.define('my-element', MyElement);

const root = createRoot(document.getElementById('root'))
root.render(<App />);
```

```js src/MyElement.js active
export class MyElement extends HTMLElement {
constructor() {
super();
// The value here will be overwritten by React
// when initialized as an element
this.value = undefined;
}

connectedCallback() {
this.innerHTML = this.value.join(", ");
}
}
```

[A future version of React will include more comprehensive support for custom elements.](https://github.com/facebook/react/issues/11347#issuecomment-1122275286)
```js src/App.js
export function App() {
return <my-element value={[1,2,3]}></my-element>
}
```

You can try it by upgrading React packages to the most recent experimental version:
</Sandpack>

#### Listening for events on custom elements {/*custom-element-events*/}

A common pattern when using custom elements is that they may dispatch [`CustomEvent`s](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) rather than accept a function to call when an event occur. You can listen for these events using an `on` prefix when binding to the event via JSX.

<Sandpack>

```js src/index.js hidden
import {MyElement} from './MyElement.js';
import { createRoot } from 'react-dom/client';
import {App} from "./App.js";

customElements.define('my-element', MyElement);

const root = createRoot(document.getElementById('root'))
root.render(<App />);
```

```javascript src/MyElement.js
export class MyElement extends HTMLElement {
constructor() {
super();
this.test = undefined;
this.emitEvent = this._emitEvent.bind(this);
}

_emitEvent() {
const event = new CustomEvent('speak', {
detail: {
message: 'Hello, world!',
},
});
this.dispatchEvent(event);
}

connectedCallback() {
this.el = document.createElement('button');
this.el.innerText = 'Say hi';
this.el.addEventListener('click', this.emitEvent);
this.appendChild(this.el);
}

disconnectedCallback() {
this.el.removeEventListener('click', this.emitEvent);
}
}
```

```jsx src/App.js active
export function App() {
return (
<my-element
onspeak={e => console.log(e.detail.message)}
></my-element>
)
}
```

</Sandpack>

<Note>

- `react@experimental`
- `react-dom@experimental`
Events are case-sensitive and support dashes (`-`). Preserve the casing of the event and include all dashes when listening for custom element's events:

Experimental versions of React may contain bugs. Don't use them in production.
```jsx
// Listens for `say-hi` events
<my-element onsay-hi={console.log}></my-element>
// Listens for `sayHi` events
<my-element onsayHi={console.log}></my-element>
```

</Note>
---
Expand Down
Loading