Files
vercel__components.build/content/docs/composition.fi.mdx
Hayden Bleasel 55fae375a4 Update docs, internationalization (#35)
* Update Geistdocs

* Update geistdocs.tsx

* Run translation script

* Delete toc.tsx

* Update route.ts

* Update route.ts
2025-12-04 23:57:35 -08:00

233 lines
7.3 KiB
Plaintext

---
title: Koostettavuus
description: Modernien käyttöliittymäkomponenttien rakentamisen perusta.
---
Koostettavuus, tai composability, on modernien käyttöliittymäkomponenttien rakentamisen perusta. Se on yksi tehokkaimmista tekniikoista joustavien, uudelleenkäytettävien komponenttien luomiseksi, jotka pystyvät käsittelemään monimutkaisia vaatimuksia ilman, että API:n selkeys kärsii.
Sen sijaan, että kaikki toiminnallisuus ahtauttaisiin yhteen komponenttiin kymmenien propien kanssa, koostettavuus jakaa vastuun useiden yhteistyössä toimivien komponenttien kesken.
Fernando piti tästä erinomaisen esityksen React Universe Conf 2025 -tapahtumassa, jossa hän jakoi lähestymistapansa Slackin Message Composerin rakentamiseen uudelleen koostettavana komponenttina.
<Video src="https://www.youtube.com/watch?v=4KvbVq3Eg5w" />
## Komponentin tekeminen koostettavaksi
Jotta komponentista tulisi koostettava, se täytyy pilkkoa pienempiin, tarkemmin fokusoituihin komponentteihin. Otetaan esimerkiksi tämä Accordion-komponentti:
```tsx title="accordion.tsx"
import { Accordion } from '@/components/ui/accordion';
const data = [
{
title: 'Accordion 1',
content: 'Accordion 1 content',
},
{
title: 'Accordion 2',
content: 'Accordion 2 content',
},
{
title: 'Accordion 3',
content: 'Accordion 3 content',
},
];
return (
<Accordion data={data} />
);
```
Vaikka tämä Accordion-komponentti saattaa vaikuttaa yksinkertaiselta, se käsittelee liian monia vastuita. Se on vastuussa säiliön, triggerin ja sisällön renderöinnistä; sekä accordion-tilan ja datan käsittelystä.
Tämän komponentin tyylien mukauttaminen on vaikeaa, koska se on tiukasti kytketty. Se todennäköisesti vaatii globaaleja CSS-overrideja. Lisäksi uuden toiminnallisuuden lisääminen tai käyttäytymisen hienosäätö vaatii komponentin lähdekoodin muokkaamista.
Ratkaisuna voimme jakaa tämän pienempiin, tarkemmin fokusoituihin komponentteihin.
### 1. Root-komponentti
Aloitetaan säiliöstä — komponentista, joka pitää kaiken koossa, eli triggeristä ja sisällöstä. Tämän säiliön ei tarvitse tietää datasta, mutta sen täytyy pitää kirjaa avoimesta tilasta.
Haluamme kuitenkin, että tämä tila on lapsikomponenttien saatavilla. Käytetään siis Context API:a luodaksemme kontekstin avoimelle tilalle.
Lopuksi, jotta `div`-elementtiä voidaan muokata, laajennamme oletusarvoisia HTML-attribuutteja.
Kutsumme tätä komponenttia "Root"-komponentiksi.
```tsx title="@/components/ui/accordion.tsx"
type AccordionProps = React.ComponentProps<'div'> & {
open: boolean;
setOpen: (open: boolean) => void;
};
const AccordionContext = createContext<AccordionProps>({
open: false,
setOpen: () => {},
});
export type AccordionRootProps = React.ComponentProps<'div'> & {
open: boolean;
setOpen: (open: boolean) => void;
};
export const Root = ({
children,
open,
setOpen,
...props
}: AccordionRootProps) => (
<AccordionContext.Provider value={{ open, setOpen }}>
<div {...props}>{children}</div>
</AccordionContext.Provider>
);
```
### 2. Item-komponentti
Item-komponentti on elementti, joka sisältää yksittäisen accordion-kohteen. Se on yksinkertaisesti wrapper kullekin kohteelle accordionissa.
```tsx title="@/components/ui/accordion.tsx"
export type AccordionItemProps = React.ComponentProps<'div'>;
export const Item = (props: AccordionItemProps) => <div {...props} />;
```
### 3. Trigger-komponentti
Trigger-komponentti on elementti, joka avaa accordionin, kun sitä aktivoidaan. Se on vastuussa:
- Renderöinnistä oletuksena napiksi (voidaan mukauttaa `asChild`-propin avulla)
- Klikkitapahtumien käsittelystä accordionin avaamiseksi
- Fokuksen hallinnasta, kun accordion sulkeutuu
- Oikeiden ARIA-attribuuttien tarjoamisesta
Lisätään tämä komponentti Accordion-komponenttiimme.
```tsx title="@/components/ui/accordion.tsx"
export type AccordionTriggerProps = React.ComponentProps<'button'> & {
asChild?: boolean;
};
export const Trigger = ({ asChild, ...props }: AccordionTriggerProps) => (
<AccordionContext.Consumer>
{({ open, setOpen }) => (
<button onClick={() => setOpen(!open)} {...props} />
)}
</AccordionContext.Consumer>
);
```
### 4. Content-komponentti
Content-komponentti on elementti, joka sisältää accordionin sisällön. Se on vastuussa:
- Sisällön renderöimisestä, kun accordion on avoinna
- Oikeiden ARIA-attribuuttien tarjoamisesta
Lisätään tämä komponentti Accordion-komponenttiimme.
```tsx title="@/components/ui/accordion.tsx"
export type AccordionContentProps = React.ComponentProps<'div'> & {
asChild?: boolean;
};
export const Content = ({ asChild, ...props }: AccordionContentProps) => (
<AccordionContext.Consumer>
{({ open }) => <div {...props} />}
</AccordionContext.Consumer>
);
```
### 5. Yhdistäminen
Nyt kun meillä on kaikki komponentit, voimme yhdistää ne alkuperäiseen tiedostoomme.
```tsx title="accordion.tsx"
import * as Accordion from '@/components/ui/accordion';
const data = [
{
title: 'Accordion 1',
content: 'Accordion 1 content',
},
{
title: 'Accordion 2',
content: 'Accordion 2 content',
},
{
title: 'Accordion 3',
content: 'Accordion 3 content',
},
];
return (
<Accordion.Root open={false} setOpen={() => {}}>
{data.map((item) => (
<Accordion.Item key={item.title}>
<Accordion.Trigger>{item.title}</Accordion.Trigger>
<Accordion.Content>{item.content}</Accordion.Content>
</Accordion.Item>
))}
</Accordion.Root>
);
```
## Nimeämiskäytännöt
Kun rakennat koostettavia komponentteja, yhdenmukaiset nimeämiskäytännöt ovat ratkaisevia intuitiivisten ja ennustettavien API:en luomiseksi. Sekä shadcn/ui että Radix UI noudattavat vakiintuneita malleja, jotka ovat muodostuneet de facto -standardiksi React-ekosysteemissä.
### Root-komponentit
`Root`-komponentti toimii pääsäiliönä, joka käärii kaikki muut alikomponentit. Se hallinnoi tyypillisesti jaettua tilaa ja kontekstia tarjoamalla kontekstin kaikille lapsikomponenteille.
```tsx
<AccordionRoot>{/* Child components */}</AccordionRoot>
```
### Interaktiiviset elementit
Interaktiiviset komponentit, jotka laukaisevat toimintoja tai vaihtavat tiloja, käyttävät kuvaavia nimiä:
- `Trigger` - Elementti, joka aloittaa toiminnon (avaaminen, sulkeminen, kytkeminen)
- `Content` - Elementti, joka sisältää pääasiallisen sisällön, joka näytetään/piilotetaan
```tsx
<CollapsibleTrigger>Click to expand</CollapsibleTrigger>
<CollapsibleContent>
Hidden content revealed here
</CollapsibleContent>
```
### Sisällön rakenne
Komponenteille, joilla on jäsenneltyjä sisältöalueita, käytä semanttisia nimiä, jotka kuvaavat niiden tarkoitusta:
- `Header` - Yläsivu, joka sisältää otsikot tai ohjaimet
- `Body` - Pääsisältöalue
- `Footer` - Alatunniste alue toimille tai metadataan
```tsx
<DialogHeader>
{/* Dialog title */}
</DialogHeader>
<DialogBody>
{/* Dialog content */}
</DialogBody>
<DialogFooter>
{/* Dialog footer */}
</DialogFooter>
```
### Informatiiviset komponentit
Komponentit, jotka tarjoavat tietoa tai kontekstia, käyttävät kuvaavia päätteitä:
- `Title` - Ensisijainen otsikko tai etiketti
- `Description` - Tukiteksti tai selittävä sisältö
```tsx
<CardTitle>Project Statistics</CardTitle>
<CardDescription>
View your project's performance over time
</CardDescription>
```