shadcn-admin-kit
repository·main·Indexed 22 days ago
https://github.com/marmelab/shadcn-admin-kitA component kit for building administrative applications using shadcn/ui. It provides a framework for CRUD operations, data tables, authentication, and dashboarding, compatible with any API backend. Key features include the <Admin> root component, <Resource> for CRUD route definition, and built-in guessers for rapid UI scaffolding.
What's inside shadcn-admin-kit
- Shadcn Admin Kit provides several primitives designed to fetch and display relational data within your admin interface. These are categorized into Data Display components (for high-level views), Fields (for specific data types), and Controls (for interacting with data lists).
Available components for data creation and editing
mainThe Shadcn Admin Kit provides a suite of components designed for creating and updating records. These are categorized into Forms, Inputs, Action Buttons, and Bulk Action Buttons.
Forms
SimpleForm: A standard form container.SimpleFormIterator: A form container for handling collections of items.
Inputs
Inputs allow for specific data types and relationships:
- Text & Numbers:
TextInput,NumberInput,TextArrayInput. - Selection:
SelectInput,RadioButtonGroupInput,AutocompleteInput,AutocompleteArrayInput. - Booleans & Files:
BooleanInput,FileInput. - Arrays:
ArrayInput. - References:
ReferenceInput(for single records),ReferenceArrayInput(for multiple records). - Rich Text:
RichTextInput(requires an optional installation).
Action Buttons
Used to trigger lifecycle events for a single record:
CreateButton: Create a new record.EditButton: Enter edit mode.SaveButton: Save changes.CancelButton: Cancel current operation.DeleteButton: Remove a record.ShowButton: View record details.
Bulk Action Buttons
Used for performing operations on multiple selected records:
BulkDeleteButton: Delete multiple selected records.BulkExportButton: Export multiple selected records.
What is an `authProvider` and how does it work?
mainAn
authProvideracts as a bridge betweenshadcn-admin-kitand your authentication backend (e.g., OAuth, MFA, or passwordless systems). It handles the lifecycle of a user session, including logging in, checking authentication status during navigation, and retrieving user identity.By providing an
authProviderto the<Admin>component, the kit automatically secures your application: unauthorized users are redirected to a login page, and they are redirected back to their intended destination after a successful login.const authProvider = { // Send username and password to the auth server and get back credentials async login(params) {/** ... **/}, // Check if an error from the dataProvider indicates an authentication issue async checkError(error) {/** ... **/}, // Verify that the user's credentials are still valid during navigation async checkAuth(params) {/** ... **/}, // Remove local credentials and notify the auth server of the logout async logout() {/** ... **/}, // Retrieve the user's profile async getIdentity() {/** ... **/}, // (Optional) Check if the user has permission for a specific action on a resource async canAccess() {/** ... **/}, };What is a Data Provider in shadcn-admin-kit?
mainIn
shadcn-admin-kit, you do not usefetchoraxiosdirectly for API calls. Instead, you use adataProviderobject. This abstraction unifies interactions across different API types (like REST and GraphQL), allowing the framework's components to communicate with your backend through a standardized interface.Key characteristics include:
- Abstraction: Focus on UI development instead of manual API request construction.
- Integration: Works with specialized hooks like
useGetListanduseGetOne. - State Management: Integrates with [TanStack Query] for caching and optimistic updates.
- Security: Works alongside an
authProviderto include authentication tokens in requests. - Relational Support: Simplifies working with relational data and real-time capabilities.
How Data Providers work in shadcn-admin-kit
mainSince
shadcn-admin-kitapps are Single Page Applications (SPA) that fetch data from an API, they use a Data Provider to act as an adapter between the kit's CRUD requirements and your specific API.Instead of writing custom fetch logic for every component, you provide a single
dataProviderinstance to the<Admin>component. This provider translates kit actions (like listing, creating, or updating records) into the specific HTTP requests your backend expects. You can use existing packages likera-data-json-serveror build a custom one if your API follows a non-standard format.import { Admin } from "@/components/admin"; import { dataProvider } from "./dataProvider"; const App = () => <Admin dataProvider={dataProvider}></Admin>;Automatic loading indicators with React Suspense
mainThe Shadcn Admin Kit
<Layout>component automatically displays the<Loading>component in the main content area when a page component is loading, provided the loading duration exceeds 1 second. This behavior is powered by React Suspense and requires no manual configuration.This is particularly useful when using code splitting to lazy load resource views (e.g.,
listoreditcomponents).import * as React from 'react'; import { Admin } from "@/components/admin"; import { Resource } from "ra-core"; import { dataProvider } from './dataProvider'; // Lazy loading components will trigger the automatic Loading component const OrderList = React.lazy(() => import('./orders/OrderList')); const OrderEdit = React.lazy(() => import('./orders/OrderEdit')); const App = () => ( <Admin dataProvider={dataProvider}> <Resource name="orders" list={OrderList} edit={OrderEdit} /> {/* ... */} </Admin> );Format and Parse values in BooleanInput
mainBy default,
BooleanInputexpects the form state value to be a boolean (trueorfalse). If your form state uses different types (e.g., integers1/0or strings), you must use theformatandparseprops to bridge the difference.format: A callback that takes the value from the form state and returns a boolean for the input.parse: A callback that takes the boolean from the input and returns the value to be stored in the form state.
Data Flow:
form state value$\rightarrow$format$\rightarrow$form input value (boolean)form input value (boolean)$\rightarrow$parse$\rightarrow$form state value<BooleanInput source="is_active" format={(value) => value === 1} parse={(value) => (value ? 1 : 0)} />Implement custom layouts with `<EditBase>` or `useEditController`
mainIf you need a custom layout that doesn't follow the default Shadcn Admin Kit edition page structure, you have two options:
<EditBase>: Renders its children within anEditContext. Components like<SimpleForm>can then automatically access the record and save handler from this context.useEditController: A hook that provides therecordandsavefunction directly. This is best for completely custom implementations where you don't want to rely on theEditContextprovider.
import { useEditController } from "ra-core"; import { SelectInput, SimpleForm, TextInput } from "@/components/admin"; import { Card, CardContent } from "@/components/ui"; export const BookEdit = () => { // Manually grab the controller logic const { record, save } = useEditController(); return ( <> <h1>Edit book {record?.title}</h1> <Card> <CardContent> <SimpleForm record={record} onSubmit={values => save(values)} > <TextInput source="title" /> <SelectInput source="availability" choices={[{ id: "in_stock", name: "In stock" }]} /> </SimpleForm> </CardContent> </Card> </> ); };Implement global validation for `<ArrayInput>`
mainWhen using
<ArrayInput>within a form that uses global validation, thevalidatefunction must return an error object shaped as an array to match the data structure. Each error entry should correspond to an index in the array.Example error shape:
{ authors: [ {}, { name: 'A name is required', role: 'ra.validation.required' // translation keys are supported }, ], }Use Publish/Subscribe for real-time events
mainThe real-time features rely on a pub/sub mechanism where events are sent to a topic and all subscribers receive them.
Use
usePublishto send events anduseSubscribeoruseSubscribeCallbackto listen for them.Additionally, you can subscribe to specific CRUD events (changes to records or lists) using:
useSubscribeToRecord: Listen for changes to a specific record.useSubscribeToRecordList: Listen for changes to a list of records.
import { usePublish, useSubscribe } from '@react-admin/ra-core-ee'; // on the publisher side const [publish] = usePublish(); publish(topic, event); // on the subscriber side useSubscribe(topic, callback);How optimistic rendering and undo work
mainBy default,
shadcn-admin-kituses optimistic updates. When a user performs an action (like editing or deleting a record), the UI updates immediately to show the new state before the server request is completed.This provides two main benefits:
- Immediate Feedback: Users don't have to wait for network latency to see their changes.
- Undo Feature: Because updates are sent to the server after a short delay (approx. 5 seconds), a confirmation box appears allowing users to click Undo. If clicked, the app cancels the pending API request and reverts the UI to the previous state.
These features are handled entirely on the client side and do not require special implementation on your API.
Perform Soft Deletes in bulk
mainIf your data provider supports soft delete, you should use
<BulkSoftDeleteButton>instead of<BulkDeleteButton>to avoid permanent record removal.Once records are soft-deleted, you can use:
<BulkRestoreButton>to bring them back.<BulkDeletePermanentlyButton>to remove them from the system entirely.
Note: Soft delete features require an Enterprise Edition subscription.