Float UI

repository·main·Indexed 25 days ago

https://github.com/marsx-dev/floatui

A free, open-source collection of modern UI components and website templates built with React and Tailwind CSS. Version 0.1.0 provides reusable, customizable patterns including UI components and professional templates for React, Next.js, and Nuxt. It features a comprehensive set of components such as Button, Hero, Navbar, Sidebar, and a dedicated icon collection, all supporting both LTR and RTL directions.

Tokens
39.4K
Snippets
29
Records
264
Agent score
85%

What's inside floatui

  1. Understand Float UI License Permissions and Restrictions

    main

    The standard license for Float UI components and templates allows for the creation of unlimited end products for yourself or clients, including commercial SaaS applications, personal websites, and open-source projects. You may modify components to create derivatives, provided they remain subject to this license.

    Prohibited uses include:

    • Creating 'website builders' or tools that allow end users to build their own products using the components.
    • Distributing components or derivatives separately from an end product (as code or design assets).
    • Creating and distributing themes, templates, or project starter kits using the components.
    • Distributing the components as a standalone product.
  2. Explore Float UI components and templates

    main

    Float UI provides two main categories of resources for building websites:

    • UI components: React components (with Vue support coming soon) built with Tailwind CSS. All examples support both LTR (Left-to-Right) and RTL (Right-to-Left) directions.
    • Website templates: Professional templates built on React, Next.js, and Nuxt (Nuxt support coming soon) using Tailwind CSS.
  3. Implement FAQs with shadow component

    main

    The FAQs with shadow component displays a list of frequently asked questions in a grid layout with a subtle shadow effect. It is available for multiple frameworks including React, Svelte, Vue, and plain HTML (Alpine.js).

    Data Structure

    The component expects an array of objects called faqsList. Each object must contain:

    • q: The question string.
    • a: The answer string.

    Framework Implementations

    React (JSX)

    Use a standard array mapping within a container div. The component uses Tailwind CSS classes for styling.

    Svelte

    Use the {#each} block to iterate over the faqsList array.

    Vue

    Use the v-for directive to iterate over the faqsList array.

    Alpine.js (HTML)

    Initialize the data using x-data and iterate using the <template x-for=...> tag.

  4. Implement Secondary FAQs component

    main

    The Secondary FAQs component is an accordion-style FAQ section designed for marketing pages. It supports multiple frameworks including React, Vue, Svelte, and Alpine.js. The component accepts a list of FAQ items, each containing a question (q) and an answer (a).

    Data Structure

    Each FAQ item in the list should follow this format:

    {
      "q": "The question text",
      "a": "The answer text"
    }
  5. Use Float UI with pure CSS and React

    main

    If you do not want to use Tailwind CSS, you can use Float UI components with pure CSS in your React project. To ensure components render correctly, add the following CSS reset/base styles to your global CSS file:

    *, 
    ::before, 
    ::after {
      box-sizing: border-box;
      border-width: 0;
      border-style: solid;
      border-color: currentColor;
    }
    
    ::before, 
    ::after {
      --tw-content: '';
    }
    
    html {
      line-height: 1.5;
      -webkit-text-size-adjust: 100%;
      -moz-tab-size: 4;
      tab-size: 4;
      font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    }
    
    body {
      margin: 0;
      line-height: inherit;
    }
    
    hr {
      height: 0;
      color: inherit;
      border-top-width: 1px;
    }
    
    abbr[title] {
      -webkit-text-decoration: underline dotted;
      text-decoration: underline dotted;
    }
    
    h1, h2, h3, h4, h5, h6 {
      font-size: inherit;
      font-weight: inherit;
    }
    
    a {
      color: inherit;
      text-decoration: inherit;
    }
    
    b, strong {
      font-weight: bolder;
    }
    
    code, kbd, samp, pre {
      font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
      font-size: 1em;
    }
    
    small {
      font-size: 80%;
    }
    
    sub, sup {
      font-size: 75%;
      line-height: 0;
      position: relative;
      vertical-align: baseline;
    }
    
    sub {
      bottom: -0.25em;
    }
    
    sup {
      top: -0.5em;
    }
    
    table {
      text-indent: 0;
      border-color: inherit;
      border-collapse: collapse;
    }
    
    button, input, optgroup, select, textarea {
      font-family: inherit;
      font-size: 100%;
      line-height: inherit;
      color: inherit;
      margin: 0;
      padding: 0;
    }
    
    button, select {
      text-transform: none;
    }
    
    button, [type='button'], [type='reset'], [type='submit'] {
      -webkit-appearance: button;
      background-color: transparent;
      background-image: none;
    }
    
    :-moz-focusring {
      outline: auto;
    }
    
    :-moz-ui-invalid {
      box-shadow: none;
    }
    
    progress {
      vertical-align: baseline;
    }
    
    ::-webkit-inner-spin-button, 
    ::-webkit-outer-spin-button {
      height: auto;
    }
    
    [type='search'] {
      -webkit-appearance: textfield;
      outline-offset: -2px;
    }
    
    ::-webkit-search-decoration {
      -webkit-appearance: none;
    }
    
    ::-webkit-file-upload-button {
      -webkit-appearance: button;
      font: inherit;
    }
    
    summary {
      display: list-item;
    }
    
    blockquote, dl, dd, h1, h2, h3, h4, h5, h6, hr, figure, p, pre {
      margin: 0;
    }
    
    fieldset {
      margin: 0;
      padding: 0;
    }
    
    legend {
      padding: 0;
    }
    
    ol, ul, menu {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    
    textarea {
      resize: vertical;
    }
    
    input::-webkit-input-placeholder, 
    textarea::-webkit-input-placeholder, 
    input:-ms-input-placeholder, 
    textarea:-ms-input-placeholder, 
    input::placeholder, 
    textarea::placeholder {
      opacity: 1;
      color: #9ca3af;
    }
    
    button, [role="button"] {
      cursor: pointer;
    }
    
    :disabled {
      cursor: default;
    }
    
    img, svg, video, canvas, audio, iframe, embed, object {
      display: block;
      vertical-align: middle;
    }
    
    img, video {
      max-width: 100%;
      height: auto;
    }
    
    [hidden] {
      display: none;
    }
  6. Custom Checkbox Styling with Tailwind CSS

    main

    To achieve the custom checkbox look used in Float UI tables, hide the native checkbox and style a sibling <label> using the peer class. This allows the label to react to the checkbox's checked state.

    Required Tailwind Classes:

    • peer hidden: Applied to the <input type="checkbox" /> to hide it but keep it functional for state.
    • peer-checked:bg-indigo-600: Applied to the <label> to change the background color when checked.
    • after:absolute after:inset-x-0 after:top-[3px] ... after:rotate-45: Used on the <label> to create the checkmark icon via pseudo-elements.
  7. Implement a Team Section with centred avatars

    main

    You can implement a marketing team section featuring centered avatars, names, and job titles. This component is available for React, Vue, Svelte, and HTML (Alpine.js) implementations.

    Data Structure

    The component expects an array of team member objects with the following schema:

    • avatar: (string) URL to the member's image.
    • name: (string) The member's full name.
    • title: (string) The member's job title.

    Implementation Examples

    React

    Use a standard array mapping to render the list items within a grid layout.

    Vue

    Use v-for to iterate through the team array within the template.

    Svelte

    Use the {#each} block to iterate through the team array.

    HTML (Alpine.js)

    Use x-data to define the team array and x-for with a <template> tag to render the list.

  8. Implement a Contact Section with image

    main

    The Contact Section with image component is a marketing-focused layout featuring a split screen: a full-height image on one side (hidden on mobile) and a contact form on the other. The form includes fields for Full name, Email, Phone number (with a country code selector), a checkbox-based Services selection, and a Message textarea.

    This component is available for multiple frameworks including React, Svelte, Vue, and HTML/Alpine.js.

  9. Implement Tabs with Icons in React, Vue, or Alpine.js

    main

    You can implement a tabbed interface that includes icons using the components provided by Float UI (built on Radix UI primitives). The implementation involves a root container, a list of triggers (tabs), and content areas that correspond to each trigger's value.

    React Implementation

    Uses @radix-ui/react-tabs. Map through an array of objects containing an icon (JSX) and a name (string) to render Tabs.Trigger and Tabs.Content components.

    Vue Implementation

    Uses radix-vue. Use v-model on TabsRoot for state management and v-for to iterate through tab items.

    Alpine.js Implementation

    Use x-data to manage the selectedTab state and x-show to toggle visibility of the TabsContent sections.

    import * as Tabs from "@radix-ui/react-tabs";
    
    export default () => {
      const tabItems = [
        {
          icon: (<svg>...</svg>),
          name: "Overview",
        },
        // ... other items
      ];
    
      return (
        <Tabs.Root className="max-w-screen-xl mx-auto px-4 md:px-8" defaultValue="Overview">
          <Tabs.List className="w-full border-b flex items-center gap-x-3 overflow-x-auto text-sm" aria-label="Manage your account">
            {tabItems.map((item, idx) => (
              <Tabs.Trigger
                key={idx}
                className="group outline-none py-1.5 border-b-2 border-white text-gray-500 data-[state=active]:border-indigo-600 data-[state=active]:text-indigo-600"
                value={item.name}
              >
                <div className="flex items-center gap-x-2 py-1.5 px-3 rounded-lg duration-150 group-hover:text-indigo-600 group-hover:bg-gray-50 group-active:bg-gray-100 font-medium">
                  {item.icon}
                  {item.name}
                </div>
              </Tabs.Trigger>
            ))}
          </Tabs.List>
          {tabItems.map((item, idx) => (
            <Tabs.Content key={idx} className="py-6" value={item.name}>
              <p className="text-xs leading-normal">
                This is <b>{item.name}</b> Tab
              </p>
            </Tabs.Content>
          ))}
        </Tabs.Root>
      );
    };