Actions
Button
Buttons for actions and links.
| Class name | Type | Description |
|---|---|---|
btnplf:btn | Component | Button; neutral on its own |
btn-iconplf:btn-icon | Part | An SVG icon in the button; an icon class there doesn't need it |
btn-icon-loadingplf:btn-icon-loading | Part | Draws and spins the loader |
btn-labelplf:btn-label | Part | The label, which the loading part replaces while loading |
btn-loadingplf:btn-loading | Part | Shown in the label's place while loading |
btn-outlineplf:btn-outline | Style | Outline on the surface |
btn-ghostplf:btn-ghost | Style | No background or border until hover |
btn-linkplf:btn-link | Style | Looks like a link |
btn-softplf:btn-soft | Style | A light fill in the color |
btn-neutralplf:btn-neutral | Color | Neutral (dark) color |
btn-primaryplf:btn-primary | Color | Primary color |
btn-errorplf:btn-error | Color | Error color, for destructive actions |
btn-successplf:btn-success | Color | Success color |
btn-warningplf:btn-warning | Color | Warning color |
btn-infoplf:btn-info | Color | Info color |
btn-smplf:btn-sm | Size | Small |
btn-lgplf:btn-lg | Size | Large |
btn-squareplf:btn-square | Modifier | Square, for an icon-only button |
btn-circleplf:btn-circle | Modifier | Round, for an icon-only button |
<button class="btn">Button</button><button class="plf:btn">Button</button>import { Button } from '@pelatform/react';
export function Example() {
return <Button>Button</Button>;
}import { Button } from '@pelatform/react/prefixed';
export function Example() {
return <Button>Button</Button>;
}<button class="btn btn-neutral">Neutral</button>
<button class="btn btn-primary">Primary</button>
<button class="btn btn-error">Error</button>
<button class="btn btn-success">Success</button>
<button class="btn btn-warning">Warning</button>
<button class="btn btn-info">Info</button><button class="plf:btn plf:btn-neutral">Neutral</button>
<button class="plf:btn plf:btn-primary">Primary</button>
<button class="plf:btn plf:btn-error">Error</button>
<button class="plf:btn plf:btn-success">Success</button>
<button class="plf:btn plf:btn-warning">Warning</button>
<button class="plf:btn plf:btn-info">Info</button>import { Button } from '@pelatform/react';
export function Example() {
return (
<>
<Button color="neutral">Neutral</Button>
<Button color="primary">Primary</Button>
<Button color="error">Error</Button>
<Button color="success">Success</Button>
<Button color="warning">Warning</Button>
<Button color="info">Info</Button>
</>
);
}import { Button } from '@pelatform/react/prefixed';
export function Example() {
return (
<>
<Button color="neutral">Neutral</Button>
<Button color="primary">Primary</Button>
<Button color="error">Error</Button>
<Button color="success">Success</Button>
<Button color="warning">Warning</Button>
<Button color="info">Info</Button>
</>
);
}<button class="btn btn-outline">Outline</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-link">Link</button><button class="plf:btn plf:btn-outline">Outline</button>
<button class="plf:btn plf:btn-ghost">Ghost</button>
<button class="plf:btn plf:btn-link">Link</button>import { Button } from '@pelatform/react';
export function Example() {
return (
<>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</>
);
}import { Button } from '@pelatform/react/prefixed';
export function Example() {
return (
<>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</>
);
}<button class="btn btn-soft">Soft</button>
<button class="btn btn-soft btn-primary">Primary</button>
<button class="btn btn-soft btn-error">Error</button>
<button class="btn btn-soft btn-success">Success</button>
<button class="btn btn-soft btn-warning">Warning</button>
<button class="btn btn-soft btn-info">Info</button><button class="plf:btn plf:btn-soft">Soft</button>
<button class="plf:btn plf:btn-soft plf:btn-primary">Primary</button>
<button class="plf:btn plf:btn-soft plf:btn-error">Error</button>
<button class="plf:btn plf:btn-soft plf:btn-success">Success</button>
<button class="plf:btn plf:btn-soft plf:btn-warning">Warning</button>
<button class="plf:btn plf:btn-soft plf:btn-info">Info</button>import { Button } from '@pelatform/react';
export function Example() {
return (
<>
<Button variant="soft">Soft</Button>
<Button variant="soft" color="primary">Primary</Button>
<Button variant="soft" color="error">Error</Button>
<Button variant="soft" color="success">Success</Button>
<Button variant="soft" color="warning">Warning</Button>
<Button variant="soft" color="info">Info</Button>
</>
);
}import { Button } from '@pelatform/react/prefixed';
export function Example() {
return (
<>
<Button variant="soft">Soft</Button>
<Button variant="soft" color="primary">Primary</Button>
<Button variant="soft" color="error">Error</Button>
<Button variant="soft" color="success">Success</Button>
<Button variant="soft" color="warning">Warning</Button>
<Button variant="soft" color="info">Info</Button>
</>
);
}Button tags
<button> for actions, <a> for navigation. Inside a form a button submits it, so add type="button" to one that should not.
<a class="btn btn-primary" href="#">Link</a>
<button class="btn btn-primary" type="submit">Submit</button>
<button class="btn btn-primary" type="reset">Reset</button><a class="plf:btn plf:btn-primary" href="#">Link</a>
<button class="plf:btn plf:btn-primary" type="submit">Submit</button>
<button class="plf:btn plf:btn-primary" type="reset">Reset</button>import { Button, buttonClass } from '@pelatform/react';
export function Example() {
return (
<>
<a className={buttonClass({ color: 'primary' })} href="#">Link</a>
<Button color="primary" type="submit">Submit</Button>
<Button color="primary" type="reset">Reset</Button>
</>
);
}import { Button, buttonClass } from '@pelatform/react/prefixed';
export function Example() {
return (
<>
<a className={buttonClass({ color: 'primary' })} href="#">Link</a>
<Button color="primary" type="submit">Submit</Button>
<Button color="primary" type="reset">Reset</Button>
</>
);
}<button class="btn btn-primary btn-sm">Small</button>
<button class="btn btn-primary">Default</button>
<button class="btn btn-primary btn-lg">Large</button><button class="plf:btn plf:btn-primary plf:btn-sm">Small</button>
<button class="plf:btn plf:btn-primary">Default</button>
<button class="plf:btn plf:btn-primary plf:btn-lg">Large</button>import { Button } from '@pelatform/react';
export function Example() {
return (
<>
<Button color="primary" size="sm">Small</Button>
<Button color="primary">Default</Button>
<Button color="primary" size="lg">Large</Button>
</>
);
}import { Button } from '@pelatform/react/prefixed';
export function Example() {
return (
<>
<Button color="primary" size="sm">Small</Button>
<Button color="primary">Default</Button>
<Button color="primary" size="lg">Large</Button>
</>
);
}Disabled
A link cannot be disabled: give it aria-disabled="true" and leave out href.
<button class="btn btn-primary" disabled>Primary</button>
<button class="btn btn-outline" disabled>Outline</button>
<a class="btn btn-primary" role="link" aria-disabled="true">Link</a><button class="plf:btn plf:btn-primary" disabled>Primary</button>
<button class="plf:btn plf:btn-outline" disabled>Outline</button>
<a class="plf:btn plf:btn-primary" role="link" aria-disabled="true">Link</a>import { Button, buttonClass } from '@pelatform/react';
export function Example() {
return (
<>
<Button color="primary" disabled>Primary</Button>
<Button variant="outline" disabled>Outline</Button>
<a className={buttonClass({ color: 'primary' })} role="link" aria-disabled="true">Link</a>
</>
);
}import { Button, buttonClass } from '@pelatform/react/prefixed';
export function Example() {
return (
<>
<Button color="primary" disabled>Primary</Button>
<Button variant="outline" disabled>Outline</Button>
<a className={buttonClass({ color: 'primary' })} role="link" aria-disabled="true">Link</a>
</>
);
}Loading
Put the label in btn-label and the loading text in btn-loading. PLF.Button.loading(button, true) shows the loading part and false brings the label back; the button keeps its width.
<button class="btn btn-primary" id="button-loading">
<span class="btn-label">Save</span>
<span class="btn-loading">
<span class="btn-icon btn-icon-loading"></span>
Saving…
</span>
</button>
<script>
const button = document.querySelector('#button-loading');
button.addEventListener('click', () => {
PLF.Button.loading(button, true);
// Your action, such as saving a form; this one takes two seconds.
setTimeout(() => PLF.Button.loading(button, false), 2000);
});
</script><button class="plf:btn plf:btn-primary" id="button-loading">
<span class="plf:btn-label">Save</span>
<span class="plf:btn-loading">
<span class="plf:btn-icon plf:btn-icon-loading"></span>
Saving…
</span>
</button>
<script>
const button = document.querySelector('#button-loading');
button.addEventListener('click', () => {
PLF.Button.loading(button, true);
// Your action, such as saving a form; this one takes two seconds.
setTimeout(() => PLF.Button.loading(button, false), 2000);
});
</script>'use client';
import { useState } from 'react';
import { Button } from '@pelatform/react';
export function Example() {
const [saving, setSaving] = useState(false);
function save() {
setSaving(true);
// Your action, such as saving a form; this one takes two seconds.
setTimeout(() => setSaving(false), 2000);
}
return (
<Button color="primary" loading={saving} loadingText="Saving…" onClick={save}>
Save
</Button>
);
}'use client';
import { useState } from 'react';
import { Button } from '@pelatform/react/prefixed';
export function Example() {
const [saving, setSaving] = useState(false);
function save() {
setSaving(true);
// Your action, such as saving a form; this one takes two seconds.
setTimeout(() => setSaving(false), 2000);
}
return (
<Button color="primary" loading={saving} loadingText="Saving…" onClick={save}>
Save
</Button>
);
}Loading on submit
On a form that loads a new page, such as a WordPress settings page, data-plf-loading-on-submit shows the loading part once the form submits and blocks a second submission, with no script of your own. A form that only downloads a file keeps its page, so leave the attribute off there.
<form class="flex flex-col gap-4 max-w-sm" action="/settings" method="post">
<div class="field">
<label class="field-label" for="button-settings-name">Site name</label>
<input class="input" id="button-settings-name" name="site-name" type="text" value="Acme Studio">
</div>
<button class="btn btn-primary self-start" data-plf-loading-on-submit>
<span class="btn-label">Save settings</span>
<span class="btn-loading">
<span class="btn-icon btn-icon-loading"></span>
Saving…
</span>
</button>
</form><form class="plf:flex plf:flex-col plf:gap-4 plf:max-w-sm" action="/settings" method="post">
<div class="plf:field">
<label class="plf:field-label" for="button-settings-name">Site name</label>
<input class="plf:input" id="button-settings-name" name="site-name" type="text" value="Acme Studio">
</div>
<button class="plf:btn plf:btn-primary plf:self-start" data-plf-loading-on-submit>
<span class="plf:btn-label">Save settings</span>
<span class="plf:btn-loading">
<span class="plf:btn-icon plf:btn-icon-loading"></span>
Saving…
</span>
</button>
</form>'use client';
import { useState } from 'react';
import { Button, Field, Input } from '@pelatform/react';
export function Example() {
const [saving, setSaving] = useState(false);
return (
<form className="flex flex-col gap-4 max-w-sm" action="/settings" method="post" onSubmit={() => setSaving(true)}>
<Field label="Site name">
<Input name="site-name" type="text" defaultValue="Acme Studio" />
</Field>
<Button color="primary" className="self-start" loading={saving} loadingText="Saving…">
Save settings
</Button>
</form>
);
}'use client';
import { useState } from 'react';
import { Button, Field, Input } from '@pelatform/react/prefixed';
export function Example() {
const [saving, setSaving] = useState(false);
return (
<form className="plf:flex plf:flex-col plf:gap-4 plf:max-w-sm" action="/settings" method="post" onSubmit={() => setSaving(true)}>
<Field label="Site name">
<Input name="site-name" type="text" defaultValue="Acme Studio" />
</Field>
<Button color="primary" className="plf:self-start" loading={saving} loadingText="Saving…">
Save settings
</Button>
</form>
);
}With icons
An icon-only button needs an aria-label.
<button class="btn btn-primary">
<span class="icon icon-plus"></span>
New file
</button>
<button class="btn btn-outline btn-square" aria-label="Delete">
<span class="icon icon-trash"></span>
</button>
<button class="btn btn-primary btn-circle" aria-label="Add">
<span class="icon icon-plus"></span>
</button><button class="plf:btn plf:btn-primary">
<span class="plf:icon plf:icon-plus"></span>
New file
</button>
<button class="plf:btn plf:btn-outline plf:btn-square" aria-label="Delete">
<span class="plf:icon plf:icon-trash"></span>
</button>
<button class="plf:btn plf:btn-primary plf:btn-circle" aria-label="Add">
<span class="plf:icon plf:icon-plus"></span>
</button>import { Button, Icon } from '@pelatform/react';
export function Example() {
return (
<>
<Button color="primary">
<Icon name="plus" />
New file
</Button>
<Button variant="outline" shape="square" aria-label="Delete">
<Icon name="trash" />
</Button>
<Button color="primary" shape="circle" aria-label="Add">
<Icon name="plus" />
</Button>
</>
);
}import { Button, Icon } from '@pelatform/react/prefixed';
export function Example() {
return (
<>
<Button color="primary">
<Icon name="plus" />
New file
</Button>
<Button variant="outline" shape="square" aria-label="Delete">
<Icon name="trash" />
</Button>
<Button color="primary" shape="circle" aria-label="Add">
<Icon name="plus" />
</Button>
</>
);
}<button class="btn btn-primary w-full">Continue</button><button class="plf:btn plf:btn-primary plf:w-full">Continue</button>import { Button } from '@pelatform/react';
export function Example() {
return <Button color="primary" className="w-full">Continue</Button>;
}import { Button } from '@pelatform/react/prefixed';
export function Example() {
return <Button color="primary" className="plf:w-full">Continue</Button>;
}Login buttons
Each brand’s colors go through Button’s variables, and each logo is its owner’s trademark, used as its sign-in guidelines say; Google’s 2025 guidelines ask for its newer gradient “G”, from Google’s branding page.
<button class="btn btn-outline">
<span class="icon icon-mail"></span>
Sign in with Email
</button>
<button class="btn" style="--plf-button-bg: #fff; --plf-button-color: #1f1f1f; --plf-button-border: #747775; --plf-button-hover-bg: #f2f2f2">
<svg class="btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path fill="#ea4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/>
<path fill="#4285f4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/>
<path fill="#fbbc05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/>
<path fill="#34a853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/>
</svg>
Sign in with Google
</button>
<button class="btn" style="--plf-button-bg: #000; --plf-button-color: #fff; --plf-button-border: #000; --plf-button-hover-bg: #262626">
<span class="icon icon-brand-github"></span>
Sign in with GitHub
</button>
<button class="btn" style="--plf-button-bg: #000; --plf-button-color: #fff; --plf-button-border: #000; --plf-button-hover-bg: #262626">
<span class="icon icon-brand-apple"></span>
Sign in with Apple
</button>
<button class="btn" style="--plf-button-bg: #2f2f2f; --plf-button-color: #fff; --plf-button-border: #000; --plf-button-hover-bg: #404040">
<svg class="btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 21">
<rect x="1" y="1" width="9" height="9" fill="#f25022"/>
<rect x="1" y="11" width="9" height="9" fill="#00a4ef"/>
<rect x="11" y="1" width="9" height="9" fill="#7fba00"/>
<rect x="11" y="11" width="9" height="9" fill="#ffb900"/>
</svg>
Sign in with Microsoft
</button>
<button class="btn" style="--plf-button-bg: #0866ff; --plf-button-color: #fff; --plf-button-border: #005fd8; --plf-button-hover-bg: #0757d6">
<span class="icon icon-brand-facebook"></span>
Sign in with Facebook
</button>
<button class="btn" style="--plf-button-bg: #000; --plf-button-color: #fff; --plf-button-border: #000; --plf-button-hover-bg: #262626">
<span class="icon icon-brand-x"></span>
Sign in with X
</button><button class="plf:btn plf:btn-outline">
<span class="plf:icon plf:icon-mail"></span>
Sign in with Email
</button>
<button class="plf:btn" style="--plf-button-bg: #fff; --plf-button-color: #1f1f1f; --plf-button-border: #747775; --plf-button-hover-bg: #f2f2f2">
<svg class="plf:btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path fill="#ea4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/>
<path fill="#4285f4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/>
<path fill="#fbbc05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/>
<path fill="#34a853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/>
</svg>
Sign in with Google
</button>
<button class="plf:btn" style="--plf-button-bg: #000; --plf-button-color: #fff; --plf-button-border: #000; --plf-button-hover-bg: #262626">
<span class="plf:icon plf:icon-brand-github"></span>
Sign in with GitHub
</button>
<button class="plf:btn" style="--plf-button-bg: #000; --plf-button-color: #fff; --plf-button-border: #000; --plf-button-hover-bg: #262626">
<span class="plf:icon plf:icon-brand-apple"></span>
Sign in with Apple
</button>
<button class="plf:btn" style="--plf-button-bg: #2f2f2f; --plf-button-color: #fff; --plf-button-border: #000; --plf-button-hover-bg: #404040">
<svg class="plf:btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 21">
<rect x="1" y="1" width="9" height="9" fill="#f25022"/>
<rect x="1" y="11" width="9" height="9" fill="#00a4ef"/>
<rect x="11" y="1" width="9" height="9" fill="#7fba00"/>
<rect x="11" y="11" width="9" height="9" fill="#ffb900"/>
</svg>
Sign in with Microsoft
</button>
<button class="plf:btn" style="--plf-button-bg: #0866ff; --plf-button-color: #fff; --plf-button-border: #005fd8; --plf-button-hover-bg: #0757d6">
<span class="plf:icon plf:icon-brand-facebook"></span>
Sign in with Facebook
</button>
<button class="plf:btn" style="--plf-button-bg: #000; --plf-button-color: #fff; --plf-button-border: #000; --plf-button-hover-bg: #262626">
<span class="plf:icon plf:icon-brand-x"></span>
Sign in with X
</button>import type { CSSProperties } from 'react';
import { Button, Icon } from '@pelatform/react';
const brand = (bg: string, color: string, border: string, hover: string) =>
({ '--plf-button-bg': bg, '--plf-button-color': color, '--plf-button-border': border, '--plf-button-hover-bg': hover }) as CSSProperties;
export function Example() {
return (
<>
<Button variant="outline">
<Icon name="mail" />
Sign in with Email
</Button>
<Button style={brand('#fff', '#1f1f1f', '#747775', '#f2f2f2')}>
<svg className="btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path fill="#ea4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z" />
<path fill="#4285f4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z" />
<path fill="#fbbc05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z" />
<path fill="#34a853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z" />
</svg>
Sign in with Google
</Button>
<Button style={brand('#000', '#fff', '#000', '#262626')}>
<Icon name="brand-github" />
Sign in with GitHub
</Button>
<Button style={brand('#000', '#fff', '#000', '#262626')}>
<Icon name="brand-apple" />
Sign in with Apple
</Button>
<Button style={brand('#2f2f2f', '#fff', '#000', '#404040')}>
<svg className="btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 21">
<rect x="1" y="1" width="9" height="9" fill="#f25022" />
<rect x="1" y="11" width="9" height="9" fill="#00a4ef" />
<rect x="11" y="1" width="9" height="9" fill="#7fba00" />
<rect x="11" y="11" width="9" height="9" fill="#ffb900" />
</svg>
Sign in with Microsoft
</Button>
<Button style={brand('#0866ff', '#fff', '#005fd8', '#0757d6')}>
<Icon name="brand-facebook" />
Sign in with Facebook
</Button>
<Button style={brand('#000', '#fff', '#000', '#262626')}>
<Icon name="brand-x" />
Sign in with X
</Button>
</>
);
}import type { CSSProperties } from 'react';
import { Button, Icon } from '@pelatform/react/prefixed';
const brand = (bg: string, color: string, border: string, hover: string) =>
({ '--plf-button-bg': bg, '--plf-button-color': color, '--plf-button-border': border, '--plf-button-hover-bg': hover }) as CSSProperties;
export function Example() {
return (
<>
<Button variant="outline">
<Icon name="mail" />
Sign in with Email
</Button>
<Button style={brand('#fff', '#1f1f1f', '#747775', '#f2f2f2')}>
<svg className="plf:btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path fill="#ea4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z" />
<path fill="#4285f4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z" />
<path fill="#fbbc05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z" />
<path fill="#34a853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z" />
</svg>
Sign in with Google
</Button>
<Button style={brand('#000', '#fff', '#000', '#262626')}>
<Icon name="brand-github" />
Sign in with GitHub
</Button>
<Button style={brand('#000', '#fff', '#000', '#262626')}>
<Icon name="brand-apple" />
Sign in with Apple
</Button>
<Button style={brand('#2f2f2f', '#fff', '#000', '#404040')}>
<svg className="plf:btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 21">
<rect x="1" y="1" width="9" height="9" fill="#f25022" />
<rect x="1" y="11" width="9" height="9" fill="#00a4ef" />
<rect x="11" y="1" width="9" height="9" fill="#7fba00" />
<rect x="11" y="11" width="9" height="9" fill="#ffb900" />
</svg>
Sign in with Microsoft
</Button>
<Button style={brand('#0866ff', '#fff', '#005fd8', '#0757d6')}>
<Icon name="brand-facebook" />
Sign in with Facebook
</Button>
<Button style={brand('#000', '#fff', '#000', '#262626')}>
<Icon name="brand-x" />
Sign in with X
</Button>
</>
);
}JavaScript
Only loading needs JavaScript, and its helper needs no init(). The Full script (pelatform-ui.min.js) starts every component on page load, with no code of your own; with ESM imports, call init() yourself, as in Installation. For markup you add later, see Dynamic content.
<link rel="stylesheet" href="pelatform-ui.min.css">
<link rel="stylesheet" href="icons/icons.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.min.css">
<link rel="stylesheet" href="components/button.min.css">
<link rel="stylesheet" href="components/form.min.css">
<link rel="stylesheet" href="icons/icons.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/button.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script><link rel="stylesheet" href="pelatform-ui.prefixed.min.css">
<link rel="stylesheet" href="icons/icons.prefixed.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.prefixed.min.css">
<link rel="stylesheet" href="components/button.prefixed.min.css">
<link rel="stylesheet" href="components/form.prefixed.min.css">
<link rel="stylesheet" href="icons/icons.prefixed.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/button.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script>| Attribute | Purpose |
|---|---|
data-plf-loading-on-submit |
On a submit button: once its form submits and the browser loads the next page, shows the loading part and disables the button. A submission your script cancels, to send it with fetch, is left to PLF.; a page restored with Back shows the button ready again |
| Method | Behavior |
|---|---|
PLF. |
Disables the button and shows btn-loading in the label’s place |
PLF. |
Gives the button, its label and its focus back |
PLF. |
Loading until the promise, such as fetch, settles, even when it fails; resolves to its result. A function that returns a promise works too |
PLF., getInstance |
The instance of a data-plf-loading-on-submit button, or null; instance. removes its listeners and ends a loading state it started |
Without the script, set aria-busy="true" and disabled on the button while your action runs.
React
Button from @pelatform/react renders this markup from its props, and buttonClass() gives a link or a router’s Link the same classes.
| Prop | Values | Default |
|---|---|---|
color |
neutral, primary, error, success, warning, info; a soft button takes all but neutral, and outline, ghost and link take none |
Neutral |
variant |
outline, ghost, link, soft |
Filled |
size |
sm, lg |
The default size |
shape |
square, circle, for an icon-only button with an aria-label |
None |
loading |
true while your action runs: the button is busy and disabled, and gets its focus back afterwards |
false |
loadingText |
Text or elements shown with a spinner in the label’s place while loading; the children become the label | None |
The other props are a native button’s, className and ref included; buttonClass() takes color, variant, size and shape.
CSS variables
Override on a root or on a single button. On a root, the four color variables reach every variant, ghost and link included: scope them to a variant class such as .btn-primary (.plf\:btn-primary with Prefixed CSS), or set --plf-color-primary to recolor every primary use, hover included.
| Variable | Default |
|---|---|
--plf-button-bg, --plf-button-color, --plf-button-border, --plf-button-hover-bg |
The variant’s colors |
--plf-button-shadow |
--plf-shadow-xs; none on ghost, link and disabled |
--plf-button-height |
32px small, 36px default, 40px large |
--plf-button-padding-inline |
12px, 16px, 24px (8px, 12px, 16px with an icon) |
--plf-button-radius |
Large radius (8px) |
--plf-button-icon-size |
14px, 16px, 18px |
<button class="btn btn-outline" style="--plf-button-color: var(--plf-color-danger); --plf-button-border: var(--plf-color-danger)">Delete</button><button class="plf:btn plf:btn-outline" style="--plf-button-color: var(--plf-color-danger); --plf-button-border: var(--plf-color-danger)">Delete</button>import type { CSSProperties } from 'react';
import { Button } from '@pelatform/react';
export function Example() {
return (
<Button
variant="outline"
style={{ '--plf-button-color': 'var(--plf-color-danger)', '--plf-button-border': 'var(--plf-color-danger)' } as CSSProperties}
>
Delete
</Button>
);
}import type { CSSProperties } from 'react';
import { Button } from '@pelatform/react/prefixed';
export function Example() {
return (
<Button
variant="outline"
style={{ '--plf-button-color': 'var(--plf-color-danger)', '--plf-button-border': 'var(--plf-color-danger)' } as CSSProperties}
>
Delete
</Button>
);
}