shadcn-admin-kit

repository·main·Indexed 22 days ago

https://github.com/marmelab/shadcn-admin-kit

A 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.

Tokens
137.4K
Snippets
345
Records
443
Agent score
76%

What's inside shadcn-admin-kit

  1. Available components for data creation and editing

    main

    The 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.
  2. What is an `authProvider` and how does it work?

    main

    An authProvider acts as a bridge between shadcn-admin-kit and 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 authProvider to 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() {/** ... **/},
    };
  3. What is a Data Provider in shadcn-admin-kit?

    main

    In shadcn-admin-kit, you do not use fetch or axios directly for API calls. Instead, you use a dataProvider object. 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 useGetList and useGetOne.
    • State Management: Integrates with [TanStack Query] for caching and optimistic updates.
    • Security: Works alongside an authProvider to include authentication tokens in requests.
    • Relational Support: Simplifies working with relational data and real-time capabilities.
  4. How Data Providers work in shadcn-admin-kit

    main

    Since shadcn-admin-kit apps 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 dataProvider instance 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 like ra-data-json-server or 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>;
  5. Automatic loading indicators with React Suspense

    main

    The 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., list or edit components).

    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>
    );
  6. Format and Parse values in BooleanInput

    main

    By default, BooleanInput expects the form state value to be a boolean (true or false). If your form state uses different types (e.g., integers 1/0 or strings), you must use the format and parse props 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)}
    />
  7. Implement custom layouts with `<EditBase>` or `useEditController`

    main

    If you need a custom layout that doesn't follow the default Shadcn Admin Kit edition page structure, you have two options:

    1. <EditBase>: Renders its children within an EditContext. Components like <SimpleForm> can then automatically access the record and save handler from this context.
    2. useEditController: A hook that provides the record and save function directly. This is best for completely custom implementations where you don't want to rely on the EditContext provider.
    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>
            </>
        );
    };
  8. Implement global validation for `<ArrayInput>`

    main

    When using <ArrayInput> within a form that uses global validation, the validate function 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
            },
        ],
    }
  9. Use Publish/Subscribe for real-time events

    main

    The real-time features rely on a pub/sub mechanism where events are sent to a topic and all subscribers receive them.

    Use usePublish to send events and useSubscribe or useSubscribeCallback to 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);
  10. How optimistic rendering and undo work

    main

    By default, shadcn-admin-kit uses 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:

    1. Immediate Feedback: Users don't have to wait for network latency to see their changes.
    2. 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.

  11. Perform Soft Deletes in bulk

    main

    If 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.