mirror of
https://github.com/block/buzz.git
synced 2026-11-06 09:21:45 +00:00
feat(design-system): add portable open-source component library
Signed-off-by: Arjun Mahanti <arjun@squareup.com> Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build && tsc --noEmit",
|
||||
"build": "pnpm --filter @buzz/ui build && vite build && tsc --noEmit",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"preview": "vite preview",
|
||||
"lint": "biome lint .",
|
||||
@@ -18,13 +18,14 @@
|
||||
"test": "pnpm --filter @buzz/design-tokens test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@base-ui-components/react": "1.0.0-rc.0",
|
||||
"@fontsource-variable/inter": "^5.2.8",
|
||||
"@fontsource/jetbrains-mono": "^5.3.0",
|
||||
"@tanstack/react-router": "^1.168.10",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"@buzz/design-tokens": "workspace:*"
|
||||
"@buzz/design-tokens": "workspace:*",
|
||||
"@buzz/ui": "workspace:*",
|
||||
"lucide-react": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.3.0",
|
||||
@@ -34,6 +35,7 @@
|
||||
"@vitejs/plugin-react": "^6.0.0",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"typescript": "~6.0.0",
|
||||
"vite": "^8.0.0"
|
||||
"vite": "^8.0.0",
|
||||
"@playwright/test": "^1.58.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { FOUNDATION_GROUPS } from "@buzz/design-tokens/foundations";
|
||||
import { PageHeader, Section } from "./primitives";
|
||||
export function MotionPage() {
|
||||
const group = FOUNDATION_GROUPS[2];
|
||||
const group = FOUNDATION_GROUPS.find((group) => group.name === "Motion");
|
||||
if (!group) throw new Error("Missing foundation group");
|
||||
return (
|
||||
<>
|
||||
<PageHeader title={group.name} intro={group.description} />
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { FOUNDATION_GROUPS } from "@buzz/design-tokens/foundations";
|
||||
import { PageHeader, Section } from "./primitives";
|
||||
export function RadiusPage() {
|
||||
const group = FOUNDATION_GROUPS[1];
|
||||
const group = FOUNDATION_GROUPS.find((group) => group.name === "Radius");
|
||||
if (!group) throw new Error("Missing foundation group");
|
||||
return (
|
||||
<>
|
||||
<PageHeader title={group.name} intro={group.description} />
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { FOUNDATION_GROUPS } from "@buzz/design-tokens/foundations";
|
||||
import { PageHeader, Section } from "./primitives";
|
||||
export function SpacingPage() {
|
||||
const group = FOUNDATION_GROUPS[0];
|
||||
const group = FOUNDATION_GROUPS.find((group) => group.name === "Spacing");
|
||||
if (!group) throw new Error("Missing foundation group");
|
||||
return (
|
||||
<>
|
||||
<PageHeader title={group.name} intro={group.description} />
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
/* Generated by packages/design-tokens/build.mjs. */
|
||||
@theme {
|
||||
--control-sm: 2rem;
|
||||
--control-md: 2.5rem;
|
||||
--control-lg: 3.25rem;
|
||||
--space-action-inset: 1.25rem;
|
||||
--space-tooltip-block: 0.125rem;
|
||||
--layer-dialog: 80;
|
||||
--layer-floating: 100;
|
||||
--layer-toast: 120;
|
||||
--overlay-scrim: rgb(0 0 0 / 0.5);
|
||||
--space-control-gap: 0.5rem;
|
||||
--space-control-inset: 0.75rem;
|
||||
--space-section-gap: 1.5rem;
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
/** Role-based geometry and motion shared by components and documentation. */
|
||||
export const FOUNDATION_GROUPS = [
|
||||
{
|
||||
name: "Controls",
|
||||
description: "Shared control dimensions and overlay stacking.",
|
||||
roles: [
|
||||
["control-sm", "2rem", "Small actions."],
|
||||
["control-md", "2.5rem", "Standard actions and inputs."],
|
||||
["control-lg", "3.25rem", "Prominent actions."],
|
||||
["space-action-inset", "1.25rem", "Standard button horizontal padding."],
|
||||
["space-tooltip-block", "0.125rem", "Compact tooltip vertical padding."],
|
||||
["layer-dialog", "80", "Modal surfaces."],
|
||||
["layer-floating", "100", "Menus and tooltips above their trigger."],
|
||||
["layer-toast", "120", "Transient status announcements."],
|
||||
["overlay-scrim", "rgb(0 0 0 / 0.5)", "A modal backdrop."],
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Spacing",
|
||||
description:
|
||||
|
||||
1
packages/ui/.gitignore
vendored
Normal file
1
packages/ui/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
dist/
|
||||
68
packages/ui/README.md
Normal file
68
packages/ui/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Buzz UI
|
||||
|
||||
Open-source React components with Buzz's semantic roles, Inter typography, and
|
||||
Lucide icons. Behavior comes from public Base UI primitives; calendar and resize
|
||||
behavior come from DayPicker and react-resizable-panels. No internal package,
|
||||
font CDN, Storybook server, or native Buzz bridge is required.
|
||||
|
||||
From the repository root:
|
||||
|
||||
```sh
|
||||
. ./bin/activate-hermit
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm --filter buzz-desktop-next dev
|
||||
# Open http://localhost:5173/design
|
||||
pnpm --filter @buzz/ui build
|
||||
```
|
||||
|
||||
## Consume
|
||||
|
||||
```tsx
|
||||
import '@fontsource-variable/inter/index.css';
|
||||
import '@fontsource/jetbrains-mono/index.css';
|
||||
import { Button, Field, Input } from '@buzz/ui';
|
||||
|
||||
<Field.Root name="name">
|
||||
<Field.Label>Name</Field.Label>
|
||||
<Input required />
|
||||
<Field.Error />
|
||||
</Field.Root>
|
||||
<Button variant="primary">Continue</Button>
|
||||
```
|
||||
|
||||
The workspace export includes the source CSS; use a Tailwind 4 PostCSS pipeline.
|
||||
For a consumer without Tailwind, build the package and use `@buzz/ui/dist` plus
|
||||
`@buzz/ui/dist/styles.css`. Build output keeps React and behavior libraries external.
|
||||
The package is intentionally private until package naming and release automation
|
||||
are agreed; it is fully usable from this open-source workspace.
|
||||
|
||||
The stylesheet includes the shared theme and Tailwind reset. Load it once at the
|
||||
application boundary. Set `class="dark"` on the document root for dark mode.
|
||||
Font packages belong to the host, allowing self-hosted subsets without remote requests.
|
||||
|
||||
## Component contract
|
||||
|
||||
Compound families retain Base UI's API: `Dialog.Root`, `Dialog.Trigger`,
|
||||
`Dialog.Portal`, `Dialog.Backdrop`, `Dialog.Popup`, `Dialog.Title`, and
|
||||
`Dialog.Close`. Use `render={<Button />}` to skin triggers and closes. Supply a
|
||||
Title and Description for dialogs and popovers. Label inputs with Field.Label;
|
||||
label standalone controls directly. IconButton requires an accessible name.
|
||||
|
||||
Behavioral Root, Portal, and state helpers are direct exports, preserving generics,
|
||||
refs, controlled state, and events. Styled parts merge both string and state-function
|
||||
class names. The underlying libraries own focus management, keyboard navigation,
|
||||
ARIA semantics, and dismissal. Caller-supplied labels and composition still matter.
|
||||
|
||||
Button variants: primary, secondary, outline, ghost, danger, link. Sizes: sm, md,
|
||||
lg. Loading disables duplicate activation while preserving the accessible name.
|
||||
Color, type, geometry, and motion are roles; components never consume color ramps.
|
||||
BarChart covers nonnegative categorical bars with a semantic data table, not a
|
||||
full chart grammar. Carousel is manually advanced, without autoplay or drag.
|
||||
|
||||
Naming differences from shadcn: Menu is DropdownMenu; PreviewCard is HoverCard;
|
||||
OTPField is InputOTP; Field.Label is Label; Toast replaces Sonner's role; BarChart
|
||||
is the initial Chart treatment. Sheet composes Dialog. No shadcn API compatibility
|
||||
or proprietary BlockUI package compatibility is implied.
|
||||
|
||||
See `../../desktop-next/OPEN_SOURCE.md` for provenance and `THIRD_PARTY_NOTICES.md`
|
||||
for upstream notices. New source is covered by the repository's Apache-2.0 license.
|
||||
332
packages/ui/THIRD_PARTY_NOTICES.md
Normal file
332
packages/ui/THIRD_PARTY_NOTICES.md
Normal file
@@ -0,0 +1,332 @@
|
||||
# Third-party notices
|
||||
|
||||
These notices accompany the public dependencies used by Buzz UI and the catalog.
|
||||
Transitive dependencies retain their own notices in their npm distributions.
|
||||
|
||||
## Inter
|
||||
|
||||
```text
|
||||
Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter) Inter-Italic[opsz,wght].ttf: Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
## JetBrains Mono
|
||||
|
||||
```text
|
||||
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) JetBrainsMono-Italic[wght].ttf: Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
## Lucide
|
||||
|
||||
```text
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2026 Lucide Icons and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
The following Lucide icons are derived from the Feather project:
|
||||
|
||||
airplay, alert-circle, alert-octagon, alert-triangle, aperture, arrow-down-circle, arrow-down-left, arrow-down-right, arrow-down, arrow-left-circle, arrow-left, arrow-right-circle, arrow-right, arrow-up-circle, arrow-up-left, arrow-up-right, arrow-up, at-sign, calendar, cast, check, chevron-down, chevron-left, chevron-right, chevron-up, chevrons-down, chevrons-left, chevrons-right, chevrons-up, circle, clipboard, clock, code, columns, command, compass, corner-down-left, corner-down-right, corner-left-down, corner-left-up, corner-right-down, corner-right-up, corner-up-left, corner-up-right, crosshair, database, divide-circle, divide-square, dollar-sign, download, external-link, feather, frown, hash, headphones, help-circle, info, italic, key, layout, life-buoy, link-2, link, loader, lock, log-in, log-out, maximize, meh, minimize, minimize-2, minus-circle, minus-square, minus, monitor, moon, more-horizontal, more-vertical, move, music, navigation-2, navigation, octagon, pause-circle, percent, plus-circle, plus-square, plus, power, radio, rss, search, server, share, shopping-bag, sidebar, smartphone, smile, square, table-2, tablet, target, terminal, trash-2, trash, triangle, tv, type, upload, x-circle, x-octagon, x-square, x, zoom-in, zoom-out
|
||||
|
||||
The MIT License (MIT) (for the icons listed above)
|
||||
|
||||
Copyright (c) 2013-present Cole Bemis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
## Base UI
|
||||
|
||||
```text
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Material-UI SAS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
## DayPicker
|
||||
|
||||
```text
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2026 Giampaolo Bellavite <io@gpbl.dev> and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
## React Resizable Panels
|
||||
|
||||
```text
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Brian Vaughn
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
46
packages/ui/package.json
Normal file
46
packages/ui/package.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "@buzz/ui",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"license": "Apache-2.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./styles.css": "./src/styles.css",
|
||||
"./dist/styles.css": "./dist/ui.css",
|
||||
"./dist": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build && tsc --emitDeclarationOnly",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@base-ui/react": "1.7.0",
|
||||
"@buzz/design-tokens": "workspace:*",
|
||||
"@daypicker/react": "^10.0.1",
|
||||
"lucide-react": "^1.0.0",
|
||||
"react-resizable-panels": "^4.12.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.3.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"typescript": "~6.0.0",
|
||||
"vite": "^8.0.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md",
|
||||
"THIRD_PARTY_NOTICES.md"
|
||||
]
|
||||
}
|
||||
1
packages/ui/postcss.config.js
Normal file
1
packages/ui/postcss.config.js
Normal file
@@ -0,0 +1 @@
|
||||
export default { plugins: { "@tailwindcss/postcss": {} } };
|
||||
1
packages/ui/src/assets.d.ts
vendored
Normal file
1
packages/ui/src/assets.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare module "*.css";
|
||||
42
packages/ui/src/button.tsx
Normal file
42
packages/ui/src/button.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Button as Primitive } from "@base-ui/react/button";
|
||||
import { LoaderCircle } from "lucide-react";
|
||||
import { skin } from "./classes";
|
||||
/** Appearance and behavior of an action. Loading preserves its accessible label. */
|
||||
export type ButtonProps = ComponentProps<typeof Primitive> & {
|
||||
variant?: "primary" | "secondary" | "outline" | "ghost" | "danger" | "link";
|
||||
size?: "sm" | "md" | "lg";
|
||||
loading?: boolean;
|
||||
};
|
||||
/** A pill action with explicit variants, native keyboard semantics, and bounded loading feedback. */
|
||||
export function Button({
|
||||
variant = "primary",
|
||||
size = "md",
|
||||
loading = false,
|
||||
disabled,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: ButtonProps) {
|
||||
return (
|
||||
<Primitive
|
||||
type="button"
|
||||
{...props}
|
||||
disabled={disabled || loading}
|
||||
aria-busy={loading || undefined}
|
||||
data-loading={loading || undefined}
|
||||
data-variant={variant}
|
||||
data-size={size}
|
||||
className={skin("bui-button", className)}
|
||||
>
|
||||
<span className="bui-button-label">{children}</span>
|
||||
{loading && <LoaderCircle className="bui-loading" aria-hidden="true" />}
|
||||
</Primitive>
|
||||
);
|
||||
}
|
||||
/** An icon-only action must have a readable accessible name. */
|
||||
export function IconButton(props: ButtonProps & { "aria-label": string }) {
|
||||
return (
|
||||
<Button {...props} className={skin("bui-icon-button", props.className)} />
|
||||
);
|
||||
}
|
||||
21
packages/ui/src/calendar.tsx
Normal file
21
packages/ui/src/calendar.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { DayPicker, type DayPickerProps } from "@daypicker/react";
|
||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { cx } from "./classes";
|
||||
/** A keyboard-accessible calendar; selection, locale, and disabled dates use DayPicker's API. */
|
||||
export function Calendar({ className, components, ...props }: DayPickerProps) {
|
||||
return (
|
||||
<DayPicker
|
||||
{...props}
|
||||
className={cx("bui-calendar", className)}
|
||||
components={{
|
||||
Chevron: ({ orientation }) =>
|
||||
orientation === "left" ? (
|
||||
<ChevronLeft aria-hidden="true" />
|
||||
) : (
|
||||
<ChevronRight aria-hidden="true" />
|
||||
),
|
||||
...components,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
56
packages/ui/src/carousel.tsx
Normal file
56
packages/ui/src/carousel.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { useId, useState, type ReactNode } from "react";
|
||||
import { ArrowLeft, ArrowRight } from "lucide-react";
|
||||
import { IconButton } from "./button";
|
||||
/** A manually advanced carousel. No autoplay; every slide has a named position. */
|
||||
export function Carousel({
|
||||
label,
|
||||
slides,
|
||||
}: {
|
||||
label: string;
|
||||
slides: readonly ReactNode[];
|
||||
}) {
|
||||
const [index, setIndex] = useState(0);
|
||||
const id = useId();
|
||||
const current = Math.min(index, Math.max(0, slides.length - 1));
|
||||
if (!slides.length) return null;
|
||||
return (
|
||||
<section
|
||||
className="bui-stack"
|
||||
aria-label={label}
|
||||
aria-roledescription="carousel"
|
||||
>
|
||||
{/* biome-ignore lint/a11y/useSemanticElements: WAI-ARIA carousel slides are groups, not form fieldsets. */}
|
||||
<div
|
||||
id={id}
|
||||
role="group"
|
||||
aria-roledescription="slide"
|
||||
aria-label={current + 1 + " of " + slides.length}
|
||||
>
|
||||
{slides[current]}
|
||||
</div>
|
||||
<div className="bui-inline">
|
||||
<IconButton
|
||||
aria-label="Previous slide"
|
||||
aria-controls={id}
|
||||
variant="outline"
|
||||
disabled={current === 0}
|
||||
onClick={() => setIndex(current - 1)}
|
||||
>
|
||||
<ArrowLeft aria-hidden="true" />
|
||||
</IconButton>
|
||||
<span aria-live="polite" className="bui-description">
|
||||
{current + 1} / {slides.length}
|
||||
</span>
|
||||
<IconButton
|
||||
aria-label="Next slide"
|
||||
aria-controls={id}
|
||||
variant="outline"
|
||||
disabled={current === slides.length - 1}
|
||||
onClick={() => setIndex(current + 1)}
|
||||
>
|
||||
<ArrowRight aria-hidden="true" />
|
||||
</IconButton>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
53
packages/ui/src/chart.tsx
Normal file
53
packages/ui/src/chart.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import { useId } from "react";
|
||||
/** One nonnegative scalar in a categorical bar chart. */
|
||||
export interface ChartDatum {
|
||||
label: string;
|
||||
value: number;
|
||||
}
|
||||
/** A compact bar chart whose table is the accessible data source. Invalid values fail explicitly. */
|
||||
export function BarChart({
|
||||
title,
|
||||
data,
|
||||
formatValue = String,
|
||||
}: {
|
||||
title: string;
|
||||
data: readonly ChartDatum[];
|
||||
formatValue?: (value: number) => string;
|
||||
}) {
|
||||
const id = useId();
|
||||
if (data.some((item) => !Number.isFinite(item.value) || item.value < 0))
|
||||
throw new RangeError("BarChart requires finite nonnegative values");
|
||||
if (new Set(data.map((item) => item.label)).size !== data.length)
|
||||
throw new Error("Chart labels must be unique");
|
||||
const max = Math.max(1, ...data.map((item) => item.value));
|
||||
return (
|
||||
<figure className="bui-stack" aria-labelledby={id}>
|
||||
<figcaption id={id} className="bui-label">
|
||||
{title}
|
||||
</figcaption>
|
||||
<table className="bui-chart">
|
||||
<thead className="bui-sr-only">
|
||||
<tr>
|
||||
<th scope="col">Category</th>
|
||||
<th scope="col">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((item) => (
|
||||
<tr key={item.label}>
|
||||
<th scope="row">{item.label}</th>
|
||||
<td>
|
||||
<span
|
||||
className="bui-chart-bar"
|
||||
aria-hidden="true"
|
||||
style={{ width: (item.value / max) * 100 + "%" }}
|
||||
/>
|
||||
<span>{formatValue(item.value)}</span>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</figure>
|
||||
);
|
||||
}
|
||||
12
packages/ui/src/classes.ts
Normal file
12
packages/ui/src/classes.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/** Joins optional class names without rewriting semantic size roles. */
|
||||
export function cx(...values: Array<string | false | undefined>) {
|
||||
return values.filter(Boolean).join(" ");
|
||||
}
|
||||
/** Preserves Base UI state-aware className callbacks when adding the Buzz skin. */
|
||||
export function skin<State>(
|
||||
base: string,
|
||||
custom?: string | ((state: State) => string | undefined),
|
||||
) {
|
||||
return (state: State) =>
|
||||
cx(base, typeof custom === "function" ? custom(state) : custom);
|
||||
}
|
||||
51
packages/ui/src/command.tsx
Normal file
51
packages/ui/src/command.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import { useState } from "react";
|
||||
import { Combobox } from "./primitives/combobox";
|
||||
/** A command is an explicit user action, identified independently of its label. */
|
||||
export interface CommandItem {
|
||||
id: string;
|
||||
label: string;
|
||||
}
|
||||
/** Searchable actions with arrow-key selection. Opening or filtering never invokes an action. */
|
||||
export function Command({
|
||||
label,
|
||||
items,
|
||||
onAction,
|
||||
}: {
|
||||
label: string;
|
||||
items: readonly CommandItem[];
|
||||
onAction: (id: string) => void;
|
||||
}) {
|
||||
const [query, setQuery] = useState("");
|
||||
return (
|
||||
<Combobox.Root<CommandItem>
|
||||
items={items}
|
||||
itemToStringLabel={(item) => item.label}
|
||||
itemToStringValue={(item) => item.id}
|
||||
inputValue={query}
|
||||
onInputValueChange={setQuery}
|
||||
value={null}
|
||||
onValueChange={(item) => {
|
||||
if (item) {
|
||||
onAction(item.id);
|
||||
setQuery("");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Combobox.Input aria-label={label} placeholder="Search commands…" />
|
||||
<Combobox.Portal>
|
||||
<Combobox.Positioner sideOffset={8}>
|
||||
<Combobox.Popup>
|
||||
<Combobox.Empty>No matching commands</Combobox.Empty>
|
||||
<Combobox.List>
|
||||
{(item: CommandItem) => (
|
||||
<Combobox.Item key={item.id} value={item}>
|
||||
{item.label}
|
||||
</Combobox.Item>
|
||||
)}
|
||||
</Combobox.List>
|
||||
</Combobox.Popup>
|
||||
</Combobox.Positioner>
|
||||
</Combobox.Portal>
|
||||
</Combobox.Root>
|
||||
);
|
||||
}
|
||||
47
packages/ui/src/index.ts
Normal file
47
packages/ui/src/index.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import "./styles.css";
|
||||
export { Accordion } from "./primitives/accordion";
|
||||
export { AlertDialog } from "./primitives/alert-dialog";
|
||||
export { Avatar } from "./primitives/avatar";
|
||||
export { Checkbox } from "./primitives/checkbox";
|
||||
export { CheckboxGroup } from "./primitives/checkbox-group";
|
||||
export { Collapsible } from "./primitives/collapsible";
|
||||
export { Combobox } from "./primitives/combobox";
|
||||
export { Autocomplete } from "./primitives/autocomplete";
|
||||
export { ContextMenu } from "./primitives/context-menu";
|
||||
export { Dialog } from "./primitives/dialog";
|
||||
export { Drawer } from "./primitives/drawer";
|
||||
export { Field } from "./primitives/field";
|
||||
export { Fieldset } from "./primitives/fieldset";
|
||||
export { Form } from "./primitives/form";
|
||||
export { Menu } from "./primitives/menu";
|
||||
export { Menubar } from "./primitives/menubar";
|
||||
export { NavigationMenu } from "./primitives/navigation-menu";
|
||||
export { NumberField } from "./primitives/number-field";
|
||||
export { OTPField } from "./primitives/otp-field";
|
||||
export { Popover } from "./primitives/popover";
|
||||
export { PreviewCard } from "./primitives/preview-card";
|
||||
export { Progress } from "./primitives/progress";
|
||||
export { Meter } from "./primitives/meter";
|
||||
export { Radio } from "./primitives/radio";
|
||||
export { RadioGroup } from "./primitives/radio-group";
|
||||
export { ScrollArea } from "./primitives/scroll-area";
|
||||
export { Select } from "./primitives/select";
|
||||
export { Slider } from "./primitives/slider";
|
||||
export { Switch } from "./primitives/switch";
|
||||
export { Tabs } from "./primitives/tabs";
|
||||
export { Toast } from "./primitives/toast";
|
||||
export { Toggle } from "./primitives/toggle";
|
||||
export { ToggleGroup } from "./primitives/toggle-group";
|
||||
export { Toolbar } from "./primitives/toolbar";
|
||||
export { Tooltip } from "./primitives/tooltip";
|
||||
export { Button, IconButton, type ButtonProps } from "./button";
|
||||
export { Input, Textarea } from "./input";
|
||||
export * from "./surfaces";
|
||||
|
||||
export { Calendar } from "./calendar";
|
||||
export { Resizable } from "./resizable";
|
||||
export { Carousel } from "./carousel";
|
||||
export { BarChart, type ChartDatum } from "./chart";
|
||||
export { Command, type CommandItem } from "./command";
|
||||
export { InputGroup } from "./input-group";
|
||||
export { Sheet } from "./sheet";
|
||||
6
packages/ui/src/input-group.tsx
Normal file
6
packages/ui/src/input-group.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { cx } from "./classes";
|
||||
/** Inline input accessories. Label the input itself; decorative accessories should be aria-hidden. */
|
||||
export function InputGroup(props: ComponentProps<"div">) {
|
||||
return <div {...props} className={cx("bui-input-group", props.className)} />;
|
||||
}
|
||||
24
packages/ui/src/input.tsx
Normal file
24
packages/ui/src/input.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Input as Primitive } from "@base-ui/react/input";
|
||||
import { Field } from "@base-ui/react/field";
|
||||
import { skin } from "./classes";
|
||||
/** A text input that participates in Field labeling and validation. */
|
||||
export function Input({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive>) {
|
||||
return <Primitive {...props} className={skin("bui-input", className)} />;
|
||||
}
|
||||
/** A multiline field using the same labeling and validation seam as Input. */
|
||||
export function Textarea({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Field.Control>) {
|
||||
return (
|
||||
<Field.Control
|
||||
{...props}
|
||||
render={<textarea />}
|
||||
className={skin("bui-input bui-textarea", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
64
packages/ui/src/primitives/accordion.tsx
Normal file
64
packages/ui/src/primitives/accordion.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Accordion as Primitive } from "@base-ui/react/accordion";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-stack", className)} />;
|
||||
}
|
||||
|
||||
function StyledItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Item>) {
|
||||
return (
|
||||
<Primitive.Item
|
||||
{...props}
|
||||
className={skin("bui-accordion-item", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledHeader({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Header>) {
|
||||
return (
|
||||
<Primitive.Header {...props} className={skin("bui-reset", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Trigger>) {
|
||||
return (
|
||||
<Primitive.Trigger
|
||||
{...props}
|
||||
className={skin("bui-accordion-trigger", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPanel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Panel>) {
|
||||
return (
|
||||
<Primitive.Panel
|
||||
{...props}
|
||||
className={skin("bui-accordion-panel", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Accordion behavior primitives with the Buzz visual roles. */
|
||||
export const Accordion = {
|
||||
Root: StyledRoot,
|
||||
Item: StyledItem,
|
||||
Header: StyledHeader,
|
||||
Trigger: StyledTrigger,
|
||||
Panel: StyledPanel,
|
||||
};
|
||||
57
packages/ui/src/primitives/alert-dialog.tsx
Normal file
57
packages/ui/src/primitives/alert-dialog.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { AlertDialog as Primitive } from "@base-ui/react/alert-dialog";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledBackdrop({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Backdrop>) {
|
||||
return (
|
||||
<Primitive.Backdrop
|
||||
{...props}
|
||||
className={skin("bui-backdrop", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-dialog", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTitle({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Title>) {
|
||||
return (
|
||||
<Primitive.Title {...props} className={skin("bui-title", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledDescription({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Description>) {
|
||||
return (
|
||||
<Primitive.Description
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** AlertDialog behavior primitives with the Buzz visual roles. */
|
||||
export const AlertDialog = {
|
||||
Root: Primitive.Root,
|
||||
Trigger: Primitive.Trigger,
|
||||
Portal: Primitive.Portal,
|
||||
Backdrop: StyledBackdrop,
|
||||
Popup: StyledPopup,
|
||||
Title: StyledTitle,
|
||||
Description: StyledDescription,
|
||||
Close: Primitive.Close,
|
||||
};
|
||||
85
packages/ui/src/primitives/autocomplete.tsx
Normal file
85
packages/ui/src/primitives/autocomplete.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Autocomplete as Primitive } from "@base-ui/react/autocomplete";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledInput({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Input>) {
|
||||
return (
|
||||
<Primitive.Input {...props} className={skin("bui-input", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Trigger>) {
|
||||
return (
|
||||
<Primitive.Trigger
|
||||
{...props}
|
||||
className={skin("bui-icon-control", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-popup", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledList({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.List>) {
|
||||
return (
|
||||
<Primitive.List {...props} className={skin("bui-option-list", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Item>) {
|
||||
return (
|
||||
<Primitive.Item {...props} className={skin("bui-option", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledEmpty({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Empty>) {
|
||||
return (
|
||||
<Primitive.Empty {...props} className={skin("bui-empty", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** Autocomplete behavior primitives with the Buzz visual roles. */
|
||||
export const Autocomplete = {
|
||||
Root: Primitive.Root,
|
||||
Input: StyledInput,
|
||||
Trigger: StyledTrigger,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
List: StyledList,
|
||||
Item: StyledItem,
|
||||
Empty: StyledEmpty,
|
||||
};
|
||||
43
packages/ui/src/primitives/avatar.tsx
Normal file
43
packages/ui/src/primitives/avatar.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Avatar as Primitive } from "@base-ui/react/avatar";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return (
|
||||
<Primitive.Root {...props} className={skin("bui-avatar", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledImage({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Image>) {
|
||||
return (
|
||||
<Primitive.Image
|
||||
{...props}
|
||||
className={skin("bui-avatar-image", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledFallback({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Fallback>) {
|
||||
return (
|
||||
<Primitive.Fallback
|
||||
{...props}
|
||||
className={skin("bui-avatar-fallback", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Avatar behavior primitives with the Buzz visual roles. */
|
||||
export const Avatar = {
|
||||
Root: StyledRoot,
|
||||
Image: StyledImage,
|
||||
Fallback: StyledFallback,
|
||||
};
|
||||
10
packages/ui/src/primitives/checkbox-group.tsx
Normal file
10
packages/ui/src/primitives/checkbox-group.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { CheckboxGroup as Primitive } from "@base-ui/react/checkbox-group";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({ className, ...props }: ComponentProps<typeof Primitive>) {
|
||||
return <Primitive {...props} className={skin("bui-stack", className)} />;
|
||||
}
|
||||
|
||||
/** CheckboxGroup behavior primitives with the Buzz visual roles. */
|
||||
export const CheckboxGroup = { Root: StyledRoot };
|
||||
27
packages/ui/src/primitives/checkbox.tsx
Normal file
27
packages/ui/src/primitives/checkbox.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Checkbox as Primitive } from "@base-ui/react/checkbox";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return (
|
||||
<Primitive.Root {...props} className={skin("bui-checkbox", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Indicator>) {
|
||||
return (
|
||||
<Primitive.Indicator
|
||||
{...props}
|
||||
className={skin("bui-check-indicator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Checkbox behavior primitives with the Buzz visual roles. */
|
||||
export const Checkbox = { Root: StyledRoot, Indicator: StyledIndicator };
|
||||
41
packages/ui/src/primitives/collapsible.tsx
Normal file
41
packages/ui/src/primitives/collapsible.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Collapsible as Primitive } from "@base-ui/react/collapsible";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-stack", className)} />;
|
||||
}
|
||||
|
||||
function StyledTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Trigger>) {
|
||||
return (
|
||||
<Primitive.Trigger
|
||||
{...props}
|
||||
className={skin("bui-disclosure", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPanel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Panel>) {
|
||||
return (
|
||||
<Primitive.Panel
|
||||
{...props}
|
||||
className={skin("bui-accordion-panel", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Collapsible behavior primitives with the Buzz visual roles. */
|
||||
export const Collapsible = {
|
||||
Root: StyledRoot,
|
||||
Trigger: StyledTrigger,
|
||||
Panel: StyledPanel,
|
||||
};
|
||||
179
packages/ui/src/primitives/combobox.tsx
Normal file
179
packages/ui/src/primitives/combobox.tsx
Normal file
@@ -0,0 +1,179 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Combobox as Primitive } from "@base-ui/react/combobox";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledInput({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Input>) {
|
||||
return (
|
||||
<Primitive.Input {...props} className={skin("bui-input", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledInputGroup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.InputGroup>) {
|
||||
return (
|
||||
<Primitive.InputGroup
|
||||
{...props}
|
||||
className={skin("bui-input-group", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Trigger>) {
|
||||
return (
|
||||
<Primitive.Trigger
|
||||
{...props}
|
||||
className={skin("bui-icon-control", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-popup", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledList({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.List>) {
|
||||
return (
|
||||
<Primitive.List {...props} className={skin("bui-option-list", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Item>) {
|
||||
return (
|
||||
<Primitive.Item {...props} className={skin("bui-option", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledItemIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.ItemIndicator>) {
|
||||
return (
|
||||
<Primitive.ItemIndicator
|
||||
{...props}
|
||||
className={skin("bui-option-check", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledEmpty({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Empty>) {
|
||||
return (
|
||||
<Primitive.Empty {...props} className={skin("bui-empty", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledGroup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Group>) {
|
||||
return (
|
||||
<Primitive.Group {...props} className={skin("bui-stack", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledGroupLabel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.GroupLabel>) {
|
||||
return (
|
||||
<Primitive.GroupLabel
|
||||
{...props}
|
||||
className={skin("bui-group-label", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledChips({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Chips>) {
|
||||
return (
|
||||
<Primitive.Chips {...props} className={skin("bui-chips", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledChip({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Chip>) {
|
||||
return <Primitive.Chip {...props} className={skin("bui-chip", className)} />;
|
||||
}
|
||||
|
||||
function StyledChipRemove({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.ChipRemove>) {
|
||||
return (
|
||||
<Primitive.ChipRemove
|
||||
{...props}
|
||||
className={skin("bui-icon-control", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledClear({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Clear>) {
|
||||
return (
|
||||
<Primitive.Clear
|
||||
{...props}
|
||||
className={skin("bui-icon-control", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Combobox behavior primitives with the Buzz visual roles. */
|
||||
export const Combobox = {
|
||||
Root: Primitive.Root,
|
||||
Input: StyledInput,
|
||||
InputGroup: StyledInputGroup,
|
||||
Trigger: StyledTrigger,
|
||||
Value: Primitive.Value,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
List: StyledList,
|
||||
Item: StyledItem,
|
||||
ItemIndicator: StyledItemIndicator,
|
||||
Empty: StyledEmpty,
|
||||
Group: StyledGroup,
|
||||
GroupLabel: StyledGroupLabel,
|
||||
Chips: StyledChips,
|
||||
Chip: StyledChip,
|
||||
ChipRemove: StyledChipRemove,
|
||||
Clear: StyledClear,
|
||||
};
|
||||
121
packages/ui/src/primitives/context-menu.tsx
Normal file
121
packages/ui/src/primitives/context-menu.tsx
Normal file
@@ -0,0 +1,121 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { ContextMenu as Primitive } from "@base-ui/react/context-menu";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Trigger>) {
|
||||
return (
|
||||
<Primitive.Trigger
|
||||
{...props}
|
||||
className={skin("bui-context-target", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-popup", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Item>) {
|
||||
return (
|
||||
<Primitive.Item {...props} className={skin("bui-option", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledSeparator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Separator>) {
|
||||
return (
|
||||
<Primitive.Separator
|
||||
{...props}
|
||||
className={skin("bui-separator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledGroupLabel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.GroupLabel>) {
|
||||
return (
|
||||
<Primitive.GroupLabel
|
||||
{...props}
|
||||
className={skin("bui-group-label", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledCheckboxItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.CheckboxItem>) {
|
||||
return (
|
||||
<Primitive.CheckboxItem
|
||||
{...props}
|
||||
className={skin("bui-option", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledCheckboxItemIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.CheckboxItemIndicator>) {
|
||||
return (
|
||||
<Primitive.CheckboxItemIndicator
|
||||
{...props}
|
||||
className={skin("bui-option-check", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledSubmenuTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.SubmenuTrigger>) {
|
||||
return (
|
||||
<Primitive.SubmenuTrigger
|
||||
{...props}
|
||||
className={skin("bui-option", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** ContextMenu behavior primitives with the Buzz visual roles. */
|
||||
export const ContextMenu = {
|
||||
Root: Primitive.Root,
|
||||
Trigger: StyledTrigger,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
Item: StyledItem,
|
||||
Separator: StyledSeparator,
|
||||
GroupLabel: StyledGroupLabel,
|
||||
CheckboxItem: StyledCheckboxItem,
|
||||
CheckboxItemIndicator: StyledCheckboxItemIndicator,
|
||||
SubmenuRoot: Primitive.SubmenuRoot,
|
||||
SubmenuTrigger: StyledSubmenuTrigger,
|
||||
};
|
||||
70
packages/ui/src/primitives/dialog.tsx
Normal file
70
packages/ui/src/primitives/dialog.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Dialog as Primitive } from "@base-ui/react/dialog";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledBackdrop({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Backdrop>) {
|
||||
return (
|
||||
<Primitive.Backdrop
|
||||
{...props}
|
||||
className={skin("bui-backdrop", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledViewport({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Viewport>) {
|
||||
return (
|
||||
<Primitive.Viewport
|
||||
{...props}
|
||||
className={skin("bui-dialog-viewport", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-dialog", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTitle({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Title>) {
|
||||
return (
|
||||
<Primitive.Title {...props} className={skin("bui-title", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledDescription({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Description>) {
|
||||
return (
|
||||
<Primitive.Description
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Dialog behavior primitives with the Buzz visual roles. */
|
||||
export const Dialog = {
|
||||
Root: Primitive.Root,
|
||||
Trigger: Primitive.Trigger,
|
||||
Portal: Primitive.Portal,
|
||||
Backdrop: StyledBackdrop,
|
||||
Viewport: StyledViewport,
|
||||
Popup: StyledPopup,
|
||||
Title: StyledTitle,
|
||||
Description: StyledDescription,
|
||||
Close: Primitive.Close,
|
||||
};
|
||||
80
packages/ui/src/primitives/drawer.tsx
Normal file
80
packages/ui/src/primitives/drawer.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Drawer as Primitive } from "@base-ui/react/drawer";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledBackdrop({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Backdrop>) {
|
||||
return (
|
||||
<Primitive.Backdrop
|
||||
{...props}
|
||||
className={skin("bui-backdrop", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledViewport({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Viewport>) {
|
||||
return (
|
||||
<Primitive.Viewport
|
||||
{...props}
|
||||
className={skin("bui-drawer-viewport", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-drawer", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledContent({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Content>) {
|
||||
return (
|
||||
<Primitive.Content {...props} className={skin("bui-stack", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTitle({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Title>) {
|
||||
return (
|
||||
<Primitive.Title {...props} className={skin("bui-title", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledDescription({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Description>) {
|
||||
return (
|
||||
<Primitive.Description
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Drawer behavior primitives with the Buzz visual roles. */
|
||||
export const Drawer = {
|
||||
Root: Primitive.Root,
|
||||
Trigger: Primitive.Trigger,
|
||||
Portal: Primitive.Portal,
|
||||
Backdrop: StyledBackdrop,
|
||||
Viewport: StyledViewport,
|
||||
Popup: StyledPopup,
|
||||
Content: StyledContent,
|
||||
Title: StyledTitle,
|
||||
Description: StyledDescription,
|
||||
Close: Primitive.Close,
|
||||
};
|
||||
61
packages/ui/src/primitives/field.tsx
Normal file
61
packages/ui/src/primitives/field.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Field as Primitive } from "@base-ui/react/field";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-field", className)} />;
|
||||
}
|
||||
|
||||
function StyledLabel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Label>) {
|
||||
return (
|
||||
<Primitive.Label {...props} className={skin("bui-label", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledDescription({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Description>) {
|
||||
return (
|
||||
<Primitive.Description
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledError({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Error>) {
|
||||
return (
|
||||
<Primitive.Error
|
||||
{...props}
|
||||
className={skin("bui-field-error", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledControl({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Control>) {
|
||||
return (
|
||||
<Primitive.Control {...props} className={skin("bui-input", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** Field behavior primitives with the Buzz visual roles. */
|
||||
export const Field = {
|
||||
Root: StyledRoot,
|
||||
Label: StyledLabel,
|
||||
Description: StyledDescription,
|
||||
Error: StyledError,
|
||||
Control: StyledControl,
|
||||
};
|
||||
24
packages/ui/src/primitives/fieldset.tsx
Normal file
24
packages/ui/src/primitives/fieldset.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Fieldset as Primitive } from "@base-ui/react/fieldset";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return (
|
||||
<Primitive.Root {...props} className={skin("bui-fieldset", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledLegend({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Legend>) {
|
||||
return (
|
||||
<Primitive.Legend {...props} className={skin("bui-label", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** Fieldset behavior primitives with the Buzz visual roles. */
|
||||
export const Fieldset = { Root: StyledRoot, Legend: StyledLegend };
|
||||
10
packages/ui/src/primitives/form.tsx
Normal file
10
packages/ui/src/primitives/form.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Form as Primitive } from "@base-ui/react/form";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({ className, ...props }: ComponentProps<typeof Primitive>) {
|
||||
return <Primitive {...props} className={skin("bui-stack", className)} />;
|
||||
}
|
||||
|
||||
/** Form behavior primitives with the Buzz visual roles. */
|
||||
export const Form = { Root: StyledRoot };
|
||||
152
packages/ui/src/primitives/menu.tsx
Normal file
152
packages/ui/src/primitives/menu.tsx
Normal file
@@ -0,0 +1,152 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Menu as Primitive } from "@base-ui/react/menu";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-popup", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Item>) {
|
||||
return (
|
||||
<Primitive.Item {...props} className={skin("bui-option", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledSeparator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Separator>) {
|
||||
return (
|
||||
<Primitive.Separator
|
||||
{...props}
|
||||
className={skin("bui-separator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledGroup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Group>) {
|
||||
return (
|
||||
<Primitive.Group {...props} className={skin("bui-stack", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledGroupLabel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.GroupLabel>) {
|
||||
return (
|
||||
<Primitive.GroupLabel
|
||||
{...props}
|
||||
className={skin("bui-group-label", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledCheckboxItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.CheckboxItem>) {
|
||||
return (
|
||||
<Primitive.CheckboxItem
|
||||
{...props}
|
||||
className={skin("bui-option", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledCheckboxItemIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.CheckboxItemIndicator>) {
|
||||
return (
|
||||
<Primitive.CheckboxItemIndicator
|
||||
{...props}
|
||||
className={skin("bui-option-check", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledRadioGroup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.RadioGroup>) {
|
||||
return (
|
||||
<Primitive.RadioGroup {...props} className={skin("bui-stack", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledRadioItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.RadioItem>) {
|
||||
return (
|
||||
<Primitive.RadioItem {...props} className={skin("bui-option", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledRadioItemIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.RadioItemIndicator>) {
|
||||
return (
|
||||
<Primitive.RadioItemIndicator
|
||||
{...props}
|
||||
className={skin("bui-option-check", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledSubmenuTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.SubmenuTrigger>) {
|
||||
return (
|
||||
<Primitive.SubmenuTrigger
|
||||
{...props}
|
||||
className={skin("bui-option", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Menu behavior primitives with the Buzz visual roles. */
|
||||
export const Menu = {
|
||||
Root: Primitive.Root,
|
||||
Trigger: Primitive.Trigger,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
Item: StyledItem,
|
||||
Separator: StyledSeparator,
|
||||
Group: StyledGroup,
|
||||
GroupLabel: StyledGroupLabel,
|
||||
CheckboxItem: StyledCheckboxItem,
|
||||
CheckboxItemIndicator: StyledCheckboxItemIndicator,
|
||||
RadioGroup: StyledRadioGroup,
|
||||
RadioItem: StyledRadioItem,
|
||||
RadioItemIndicator: StyledRadioItemIndicator,
|
||||
SubmenuRoot: Primitive.SubmenuRoot,
|
||||
SubmenuTrigger: StyledSubmenuTrigger,
|
||||
};
|
||||
10
packages/ui/src/primitives/menubar.tsx
Normal file
10
packages/ui/src/primitives/menubar.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Menubar as Primitive } from "@base-ui/react/menubar";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({ className, ...props }: ComponentProps<typeof Primitive>) {
|
||||
return <Primitive {...props} className={skin("bui-toolbar", className)} />;
|
||||
}
|
||||
|
||||
/** Menubar behavior primitives with the Buzz visual roles. */
|
||||
export const Menubar = { Root: StyledRoot };
|
||||
64
packages/ui/src/primitives/meter.tsx
Normal file
64
packages/ui/src/primitives/meter.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Meter as Primitive } from "@base-ui/react/meter";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-field", className)} />;
|
||||
}
|
||||
|
||||
function StyledLabel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Label>) {
|
||||
return (
|
||||
<Primitive.Label {...props} className={skin("bui-label", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledValue({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Value>) {
|
||||
return (
|
||||
<Primitive.Value
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTrack({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Track>) {
|
||||
return (
|
||||
<Primitive.Track
|
||||
{...props}
|
||||
className={skin("bui-progress-track", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Indicator>) {
|
||||
return (
|
||||
<Primitive.Indicator
|
||||
{...props}
|
||||
className={skin("bui-progress-indicator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Meter behavior primitives with the Buzz visual roles. */
|
||||
export const Meter = {
|
||||
Root: StyledRoot,
|
||||
Label: StyledLabel,
|
||||
Value: StyledValue,
|
||||
Track: StyledTrack,
|
||||
Indicator: StyledIndicator,
|
||||
};
|
||||
105
packages/ui/src/primitives/navigation-menu.tsx
Normal file
105
packages/ui/src/primitives/navigation-menu.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { NavigationMenu as Primitive } from "@base-ui/react/navigation-menu";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return (
|
||||
<Primitive.Root {...props} className={skin("bui-navigation", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledList({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.List>) {
|
||||
return (
|
||||
<Primitive.List {...props} className={skin("bui-toolbar", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Item>) {
|
||||
return <Primitive.Item {...props} className={skin("bui-reset", className)} />;
|
||||
}
|
||||
|
||||
function StyledTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Trigger>) {
|
||||
return (
|
||||
<Primitive.Trigger
|
||||
{...props}
|
||||
className={skin("bui-disclosure", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledContent({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Content>) {
|
||||
return (
|
||||
<Primitive.Content {...props} className={skin("bui-stack", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledLink({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Link>) {
|
||||
return (
|
||||
<Primitive.Link
|
||||
{...props}
|
||||
className={skin("bui-navigation-link", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-popup", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledViewport({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Viewport>) {
|
||||
return (
|
||||
<Primitive.Viewport {...props} className={skin("bui-stack", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** NavigationMenu behavior primitives with the Buzz visual roles. */
|
||||
export const NavigationMenu = {
|
||||
Root: StyledRoot,
|
||||
List: StyledList,
|
||||
Item: StyledItem,
|
||||
Trigger: StyledTrigger,
|
||||
Content: StyledContent,
|
||||
Link: StyledLink,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
Viewport: StyledViewport,
|
||||
};
|
||||
77
packages/ui/src/primitives/number-field.tsx
Normal file
77
packages/ui/src/primitives/number-field.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { NumberField as Primitive } from "@base-ui/react/number-field";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-field", className)} />;
|
||||
}
|
||||
|
||||
function StyledGroup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Group>) {
|
||||
return (
|
||||
<Primitive.Group
|
||||
{...props}
|
||||
className={skin("bui-number-group", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledInput({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Input>) {
|
||||
return (
|
||||
<Primitive.Input
|
||||
{...props}
|
||||
className={skin("bui-number-input", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledIncrement({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Increment>) {
|
||||
return (
|
||||
<Primitive.Increment
|
||||
{...props}
|
||||
className={skin("bui-icon-control", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledDecrement({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Decrement>) {
|
||||
return (
|
||||
<Primitive.Decrement
|
||||
{...props}
|
||||
className={skin("bui-icon-control", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledScrubArea({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.ScrubArea>) {
|
||||
return (
|
||||
<Primitive.ScrubArea {...props} className={skin("bui-label", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** NumberField behavior primitives with the Buzz visual roles. */
|
||||
export const NumberField = {
|
||||
Root: StyledRoot,
|
||||
Group: StyledGroup,
|
||||
Input: StyledInput,
|
||||
Increment: StyledIncrement,
|
||||
Decrement: StyledDecrement,
|
||||
ScrubArea: StyledScrubArea,
|
||||
};
|
||||
22
packages/ui/src/primitives/otp-field.tsx
Normal file
22
packages/ui/src/primitives/otp-field.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { OTPField as Primitive } from "@base-ui/react/otp-field";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-otp", className)} />;
|
||||
}
|
||||
|
||||
function StyledInput({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Input>) {
|
||||
return (
|
||||
<Primitive.Input {...props} className={skin("bui-otp-input", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** OTPField behavior primitives with the Buzz visual roles. */
|
||||
export const OTPField = { Root: StyledRoot, Input: StyledInput };
|
||||
57
packages/ui/src/primitives/popover.tsx
Normal file
57
packages/ui/src/primitives/popover.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Popover as Primitive } from "@base-ui/react/popover";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-popover", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTitle({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Title>) {
|
||||
return (
|
||||
<Primitive.Title {...props} className={skin("bui-label", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledDescription({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Description>) {
|
||||
return (
|
||||
<Primitive.Description
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Popover behavior primitives with the Buzz visual roles. */
|
||||
export const Popover = {
|
||||
Root: Primitive.Root,
|
||||
Trigger: Primitive.Trigger,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
Title: StyledTitle,
|
||||
Description: StyledDescription,
|
||||
Close: Primitive.Close,
|
||||
};
|
||||
45
packages/ui/src/primitives/preview-card.tsx
Normal file
45
packages/ui/src/primitives/preview-card.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { PreviewCard as Primitive } from "@base-ui/react/preview-card";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Trigger>) {
|
||||
return (
|
||||
<Primitive.Trigger
|
||||
{...props}
|
||||
className={skin("bui-navigation-link", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-popover", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** PreviewCard behavior primitives with the Buzz visual roles. */
|
||||
export const PreviewCard = {
|
||||
Root: Primitive.Root,
|
||||
Trigger: StyledTrigger,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
};
|
||||
64
packages/ui/src/primitives/progress.tsx
Normal file
64
packages/ui/src/primitives/progress.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Progress as Primitive } from "@base-ui/react/progress";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-field", className)} />;
|
||||
}
|
||||
|
||||
function StyledLabel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Label>) {
|
||||
return (
|
||||
<Primitive.Label {...props} className={skin("bui-label", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledValue({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Value>) {
|
||||
return (
|
||||
<Primitive.Value
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTrack({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Track>) {
|
||||
return (
|
||||
<Primitive.Track
|
||||
{...props}
|
||||
className={skin("bui-progress-track", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Indicator>) {
|
||||
return (
|
||||
<Primitive.Indicator
|
||||
{...props}
|
||||
className={skin("bui-progress-indicator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Progress behavior primitives with the Buzz visual roles. */
|
||||
export const Progress = {
|
||||
Root: StyledRoot,
|
||||
Label: StyledLabel,
|
||||
Value: StyledValue,
|
||||
Track: StyledTrack,
|
||||
Indicator: StyledIndicator,
|
||||
};
|
||||
10
packages/ui/src/primitives/radio-group.tsx
Normal file
10
packages/ui/src/primitives/radio-group.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { RadioGroup as Primitive } from "@base-ui/react/radio-group";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({ className, ...props }: ComponentProps<typeof Primitive>) {
|
||||
return <Primitive {...props} className={skin("bui-stack", className)} />;
|
||||
}
|
||||
|
||||
/** RadioGroup behavior primitives with the Buzz visual roles. */
|
||||
export const RadioGroup = { Root: StyledRoot };
|
||||
25
packages/ui/src/primitives/radio.tsx
Normal file
25
packages/ui/src/primitives/radio.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Radio as Primitive } from "@base-ui/react/radio";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-radio", className)} />;
|
||||
}
|
||||
|
||||
function StyledIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Indicator>) {
|
||||
return (
|
||||
<Primitive.Indicator
|
||||
{...props}
|
||||
className={skin("bui-radio-indicator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Radio behavior primitives with the Buzz visual roles. */
|
||||
export const Radio = { Root: StyledRoot, Indicator: StyledIndicator };
|
||||
66
packages/ui/src/primitives/scroll-area.tsx
Normal file
66
packages/ui/src/primitives/scroll-area.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { ScrollArea as Primitive } from "@base-ui/react/scroll-area";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return (
|
||||
<Primitive.Root {...props} className={skin("bui-scroll-area", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledViewport({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Viewport>) {
|
||||
return (
|
||||
<Primitive.Viewport
|
||||
{...props}
|
||||
className={skin("bui-scroll-viewport", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledScrollbar({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Scrollbar>) {
|
||||
return (
|
||||
<Primitive.Scrollbar
|
||||
{...props}
|
||||
className={skin("bui-scrollbar", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledThumb({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Thumb>) {
|
||||
return (
|
||||
<Primitive.Thumb
|
||||
{...props}
|
||||
className={skin("bui-scroll-thumb", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledCorner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Corner>) {
|
||||
return (
|
||||
<Primitive.Corner {...props} className={skin("bui-reset", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** ScrollArea behavior primitives with the Buzz visual roles. */
|
||||
export const ScrollArea = {
|
||||
Root: StyledRoot,
|
||||
Viewport: StyledViewport,
|
||||
Scrollbar: StyledScrollbar,
|
||||
Thumb: StyledThumb,
|
||||
Corner: StyledCorner,
|
||||
};
|
||||
124
packages/ui/src/primitives/select.tsx
Normal file
124
packages/ui/src/primitives/select.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Select as Primitive } from "@base-ui/react/select";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledTrigger({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Trigger>) {
|
||||
return (
|
||||
<Primitive.Trigger
|
||||
{...props}
|
||||
className={skin("bui-select-trigger", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledIcon({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Icon>) {
|
||||
return <Primitive.Icon {...props} className={skin("bui-icon", className)} />;
|
||||
}
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-popup", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledList({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.List>) {
|
||||
return (
|
||||
<Primitive.List {...props} className={skin("bui-option-list", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledItem({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Item>) {
|
||||
return (
|
||||
<Primitive.Item {...props} className={skin("bui-option", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledItemIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.ItemIndicator>) {
|
||||
return (
|
||||
<Primitive.ItemIndicator
|
||||
{...props}
|
||||
className={skin("bui-option-check", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledGroup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Group>) {
|
||||
return (
|
||||
<Primitive.Group {...props} className={skin("bui-stack", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledGroupLabel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.GroupLabel>) {
|
||||
return (
|
||||
<Primitive.GroupLabel
|
||||
{...props}
|
||||
className={skin("bui-group-label", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledSeparator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Separator>) {
|
||||
return (
|
||||
<Primitive.Separator
|
||||
{...props}
|
||||
className={skin("bui-separator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Select behavior primitives with the Buzz visual roles. */
|
||||
export const Select = {
|
||||
Root: Primitive.Root,
|
||||
Trigger: StyledTrigger,
|
||||
Value: Primitive.Value,
|
||||
Icon: StyledIcon,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
List: StyledList,
|
||||
Item: StyledItem,
|
||||
ItemText: Primitive.ItemText,
|
||||
ItemIndicator: StyledItemIndicator,
|
||||
Group: StyledGroup,
|
||||
GroupLabel: StyledGroupLabel,
|
||||
Separator: StyledSeparator,
|
||||
};
|
||||
90
packages/ui/src/primitives/slider.tsx
Normal file
90
packages/ui/src/primitives/slider.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Slider as Primitive } from "@base-ui/react/slider";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-field", className)} />;
|
||||
}
|
||||
|
||||
function StyledLabel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Label>) {
|
||||
return (
|
||||
<Primitive.Label {...props} className={skin("bui-label", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledValue({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Value>) {
|
||||
return (
|
||||
<Primitive.Value
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledControl({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Control>) {
|
||||
return (
|
||||
<Primitive.Control
|
||||
{...props}
|
||||
className={skin("bui-slider-control", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTrack({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Track>) {
|
||||
return (
|
||||
<Primitive.Track
|
||||
{...props}
|
||||
className={skin("bui-slider-track", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Indicator>) {
|
||||
return (
|
||||
<Primitive.Indicator
|
||||
{...props}
|
||||
className={skin("bui-slider-indicator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledThumb({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Thumb>) {
|
||||
return (
|
||||
<Primitive.Thumb
|
||||
{...props}
|
||||
className={skin("bui-slider-thumb", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Slider behavior primitives with the Buzz visual roles. */
|
||||
export const Slider = {
|
||||
Root: StyledRoot,
|
||||
Label: StyledLabel,
|
||||
Value: StyledValue,
|
||||
Control: StyledControl,
|
||||
Track: StyledTrack,
|
||||
Indicator: StyledIndicator,
|
||||
Thumb: StyledThumb,
|
||||
};
|
||||
27
packages/ui/src/primitives/switch.tsx
Normal file
27
packages/ui/src/primitives/switch.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Switch as Primitive } from "@base-ui/react/switch";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return (
|
||||
<Primitive.Root {...props} className={skin("bui-switch", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledThumb({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Thumb>) {
|
||||
return (
|
||||
<Primitive.Thumb
|
||||
{...props}
|
||||
className={skin("bui-switch-thumb", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Switch behavior primitives with the Buzz visual roles. */
|
||||
export const Switch = { Root: StyledRoot, Thumb: StyledThumb };
|
||||
56
packages/ui/src/primitives/tabs.tsx
Normal file
56
packages/ui/src/primitives/tabs.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Tabs as Primitive } from "@base-ui/react/tabs";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-stack", className)} />;
|
||||
}
|
||||
|
||||
function StyledList({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.List>) {
|
||||
return (
|
||||
<Primitive.List {...props} className={skin("bui-tabs-list", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTab({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Tab>) {
|
||||
return <Primitive.Tab {...props} className={skin("bui-tab", className)} />;
|
||||
}
|
||||
|
||||
function StyledPanel({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Panel>) {
|
||||
return (
|
||||
<Primitive.Panel {...props} className={skin("bui-tab-panel", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledIndicator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Indicator>) {
|
||||
return (
|
||||
<Primitive.Indicator
|
||||
{...props}
|
||||
className={skin("bui-tab-indicator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Tabs behavior primitives with the Buzz visual roles. */
|
||||
export const Tabs = {
|
||||
Root: StyledRoot,
|
||||
List: StyledList,
|
||||
Tab: StyledTab,
|
||||
Panel: StyledPanel,
|
||||
Indicator: StyledIndicator,
|
||||
};
|
||||
91
packages/ui/src/primitives/toast.tsx
Normal file
91
packages/ui/src/primitives/toast.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Toast as Primitive } from "@base-ui/react/toast";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledViewport({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Viewport>) {
|
||||
return (
|
||||
<Primitive.Viewport
|
||||
{...props}
|
||||
className={skin("bui-toast-viewport", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return <Primitive.Root {...props} className={skin("bui-toast", className)} />;
|
||||
}
|
||||
|
||||
function StyledContent({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Content>) {
|
||||
return (
|
||||
<Primitive.Content {...props} className={skin("bui-stack", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledTitle({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Title>) {
|
||||
return (
|
||||
<Primitive.Title {...props} className={skin("bui-label", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledDescription({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Description>) {
|
||||
return (
|
||||
<Primitive.Description
|
||||
{...props}
|
||||
className={skin("bui-description", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledClose({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Close>) {
|
||||
return (
|
||||
<Primitive.Close
|
||||
{...props}
|
||||
className={skin("bui-icon-control", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledAction({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Action>) {
|
||||
return (
|
||||
<Primitive.Action
|
||||
{...props}
|
||||
className={skin("bui-disclosure", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Toast behavior primitives with the Buzz visual roles. */
|
||||
export const Toast = {
|
||||
Provider: Primitive.Provider,
|
||||
Portal: Primitive.Portal,
|
||||
Viewport: StyledViewport,
|
||||
Root: StyledRoot,
|
||||
Content: StyledContent,
|
||||
Title: StyledTitle,
|
||||
Description: StyledDescription,
|
||||
Close: StyledClose,
|
||||
Action: StyledAction,
|
||||
useToastManager: Primitive.useToastManager,
|
||||
createToastManager: Primitive.createToastManager,
|
||||
};
|
||||
15
packages/ui/src/primitives/toggle-group.tsx
Normal file
15
packages/ui/src/primitives/toggle-group.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { ToggleGroup as Primitive } from "@base-ui/react/toggle-group";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledToggleGroup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive>) {
|
||||
return (
|
||||
<Primitive {...props} className={skin("bui-toggle-group", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** ToggleGroup behavior primitives with the Buzz visual roles. */
|
||||
export const ToggleGroup = { ToggleGroup: StyledToggleGroup };
|
||||
13
packages/ui/src/primitives/toggle.tsx
Normal file
13
packages/ui/src/primitives/toggle.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Toggle as Primitive } from "@base-ui/react/toggle";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledToggle({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive>) {
|
||||
return <Primitive {...props} className={skin("bui-toggle", className)} />;
|
||||
}
|
||||
|
||||
/** Toggle behavior primitives with the Buzz visual roles. */
|
||||
export const Toggle = { Toggle: StyledToggle };
|
||||
63
packages/ui/src/primitives/toolbar.tsx
Normal file
63
packages/ui/src/primitives/toolbar.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Toolbar as Primitive } from "@base-ui/react/toolbar";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledRoot({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Root>) {
|
||||
return (
|
||||
<Primitive.Root {...props} className={skin("bui-toolbar", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledGroup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Group>) {
|
||||
return (
|
||||
<Primitive.Group {...props} className={skin("bui-toolbar", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledButton({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Button>) {
|
||||
return (
|
||||
<Primitive.Button {...props} className={skin("bui-toggle", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
function StyledLink({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Link>) {
|
||||
return (
|
||||
<Primitive.Link
|
||||
{...props}
|
||||
className={skin("bui-navigation-link", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledSeparator({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Separator>) {
|
||||
return (
|
||||
<Primitive.Separator
|
||||
{...props}
|
||||
className={skin("bui-separator", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Toolbar behavior primitives with the Buzz visual roles. */
|
||||
export const Toolbar = {
|
||||
Root: StyledRoot,
|
||||
Group: StyledGroup,
|
||||
Button: StyledButton,
|
||||
Link: StyledLink,
|
||||
Separator: StyledSeparator,
|
||||
};
|
||||
34
packages/ui/src/primitives/tooltip.tsx
Normal file
34
packages/ui/src/primitives/tooltip.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Tooltip as Primitive } from "@base-ui/react/tooltip";
|
||||
import { skin } from "../classes";
|
||||
|
||||
function StyledPositioner({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Positioner>) {
|
||||
return (
|
||||
<Primitive.Positioner
|
||||
{...props}
|
||||
className={skin("bui-positioner", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function StyledPopup({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Primitive.Popup>) {
|
||||
return (
|
||||
<Primitive.Popup {...props} className={skin("bui-tooltip", className)} />
|
||||
);
|
||||
}
|
||||
|
||||
/** Tooltip behavior primitives with the Buzz visual roles. */
|
||||
export const Tooltip = {
|
||||
Provider: Primitive.Provider,
|
||||
Root: Primitive.Root,
|
||||
Trigger: Primitive.Trigger,
|
||||
Portal: Primitive.Portal,
|
||||
Positioner: StyledPositioner,
|
||||
Popup: StyledPopup,
|
||||
};
|
||||
13
packages/ui/src/resizable.tsx
Normal file
13
packages/ui/src/resizable.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Group, Panel, Separator } from "react-resizable-panels";
|
||||
import type { ComponentProps } from "react";
|
||||
import { cx } from "./classes";
|
||||
function Handle(props: ComponentProps<typeof Separator>) {
|
||||
return (
|
||||
<Separator
|
||||
{...props}
|
||||
className={cx("bui-resize-handle", props.className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
/** Resizable regions with pointer and keyboard support. Sizes use the public panel API. */
|
||||
export const Resizable = { Group, Panel, Handle };
|
||||
8
packages/ui/src/sheet.tsx
Normal file
8
packages/ui/src/sheet.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Dialog } from "./primitives/dialog";
|
||||
import { skin } from "./classes";
|
||||
function Popup({ className, ...props }: ComponentProps<typeof Dialog.Popup>) {
|
||||
return <Dialog.Popup {...props} className={skin("bui-sheet", className)} />;
|
||||
}
|
||||
/** A side sheet uses the same focus, dismissal, title, and description contract as Dialog. */
|
||||
export const Sheet = { ...Dialog, Popup };
|
||||
160
packages/ui/src/styles.css
Normal file
160
packages/ui/src/styles.css
Normal file
@@ -0,0 +1,160 @@
|
||||
@import "tailwindcss";
|
||||
@import "@buzz/design-tokens/tokens.css";
|
||||
@import "@buzz/design-tokens/typography.css";
|
||||
@import "@buzz/design-tokens/foundations.css";
|
||||
|
||||
@import "./styles/actions.css";
|
||||
@import "./styles/controls.css";
|
||||
@import "./styles/overlays.css";
|
||||
@import "./styles/surfaces.css";
|
||||
@import "./styles/layout.css";
|
||||
@keyframes bui-spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes bui-pulse {
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.bui-spin,
|
||||
.bui-loading,
|
||||
.bui-skeleton {
|
||||
animation: none;
|
||||
}
|
||||
.bui-popup,
|
||||
.bui-popover,
|
||||
.bui-button,
|
||||
.bui-switch-thumb {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.bui-sheet {
|
||||
left: auto;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: none;
|
||||
height: 100dvh;
|
||||
max-height: 100dvh;
|
||||
width: min(28rem, 100vw);
|
||||
border-radius: var(--radius-sheet) 0 0 var(--radius-sheet);
|
||||
align-content: start;
|
||||
}
|
||||
.bui-calendar {
|
||||
--rdp-accent-color: var(--bg-inverse);
|
||||
color: var(--text-primary);
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.bui-calendar table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.bui-calendar .rdp-month_caption {
|
||||
@apply text-label;
|
||||
min-height: var(--control-md);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-inline: var(--space-control-gap);
|
||||
}
|
||||
.bui-calendar .rdp-nav {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
}
|
||||
.bui-calendar button {
|
||||
cursor: pointer;
|
||||
border-radius: var(--radius-pill);
|
||||
min-width: 2.25rem;
|
||||
min-height: 2.25rem;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.bui-calendar button:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
.bui-calendar button:focus-visible {
|
||||
outline: 2px solid var(--ring-focus);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
.bui-calendar svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
.bui-calendar .rdp-weekday {
|
||||
@apply text-meta text-tertiary;
|
||||
height: var(--control-sm);
|
||||
}
|
||||
.bui-calendar .rdp-day {
|
||||
@apply text-body;
|
||||
padding: 0.125rem;
|
||||
text-align: center;
|
||||
}
|
||||
.bui-calendar .rdp-selected button {
|
||||
background: var(--bg-inverse);
|
||||
color: var(--text-on-inverse);
|
||||
}
|
||||
.bui-calendar .rdp-today:not(.rdp-selected) button {
|
||||
box-shadow: inset 0 0 0 1px var(--text-primary);
|
||||
}
|
||||
.bui-calendar .rdp-disabled {
|
||||
color: var(--text-disabled);
|
||||
}
|
||||
.bui-calendar .rdp-outside {
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
.bui-calendar .rdp-range_middle {
|
||||
background: var(--bg-inset);
|
||||
}
|
||||
.bui-resize-handle {
|
||||
background: var(--border-tertiary);
|
||||
border-radius: var(--radius-pill);
|
||||
width: 0.375rem;
|
||||
margin-inline: var(--space-control-gap);
|
||||
}
|
||||
.bui-resize-handle:hover,
|
||||
.bui-resize-handle:focus-visible {
|
||||
background: var(--border-primary);
|
||||
}
|
||||
.bui-sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
.bui-chart {
|
||||
width: 100%;
|
||||
border-spacing: 0 0.5rem;
|
||||
border-collapse: separate;
|
||||
}
|
||||
.bui-chart th {
|
||||
@apply text-caption;
|
||||
width: 25%;
|
||||
text-align: start;
|
||||
padding-inline-end: var(--space-control-gap);
|
||||
}
|
||||
.bui-chart td {
|
||||
@apply text-caption;
|
||||
position: relative;
|
||||
padding: var(--space-control-gap);
|
||||
isolation: isolate;
|
||||
}
|
||||
.bui-chart-bar {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
background: var(--bg-inset);
|
||||
border-radius: var(--radius-control);
|
||||
}
|
||||
}
|
||||
148
packages/ui/src/styles/actions.css
Normal file
148
packages/ui/src/styles/actions.css
Normal file
@@ -0,0 +1,148 @@
|
||||
@layer components {
|
||||
.bui-stack,
|
||||
.bui-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-control-gap);
|
||||
min-width: 0;
|
||||
}
|
||||
.bui-inline,
|
||||
.bui-toolbar,
|
||||
.bui-chips,
|
||||
.bui-otp,
|
||||
.bui-toggle-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-control-gap);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.bui-reset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.bui-label {
|
||||
@apply text-label text-primary;
|
||||
}
|
||||
.bui-title {
|
||||
@apply text-heading text-primary;
|
||||
margin: 0;
|
||||
}
|
||||
.bui-description {
|
||||
@apply text-caption text-secondary;
|
||||
margin: 0;
|
||||
}
|
||||
.bui-field-error {
|
||||
@apply text-caption text-danger;
|
||||
}
|
||||
.bui-button {
|
||||
@apply text-label;
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--space-control-gap);
|
||||
min-height: var(--control-md);
|
||||
padding: 0 var(--space-action-inset);
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-inverse);
|
||||
color: var(--text-on-inverse);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background var(--duration-state),
|
||||
transform var(--duration-state) var(--ease-standard);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.bui-button-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--space-control-gap);
|
||||
}
|
||||
.bui-button svg,
|
||||
.bui-icon,
|
||||
.bui-inline > svg {
|
||||
width: 1.125em;
|
||||
height: 1.125em;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.bui-button[data-size="sm"] {
|
||||
min-height: var(--control-sm);
|
||||
padding-inline: var(--space-control-inset);
|
||||
}
|
||||
.bui-button[data-size="lg"] {
|
||||
min-height: var(--control-lg);
|
||||
padding-inline: var(--space-panel-inset);
|
||||
}
|
||||
.bui-button[data-variant="secondary"] {
|
||||
background: var(--bg-inset);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.bui-button[data-variant="outline"] {
|
||||
background: transparent;
|
||||
color: var(--text-primary);
|
||||
border-color: var(--border-primary);
|
||||
}
|
||||
.bui-button[data-variant="ghost"],
|
||||
.bui-button[data-variant="link"] {
|
||||
background: transparent;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.bui-button[data-variant="link"] {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.2em;
|
||||
}
|
||||
.bui-button[data-variant="danger"] {
|
||||
background: var(--bg-danger);
|
||||
color: var(--text-on-danger);
|
||||
}
|
||||
.bui-button:hover:not(:disabled) {
|
||||
background: var(--bg-inverse-hover);
|
||||
}
|
||||
.bui-button[data-variant="secondary"]:hover:not(:disabled),
|
||||
.bui-button[data-variant="outline"]:hover:not(:disabled),
|
||||
.bui-button[data-variant="ghost"]:hover:not(:disabled),
|
||||
.bui-button[data-variant="link"]:hover:not(:disabled) {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
.bui-button[data-variant="danger"]:hover:not(:disabled) {
|
||||
background: var(--bg-danger);
|
||||
}
|
||||
.bui-button:active:not(:disabled) {
|
||||
transform: scale(var(--press-scale));
|
||||
}
|
||||
.bui-button:disabled {
|
||||
cursor: not-allowed;
|
||||
background: var(--bg-inset);
|
||||
color: var(--text-disabled);
|
||||
}
|
||||
.bui-button[data-loading] {
|
||||
color: var(--text-on-inverse);
|
||||
background: var(--bg-inverse);
|
||||
}
|
||||
.bui-button[data-loading] .bui-button-label {
|
||||
opacity: 0;
|
||||
}
|
||||
.bui-loading {
|
||||
position: absolute;
|
||||
animation: bui-spin 1s linear infinite;
|
||||
}
|
||||
.bui-icon-button {
|
||||
width: var(--control-md);
|
||||
padding: 0;
|
||||
}
|
||||
.bui-icon-button[data-size="sm"] {
|
||||
width: var(--control-sm);
|
||||
padding: 0;
|
||||
}
|
||||
.bui-icon-button[data-size="lg"] {
|
||||
width: var(--control-lg);
|
||||
padding: 0;
|
||||
}
|
||||
:where([class*="bui-"]):focus-visible {
|
||||
outline: 2px solid var(--ring-focus);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
}
|
||||
176
packages/ui/src/styles/controls.css
Normal file
176
packages/ui/src/styles/controls.css
Normal file
@@ -0,0 +1,176 @@
|
||||
@layer components {
|
||||
.bui-input,
|
||||
.bui-select-trigger,
|
||||
.bui-number-group,
|
||||
.bui-otp-input {
|
||||
@apply text-body;
|
||||
width: 100%;
|
||||
min-height: var(--control-md);
|
||||
border: 1px solid var(--border-primary);
|
||||
border-radius: var(--radius-control);
|
||||
padding: var(--space-control-gap) var(--space-control-inset);
|
||||
background: var(--bg-panel);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.bui-input::placeholder {
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
.bui-input[data-invalid],
|
||||
.bui-input[aria-invalid="true"] {
|
||||
border-color: var(--text-danger);
|
||||
}
|
||||
.bui-input:disabled {
|
||||
background: var(--bg-inset);
|
||||
color: var(--text-disabled);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.bui-textarea {
|
||||
min-height: 7rem;
|
||||
resize: vertical;
|
||||
}
|
||||
.bui-input-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-control-gap);
|
||||
}
|
||||
.bui-fieldset {
|
||||
border: 0;
|
||||
display: grid;
|
||||
gap: var(--space-control-inset);
|
||||
padding: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
.bui-fieldset legend {
|
||||
margin-bottom: var(--space-control-inset);
|
||||
}
|
||||
.bui-checkbox,
|
||||
.bui-radio {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
border: 1px solid var(--text-tertiary);
|
||||
border-radius: 0.375rem;
|
||||
background: var(--bg-panel);
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.bui-checkbox[data-checked],
|
||||
.bui-checkbox[data-indeterminate] {
|
||||
background: var(--bg-inverse);
|
||||
border-color: var(--bg-inverse);
|
||||
color: var(--text-on-inverse);
|
||||
}
|
||||
.bui-check-indicator {
|
||||
display: flex;
|
||||
}
|
||||
.bui-check-indicator svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
.bui-radio {
|
||||
border-radius: var(--radius-pill);
|
||||
}
|
||||
.bui-radio-indicator {
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-inverse);
|
||||
}
|
||||
.bui-switch {
|
||||
width: 2.75rem;
|
||||
height: 1.625rem;
|
||||
border-radius: var(--radius-pill);
|
||||
padding: 0.1875rem;
|
||||
background: var(--border-primary);
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.bui-switch[data-checked] {
|
||||
background: var(--bg-inverse);
|
||||
}
|
||||
.bui-switch-thumb {
|
||||
display: block;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-panel);
|
||||
transition: transform var(--duration-state);
|
||||
}
|
||||
.bui-switch[data-checked] .bui-switch-thumb {
|
||||
transform: translateX(1.125rem);
|
||||
}
|
||||
.bui-switch[data-disabled],
|
||||
.bui-checkbox[data-disabled],
|
||||
.bui-radio[data-disabled] {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.bui-tabs-list {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
background: var(--bg-inset);
|
||||
padding: 0.25rem;
|
||||
border-radius: var(--radius-pill);
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.bui-tab,
|
||||
.bui-toggle,
|
||||
.bui-disclosure,
|
||||
.bui-navigation-link {
|
||||
@apply text-label;
|
||||
border: 0;
|
||||
padding: var(--space-control-gap) var(--space-control-inset);
|
||||
border-radius: var(--radius-pill);
|
||||
color: var(--text-secondary);
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
.bui-tab[data-active],
|
||||
.bui-toggle[data-pressed],
|
||||
.bui-navigation-link[aria-current="page"] {
|
||||
background: var(--bg-panel);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.bui-tab:not([data-active]):hover,
|
||||
.bui-toggle:hover,
|
||||
.bui-disclosure:hover,
|
||||
.bui-navigation-link:hover {
|
||||
background: var(--bg-hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.bui-tab-panel {
|
||||
padding-block: var(--space-control-inset);
|
||||
}
|
||||
.bui-accordion-item {
|
||||
border-bottom: 1px solid var(--border-tertiary);
|
||||
}
|
||||
.bui-accordion-trigger {
|
||||
@apply text-label;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding-block: var(--space-control-inset);
|
||||
background: transparent;
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
text-align: start;
|
||||
}
|
||||
.bui-accordion-trigger svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
transition: transform var(--duration-state);
|
||||
}
|
||||
.bui-accordion-trigger[data-panel-open] svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.bui-accordion-panel {
|
||||
@apply text-body text-secondary;
|
||||
padding-block: var(--space-control-gap);
|
||||
}
|
||||
}
|
||||
150
packages/ui/src/styles/layout.css
Normal file
150
packages/ui/src/styles/layout.css
Normal file
@@ -0,0 +1,150 @@
|
||||
@layer components {
|
||||
.bui-number-group {
|
||||
display: flex;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
width: fit-content;
|
||||
}
|
||||
.bui-number-input {
|
||||
width: 5rem;
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
.bui-icon-control {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: var(--space-control-gap);
|
||||
border-radius: var(--radius-control);
|
||||
cursor: pointer;
|
||||
min-width: var(--control-sm);
|
||||
min-height: var(--control-sm);
|
||||
}
|
||||
.bui-icon-control:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
.bui-icon-control svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
.bui-otp-input {
|
||||
width: 2.5rem;
|
||||
text-align: center;
|
||||
padding: var(--space-control-gap);
|
||||
}
|
||||
.bui-scroll-area {
|
||||
position: relative;
|
||||
height: 12rem;
|
||||
}
|
||||
.bui-scroll-viewport {
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
.bui-scrollbar {
|
||||
display: flex;
|
||||
width: 0.5rem;
|
||||
margin: 0.25rem;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-inset);
|
||||
}
|
||||
.bui-scroll-thumb {
|
||||
width: 100%;
|
||||
background: var(--border-primary);
|
||||
border-radius: inherit;
|
||||
}
|
||||
.bui-toast-viewport {
|
||||
position: fixed;
|
||||
bottom: var(--space-panel-inset);
|
||||
right: var(--space-panel-inset);
|
||||
width: min(22rem, calc(100vw - 3rem));
|
||||
z-index: var(--layer-toast);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-control-gap);
|
||||
}
|
||||
.bui-toast {
|
||||
background: var(--bg-float);
|
||||
border: 1px solid var(--border-secondary);
|
||||
border-radius: var(--radius-menu);
|
||||
padding: var(--space-control-inset);
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.bui-skeleton {
|
||||
min-height: var(--control-md);
|
||||
border-radius: var(--radius-control);
|
||||
background: var(--bg-inset);
|
||||
animation: bui-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
.bui-spin {
|
||||
animation: bui-spin 1s linear infinite;
|
||||
}
|
||||
.bui-empty {
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
text-align: center;
|
||||
gap: var(--space-control-inset);
|
||||
padding: var(--space-page-inset);
|
||||
}
|
||||
.bui-table-scroll {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.bui-table {
|
||||
@apply text-body;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
text-align: start;
|
||||
}
|
||||
.bui-table th {
|
||||
@apply text-label text-secondary;
|
||||
}
|
||||
.bui-table th,
|
||||
.bui-table td {
|
||||
padding: var(--space-control-inset);
|
||||
border-bottom: 1px solid var(--border-tertiary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.bui-table caption {
|
||||
text-align: start;
|
||||
margin-bottom: var(--space-control-inset);
|
||||
}
|
||||
.bui-breadcrumb {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-control-gap);
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
.bui-breadcrumb li + li::before {
|
||||
content: "/";
|
||||
color: var(--text-tertiary);
|
||||
padding-inline-end: var(--space-control-gap);
|
||||
}
|
||||
.bui-sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
padding: var(--space-control-inset);
|
||||
border-radius: var(--radius-container);
|
||||
background: var(--bg-inset);
|
||||
}
|
||||
.bui-sidebar a {
|
||||
@apply text-label;
|
||||
padding: var(--space-control-gap) var(--space-control-inset);
|
||||
border-radius: var(--radius-control);
|
||||
}
|
||||
.bui-sidebar a[aria-current="page"] {
|
||||
background: var(--bg-panel);
|
||||
}
|
||||
.bui-context-target {
|
||||
border: 1px dashed var(--border-primary);
|
||||
border-radius: var(--radius-menu);
|
||||
padding: var(--space-page-inset);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
152
packages/ui/src/styles/overlays.css
Normal file
152
packages/ui/src/styles/overlays.css
Normal file
@@ -0,0 +1,152 @@
|
||||
@layer components {
|
||||
.bui-positioner {
|
||||
z-index: var(--layer-floating);
|
||||
outline: none;
|
||||
max-width: calc(100vw - 2rem);
|
||||
}
|
||||
.bui-popup,
|
||||
.bui-popover {
|
||||
background: var(--bg-float);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-tertiary);
|
||||
border-radius: var(--radius-menu);
|
||||
padding: var(--space-control-gap);
|
||||
box-shadow: var(--shadow-sm);
|
||||
min-width: 12rem;
|
||||
max-width: min(26rem, calc(100vw - 2rem));
|
||||
max-height: var(--available-height, 70vh);
|
||||
overflow: auto;
|
||||
transform-origin: var(--transform-origin);
|
||||
transition:
|
||||
opacity var(--duration-enter),
|
||||
transform var(--duration-enter) var(--ease-standard);
|
||||
}
|
||||
.bui-popup[data-starting-style],
|
||||
.bui-popup[data-ending-style],
|
||||
.bui-popover[data-starting-style],
|
||||
.bui-popover[data-ending-style] {
|
||||
opacity: 0;
|
||||
transform: translateY(-0.25rem);
|
||||
}
|
||||
.bui-popover {
|
||||
padding: var(--space-panel-inset);
|
||||
display: grid;
|
||||
gap: var(--space-control-gap);
|
||||
}
|
||||
.bui-option {
|
||||
@apply text-label;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-control-gap);
|
||||
padding: var(--space-control-gap) var(--space-control-inset);
|
||||
border-radius: var(--radius-control);
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
.bui-option[data-highlighted],
|
||||
.bui-option:focus-visible {
|
||||
background: var(--bg-hover);
|
||||
outline: 2px solid var(--ring-focus);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
.bui-option[data-disabled] {
|
||||
color: var(--text-disabled);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.bui-option-check {
|
||||
display: flex;
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
.bui-option-check svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
.bui-option-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.bui-group-label {
|
||||
@apply text-meta text-tertiary;
|
||||
padding: var(--space-control-inset);
|
||||
}
|
||||
.bui-select-trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-control-gap);
|
||||
width: fit-content;
|
||||
min-width: 12rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.bui-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: var(--overlay-scrim);
|
||||
z-index: var(--layer-dialog);
|
||||
transition: opacity var(--duration-enter);
|
||||
}
|
||||
.bui-backdrop[data-starting-style],
|
||||
.bui-backdrop[data-ending-style] {
|
||||
opacity: 0;
|
||||
}
|
||||
.bui-dialog-viewport {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
overflow-y: auto;
|
||||
padding: var(--space-panel-inset);
|
||||
z-index: var(--layer-dialog);
|
||||
}
|
||||
.bui-dialog {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: grid;
|
||||
gap: var(--space-section-gap);
|
||||
width: min(28rem, calc(100vw - 2rem));
|
||||
max-height: calc(100dvh - 2rem);
|
||||
overflow-y: auto;
|
||||
padding: var(--space-panel-inset);
|
||||
border-radius: var(--radius-overlay);
|
||||
background: var(--bg-float);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-tertiary);
|
||||
box-shadow: var(--shadow-sm);
|
||||
z-index: var(--layer-dialog);
|
||||
outline: none;
|
||||
}
|
||||
.bui-dialog-viewport .bui-dialog {
|
||||
position: relative;
|
||||
left: auto;
|
||||
top: auto;
|
||||
transform: none;
|
||||
}
|
||||
.bui-drawer-viewport {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
z-index: var(--layer-dialog);
|
||||
}
|
||||
.bui-drawer {
|
||||
width: 100%;
|
||||
max-height: 85dvh;
|
||||
overflow-y: auto;
|
||||
background: var(--bg-float);
|
||||
color: var(--text-primary);
|
||||
padding: var(--space-page-inset);
|
||||
border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
|
||||
outline: none;
|
||||
}
|
||||
.bui-tooltip {
|
||||
@apply text-caption;
|
||||
padding: var(--space-tooltip-block) var(--space-control-gap);
|
||||
background: var(--bg-inverse);
|
||||
color: var(--text-on-inverse);
|
||||
border-radius: var(--radius-notice);
|
||||
max-width: 18rem;
|
||||
}
|
||||
}
|
||||
105
packages/ui/src/styles/surfaces.css
Normal file
105
packages/ui/src/styles/surfaces.css
Normal file
@@ -0,0 +1,105 @@
|
||||
@layer components {
|
||||
.bui-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-section-gap);
|
||||
border-radius: var(--radius-container);
|
||||
background: var(--bg-panel);
|
||||
border: 1px solid var(--border-tertiary);
|
||||
padding: var(--space-panel-inset);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.bui-badge,
|
||||
.bui-chip {
|
||||
@apply text-meta;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-control-gap);
|
||||
padding: 0.375rem 0.625rem;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-inset);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
:is(.bui-badge, .bui-alert)[data-tone="accent"] {
|
||||
background: var(--bg-accent-tint);
|
||||
color: var(--text-accent);
|
||||
}
|
||||
:is(.bui-badge, .bui-alert)[data-tone="success"] {
|
||||
background: var(--bg-success-tint);
|
||||
color: var(--text-success);
|
||||
}
|
||||
:is(.bui-badge, .bui-alert)[data-tone="warning"] {
|
||||
background: var(--bg-warning-tint);
|
||||
color: var(--text-warning);
|
||||
}
|
||||
:is(.bui-badge, .bui-alert)[data-tone="danger"] {
|
||||
background: var(--bg-danger-tint);
|
||||
color: var(--text-danger);
|
||||
}
|
||||
:is(.bui-badge, .bui-alert)[data-tone="info"] {
|
||||
background: var(--bg-info-tint);
|
||||
color: var(--text-info);
|
||||
}
|
||||
.bui-alert {
|
||||
@apply text-body;
|
||||
padding: var(--space-control-inset);
|
||||
border-radius: var(--radius-notice);
|
||||
}
|
||||
.bui-avatar {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--control-md);
|
||||
height: var(--control-md);
|
||||
overflow: hidden;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-inset);
|
||||
}
|
||||
.bui-avatar-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.bui-avatar-fallback {
|
||||
@apply text-label;
|
||||
}
|
||||
.bui-separator {
|
||||
border: 0;
|
||||
background: var(--border-tertiary);
|
||||
height: 1px;
|
||||
margin-block: var(--space-control-gap);
|
||||
}
|
||||
.bui-slider-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: var(--control-sm);
|
||||
min-width: 10rem;
|
||||
touch-action: none;
|
||||
user-select: none;
|
||||
}
|
||||
.bui-slider-track,
|
||||
.bui-progress-track {
|
||||
position: relative;
|
||||
height: 0.375rem;
|
||||
width: 100%;
|
||||
background: var(--bg-inset);
|
||||
border-radius: var(--radius-pill);
|
||||
overflow: hidden;
|
||||
}
|
||||
.bui-slider-track {
|
||||
overflow: visible;
|
||||
}
|
||||
.bui-slider-indicator,
|
||||
.bui-progress-indicator {
|
||||
background: var(--bg-inverse);
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
}
|
||||
.bui-slider-thumb {
|
||||
width: 1.125rem;
|
||||
height: 1.125rem;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-panel);
|
||||
border: 2px solid var(--bg-inverse);
|
||||
}
|
||||
}
|
||||
114
packages/ui/src/surfaces.tsx
Normal file
114
packages/ui/src/surfaces.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
import type { ComponentProps, ReactNode } from "react";
|
||||
import { LoaderCircle } from "lucide-react";
|
||||
import { cx } from "./classes";
|
||||
/** A contained group; use rows instead when content forms a list. */
|
||||
export function Card({ className, ...props }: ComponentProps<"section">) {
|
||||
return <section {...props} className={cx("bui-card", className)} />;
|
||||
}
|
||||
/** A concise status label; its text carries meaning in addition to color. */
|
||||
export function Badge({
|
||||
tone = "neutral",
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<"span"> & {
|
||||
tone?: "neutral" | "accent" | "success" | "warning" | "danger" | "info";
|
||||
}) {
|
||||
return (
|
||||
<span {...props} data-tone={tone} className={cx("bui-badge", className)} />
|
||||
);
|
||||
}
|
||||
/** An inline notice. Set role=alert only for newly occurring urgent errors. */
|
||||
export function Alert({
|
||||
tone = "info",
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<"div"> & {
|
||||
tone?: "info" | "success" | "warning" | "danger";
|
||||
}) {
|
||||
return (
|
||||
<div {...props} data-tone={tone} className={cx("bui-alert", className)} />
|
||||
);
|
||||
}
|
||||
/** Decorative placeholder; announce loading once on its owning region. */
|
||||
export function Skeleton({ className, ...props }: ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
aria-hidden="true"
|
||||
className={cx("bui-skeleton", className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
/** A named loading status with a decorative animated icon. */
|
||||
export function Spinner({ label = "Loading" }: { label?: string }) {
|
||||
return (
|
||||
<span role="status" className="bui-inline">
|
||||
<LoaderCircle aria-hidden="true" className="bui-spin" />
|
||||
<span>{label}</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
/** A stable media frame with a caller-selected ratio. */
|
||||
export function AspectRatio({
|
||||
ratio = 16 / 9,
|
||||
style,
|
||||
...props
|
||||
}: ComponentProps<"div"> & { ratio?: number }) {
|
||||
return <div {...props} style={{ ...style, aspectRatio: ratio }} />;
|
||||
}
|
||||
/** A semantic table wrapper that allows horizontal scrolling on narrow screens. */
|
||||
export function Table({ children, ...props }: ComponentProps<"table">) {
|
||||
return (
|
||||
<div className="bui-table-scroll">
|
||||
<table {...props} className={cx("bui-table", props.className)}>
|
||||
{children}
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
/** A quiet division between related regions. */
|
||||
export function Separator(props: ComponentProps<"hr">) {
|
||||
return <hr {...props} className={cx("bui-separator", props.className)} />;
|
||||
}
|
||||
/** Empty states explain purpose and provide an explicit next action. */
|
||||
export function EmptyState({
|
||||
title,
|
||||
description,
|
||||
action,
|
||||
}: {
|
||||
title: string;
|
||||
description: string;
|
||||
action?: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="bui-empty">
|
||||
<h3 className="bui-label">{title}</h3>
|
||||
<p className="bui-description">{description}</p>
|
||||
{action}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
/** Related destinations with one named navigation landmark. */
|
||||
export function Breadcrumb({ children, ...props }: ComponentProps<"nav">) {
|
||||
return (
|
||||
<nav aria-label="Breadcrumb" {...props}>
|
||||
<ol className="bui-breadcrumb">{children}</ol>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
/** A side navigation region; selection is represented by aria-current on links. */
|
||||
export function Sidebar(
|
||||
props: ComponentProps<"nav"> & { "aria-label": string },
|
||||
) {
|
||||
return <nav {...props} className={cx("bui-sidebar", props.className)} />;
|
||||
}
|
||||
/** Page navigation; callers own links and mark the current one with aria-current=page. */
|
||||
export function Pagination(props: ComponentProps<"nav">) {
|
||||
return (
|
||||
<nav
|
||||
aria-label="Pagination"
|
||||
{...props}
|
||||
className={cx("bui-toolbar", props.className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
18
packages/ui/tsconfig.json
Normal file
18
packages/ui/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
21
packages/ui/vite.config.ts
Normal file
21
packages/ui/vite.config.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { defineConfig } from "vite";
|
||||
export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: "src/index.ts",
|
||||
formats: ["es"],
|
||||
fileName: "index",
|
||||
cssFileName: "ui",
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [
|
||||
/^react($|\/)/,
|
||||
/^react-dom($|\/)/,
|
||||
/^@base-ui\//,
|
||||
/^lucide-react/,
|
||||
/^@daypicker\//,
|
||||
/^react-resizable-panels/,
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
114
pnpm-lock.yaml
generated
114
pnpm-lock.yaml
generated
@@ -310,12 +310,12 @@ importers:
|
||||
|
||||
desktop-next:
|
||||
dependencies:
|
||||
'@base-ui-components/react':
|
||||
specifier: 1.0.0-rc.0
|
||||
version: 1.0.0-rc.0(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||
'@buzz/design-tokens':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/design-tokens
|
||||
'@buzz/ui':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/ui
|
||||
'@fontsource-variable/inter':
|
||||
specifier: ^5.2.8
|
||||
version: 5.2.8
|
||||
@@ -325,6 +325,9 @@ importers:
|
||||
'@tanstack/react-router':
|
||||
specifier: ^1.168.10
|
||||
version: 1.170.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||
lucide-react:
|
||||
specifier: ^1.0.0
|
||||
version: 1.16.0(react@19.2.8)
|
||||
react:
|
||||
specifier: ^19.1.0
|
||||
version: 19.2.8
|
||||
@@ -332,6 +335,9 @@ importers:
|
||||
specifier: ^19.1.0
|
||||
version: 19.2.8(react@19.2.8)
|
||||
devDependencies:
|
||||
'@playwright/test':
|
||||
specifier: ^1.58.2
|
||||
version: 1.60.0
|
||||
'@tailwindcss/postcss':
|
||||
specifier: ^4.3.0
|
||||
version: 4.3.0
|
||||
@@ -363,6 +369,49 @@ importers:
|
||||
specifier: 4.3.0
|
||||
version: 4.3.0
|
||||
|
||||
packages/ui:
|
||||
dependencies:
|
||||
'@base-ui/react':
|
||||
specifier: 1.7.0
|
||||
version: 1.7.0(@date-fns/tz@1.5.0)(@types/react@19.2.18)(date-fns@4.4.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||
'@buzz/design-tokens':
|
||||
specifier: workspace:*
|
||||
version: link:../design-tokens
|
||||
'@daypicker/react':
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1(@types/react@19.2.18)(react@19.2.8)
|
||||
lucide-react:
|
||||
specifier: ^1.0.0
|
||||
version: 1.16.0(react@19.2.8)
|
||||
react-resizable-panels:
|
||||
specifier: ^4.12.4
|
||||
version: 4.12.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||
devDependencies:
|
||||
'@tailwindcss/postcss':
|
||||
specifier: ^4.3.0
|
||||
version: 4.3.0
|
||||
'@types/react':
|
||||
specifier: ^19.1.8
|
||||
version: 19.2.18
|
||||
'@types/react-dom':
|
||||
specifier: ^19.1.6
|
||||
version: 19.2.4(@types/react@19.2.18)
|
||||
react:
|
||||
specifier: ^19.1.0
|
||||
version: 19.2.8
|
||||
react-dom:
|
||||
specifier: ^19.1.0
|
||||
version: 19.2.8(react@19.2.8)
|
||||
tailwindcss:
|
||||
specifier: ^4.3.0
|
||||
version: 4.3.0
|
||||
typescript:
|
||||
specifier: ~6.0.0
|
||||
version: 6.0.3
|
||||
vite:
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.16(@types/node@25.6.0)(jiti@2.7.0)(yaml@2.9.0)
|
||||
|
||||
web:
|
||||
dependencies:
|
||||
'@fontsource-variable/inter':
|
||||
@@ -568,21 +617,25 @@ packages:
|
||||
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@base-ui-components/react@1.0.0-rc.0':
|
||||
resolution: {integrity: sha512-9lhUFbJcbXvc9KulLev1WTFxS/alJRBWDH/ibKSQaNvmDwMFS2gKp1sTeeldYSfKuS/KC1w2MZutc0wHu2hRHQ==}
|
||||
'@base-ui/react@1.7.0':
|
||||
resolution: {integrity: sha512-j+8QjX44C32jrXD/qyEAGpFr70FRpGL2CY61mQd9nBPWN737CK0xxD1ceJ055rW4RtdvFDT1e7otzdlfxvsYug==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
deprecated: Package was renamed to @base-ui/react
|
||||
peerDependencies:
|
||||
'@date-fns/tz': ^1.2.0
|
||||
'@types/react': ^17 || ^18 || ^19
|
||||
date-fns: ^4.0.0
|
||||
react: ^17 || ^18 || ^19
|
||||
react-dom: ^17 || ^18 || ^19
|
||||
peerDependenciesMeta:
|
||||
'@date-fns/tz':
|
||||
optional: true
|
||||
'@types/react':
|
||||
optional: true
|
||||
date-fns:
|
||||
optional: true
|
||||
|
||||
'@base-ui-components/utils@0.2.2':
|
||||
resolution: {integrity: sha512-rNJCD6TFy3OSRDKVHJDzLpxO3esTV1/drRtWNUpe7rCpPN9HZVHUCuP+6rdDYDGWfXnQHbqi05xOyRP2iZAlkw==}
|
||||
deprecated: Package was renamed to @base-ui/utils
|
||||
'@base-ui/utils@0.3.2':
|
||||
resolution: {integrity: sha512-oWy1aq/I2GmYjpl4PhEAhzflF8VPGKgZeq0xAWTbfD5KBWyxcN0ZP2+WHSUm/5Z6lVMBDLReLcoXwSYoRc/zNQ==}
|
||||
peerDependencies:
|
||||
'@types/react': ^17 || ^18 || ^19
|
||||
react: ^17 || ^18 || ^19
|
||||
@@ -687,6 +740,16 @@ packages:
|
||||
'@date-fns/tz@1.5.0':
|
||||
resolution: {integrity: sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg==}
|
||||
|
||||
'@daypicker/react@10.0.1':
|
||||
resolution: {integrity: sha512-lH4YQz4iMBWP8hsI1bD9Eg0T7t503IkSUR/WDGGkV5mKZvwVv+ukCkJz7yN+uVFBv7vHTK+ww7a5EvlkeFwPYQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@types/react': '>=16.8.0'
|
||||
react: '>=16.8.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@dnd-kit/accessibility@3.1.1':
|
||||
resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
|
||||
peerDependencies:
|
||||
@@ -3309,6 +3372,12 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
react-resizable-panels@4.12.4:
|
||||
resolution: {integrity: sha512-SOsSj4e9U7vxL15MbgTfl35IO4vxSW4Xb0b1gtJVbRPWv7FOezcgOA00Mi0jP8XqC3y7jOQxpsGs/9zLKHPitA==}
|
||||
peerDependencies:
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
react-dom: ^18.0.0 || ^19.0.0
|
||||
|
||||
react-style-singleton@2.2.3:
|
||||
resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -3483,9 +3552,6 @@ packages:
|
||||
symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
|
||||
tabbable@6.5.0:
|
||||
resolution: {integrity: sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==}
|
||||
|
||||
tailwind-merge@3.6.0:
|
||||
resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==}
|
||||
|
||||
@@ -3963,21 +4029,21 @@ snapshots:
|
||||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.29.7
|
||||
|
||||
'@base-ui-components/react@1.0.0-rc.0(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
|
||||
'@base-ui/react@1.7.0(@date-fns/tz@1.5.0)(@types/react@19.2.18)(date-fns@4.4.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.7
|
||||
'@base-ui-components/utils': 0.2.2(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||
'@base-ui/utils': 0.3.2(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||
'@floating-ui/react-dom': 2.1.9(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||
'@floating-ui/utils': 0.2.12
|
||||
react: 19.2.8
|
||||
react-dom: 19.2.8(react@19.2.8)
|
||||
reselect: 5.3.0
|
||||
tabbable: 6.5.0
|
||||
use-sync-external-store: 1.6.0(react@19.2.8)
|
||||
optionalDependencies:
|
||||
'@date-fns/tz': 1.5.0
|
||||
'@types/react': 19.2.18
|
||||
date-fns: 4.4.0
|
||||
|
||||
'@base-ui-components/utils@0.2.2(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
|
||||
'@base-ui/utils@0.3.2(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.7
|
||||
'@floating-ui/utils': 0.2.12
|
||||
@@ -4049,6 +4115,13 @@ snapshots:
|
||||
|
||||
'@date-fns/tz@1.5.0': {}
|
||||
|
||||
'@daypicker/react@10.0.1(@types/react@19.2.18)(react@19.2.8)':
|
||||
dependencies:
|
||||
react: 19.2.8
|
||||
react-day-picker: 10.0.1(@types/react@19.2.18)(react@19.2.8)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.18
|
||||
|
||||
'@dnd-kit/accessibility@3.1.1(react@19.2.8)':
|
||||
dependencies:
|
||||
react: 19.2.8
|
||||
@@ -6758,6 +6831,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.18
|
||||
|
||||
react-resizable-panels@4.12.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
|
||||
dependencies:
|
||||
react: 19.2.8
|
||||
react-dom: 19.2.8(react@19.2.8)
|
||||
|
||||
react-style-singleton@2.2.3(@types/react@19.2.18)(react@19.2.8):
|
||||
dependencies:
|
||||
get-nonce: 1.0.1
|
||||
@@ -6968,8 +7046,6 @@ snapshots:
|
||||
|
||||
symbol-tree@3.2.4: {}
|
||||
|
||||
tabbable@6.5.0: {}
|
||||
|
||||
tailwind-merge@3.6.0: {}
|
||||
|
||||
tailwindcss@4.3.0: {}
|
||||
|
||||
Reference in New Issue
Block a user