├── .nvmrc ├── .npmrc ├── packages └── radix-ui-themes │ ├── .browserslistrc │ ├── scripts │ ├── package.json │ ├── esbuild-cjs.js │ └── esbuild-esm.js │ ├── src │ ├── index.ts │ ├── components │ │ ├── dialog.css │ │ ├── radio.css │ │ ├── alert-dialog.css │ │ ├── box.css │ │ ├── radio.props.tsx │ │ ├── button.props.tsx │ │ ├── tab-nav.css │ │ ├── checkbox.props.tsx │ │ ├── icon-button.props.tsx │ │ ├── layout.css │ │ ├── slot.tsx │ │ ├── alert-dialog.props.tsx │ │ ├── blockquote.css │ │ ├── aspect-ratio.tsx │ │ ├── portal.tsx │ │ ├── tabs.css │ │ ├── accessible-icon.tsx │ │ ├── context-menu.css │ │ ├── flex.css │ │ ├── dropdown-menu.css │ │ ├── visually-hidden.tsx │ │ ├── checkbox-group.props.tsx │ │ ├── context-menu.props.tsx │ │ ├── dropdown-menu.props.tsx │ │ ├── grid.css │ │ ├── em.props.tsx │ │ ├── quote.props.tsx │ │ ├── strong.props.tsx │ │ ├── tabs.props.tsx │ │ ├── checkbox.css │ │ ├── strong.css │ │ ├── radio-group.css │ │ ├── skeleton.props.tsx │ │ ├── spinner.props.tsx │ │ ├── tab-nav.props.tsx │ │ ├── em.css │ │ ├── quote.css │ │ ├── kbd.props.tsx │ │ ├── button.tsx │ │ ├── card.props.tsx │ │ ├── section.css │ │ ├── icon-button.tsx │ │ ├── tooltip.props.tsx │ │ ├── scroll-area.props.tsx │ │ ├── _internal │ │ │ ├── base-radio.props.ts │ │ │ ├── base-checkbox.props.ts │ │ │ ├── base-tab-list.props.ts │ │ │ ├── base-button.props.ts │ │ │ └── base-menu.props.ts │ │ ├── checkbox-group.css │ │ ├── segmented-control.props.tsx │ │ ├── reset.tsx │ │ ├── slider.props.tsx │ │ ├── switch.props.tsx │ │ ├── callout.props.tsx │ │ ├── radio-group.props.tsx │ │ ├── progress.props.tsx │ │ ├── separator.props.tsx │ │ ├── badge.props.tsx │ │ ├── blockquote.props.tsx │ │ ├── em.tsx │ │ ├── text-area.props.tsx │ │ ├── quote.tsx │ │ ├── avatar.props.tsx │ │ ├── strong.tsx │ │ ├── tooltip.css │ │ ├── code.props.tsx │ │ ├── radio-cards.props.tsx │ │ ├── checkbox-cards.props.tsx │ │ ├── popover.props.tsx │ │ ├── hover-card.props.tsx │ │ ├── inset.tsx │ │ ├── kbd.tsx │ │ ├── card.tsx │ │ ├── link.props.tsx │ │ ├── text.props.tsx │ │ ├── blockquote.tsx │ │ ├── heading.props.tsx │ │ ├── box.props.tsx │ │ ├── container.css │ │ ├── link.tsx │ │ ├── select.props.tsx │ │ ├── text-field.props.tsx │ │ ├── separator.tsx │ │ ├── badge.tsx │ │ ├── section.tsx │ │ ├── dialog.props.tsx │ │ ├── heading.tsx │ │ ├── box.tsx │ │ ├── theme-panel.css │ │ ├── code.tsx │ │ ├── flex.tsx │ │ ├── grid.tsx │ │ ├── text-area.tsx │ │ ├── hover-card.css │ │ ├── data-list.props.tsx │ │ ├── switch.tsx │ │ ├── skeleton.css │ │ ├── skeleton.tsx │ │ └── popover.css │ ├── styles │ │ ├── tokens │ │ │ ├── layout.css │ │ │ ├── base.css │ │ │ ├── cursor.css │ │ │ ├── scaling.css │ │ │ ├── space.css │ │ │ ├── colors │ │ │ │ ├── red.css │ │ │ │ ├── gray.css │ │ │ │ ├── sage.css │ │ │ │ ├── sand.css │ │ │ │ ├── blue.css │ │ │ │ ├── cyan.css │ │ │ │ ├── gold.css │ │ │ │ ├── iris.css │ │ │ │ ├── jade.css │ │ │ │ ├── mauve.css │ │ │ │ ├── olive.css │ │ │ │ ├── pink.css │ │ │ │ ├── plum.css │ │ │ │ ├── ruby.css │ │ │ │ ├── slate.css │ │ │ │ ├── teal.css │ │ │ │ ├── brown.css │ │ │ │ ├── grass.css │ │ │ │ ├── green.css │ │ │ │ ├── bronze.css │ │ │ │ ├── indigo.css │ │ │ │ ├── orange.css │ │ │ │ ├── purple.css │ │ │ │ ├── tomato.css │ │ │ │ ├── violet.css │ │ │ │ ├── crimson.css │ │ │ │ ├── sky.css │ │ │ │ ├── lime.css │ │ │ │ ├── mint.css │ │ │ │ ├── amber.css │ │ │ │ └── yellow.css │ │ │ ├── radius.css │ │ │ └── index.css │ │ ├── layout.css │ │ ├── utilities │ │ │ ├── truncate.css │ │ │ ├── table-layout.css │ │ │ ├── text-align.css │ │ │ ├── flex-wrap.css │ │ │ ├── resize.css │ │ │ ├── index.css │ │ │ ├── vertical-align.css │ │ │ ├── flex-direction.css │ │ │ ├── justify-content.css │ │ │ ├── align-self.css │ │ │ ├── justify-self.css │ │ │ ├── align-items.css │ │ │ ├── justify-items.css │ │ │ ├── font-weight.css │ │ │ ├── position.css │ │ │ ├── grid-auto-flow.css │ │ │ ├── text-wrap.css │ │ │ ├── width.css │ │ │ ├── height.css │ │ │ ├── flex-basis.css │ │ │ ├── max-width.css │ │ │ ├── min-width.css │ │ │ ├── grid-area.css │ │ │ ├── max-height.css │ │ │ ├── min-height.css │ │ │ ├── align-content.css │ │ │ ├── display.css │ │ │ ├── grid-template-areas.css │ │ │ ├── flex-grow.css │ │ │ ├── flex-shrink.css │ │ │ ├── leading-trim.css │ │ │ ├── overflow.css │ │ │ ├── grid-row.css │ │ │ ├── grid-column.css │ │ │ ├── layout.css │ │ │ ├── grid-row-end.css │ │ │ ├── grid-row-start.css │ │ │ ├── grid-column-end.css │ │ │ ├── grid-column-start.css │ │ │ ├── grid-template-rows.css │ │ │ └── grid-template-columns.css │ │ ├── index.css │ │ └── breakpoints.css │ ├── helpers │ │ ├── inert.ts │ │ ├── extract-margin-props.ts │ │ ├── has-own-property.ts │ │ ├── is-responsive-object.ts │ │ ├── merge-styles.ts │ │ ├── index.ts │ │ ├── require-react-element.ts │ │ ├── component-props.ts │ │ ├── get-subtree.ts │ │ ├── get-matching-gray-color.ts │ │ └── map-prop-values.ts │ └── props │ │ ├── truncate.prop.ts │ │ ├── high-contrast.prop.ts │ │ ├── radius.prop.ts │ │ ├── weight.prop.ts │ │ ├── as-child.prop.ts │ │ ├── text-align.prop.ts │ │ ├── text-wrap.prop.ts │ │ ├── leading-trim.prop.ts │ │ ├── color.prop.ts │ │ ├── width.props.ts │ │ └── height.props.ts │ ├── tsconfig.json │ ├── postcss.config.cjs │ ├── .stylelintrc.cjs │ ├── postcss-whitespace.cjs │ └── README.md ├── .vscode ├── settings.json └── extensions.json ├── apps └── playground │ ├── app │ ├── globals.css │ ├── favicon.ico │ ├── test-tabnav │ │ ├── (accounts) │ │ │ └── page.tsx │ │ ├── settings │ │ │ └── page.tsx │ │ ├── documents │ │ │ └── page.tsx │ │ └── layout.tsx │ ├── demo │ │ └── page.module.css │ ├── next-theme-provider.tsx │ ├── layout.tsx │ ├── api │ │ └── avatar │ │ │ └── route.ts │ ├── sink │ │ ├── hide-cursor.tsx │ │ ├── radix-logo.tsx │ │ ├── page.module.css │ │ ├── pointer-cursors-checkbox.tsx │ │ └── tab-nav-demo.tsx │ ├── home-os │ │ └── page.module.css │ ├── test-grid-align-self │ │ └── page.tsx │ ├── test-grid-justify-self │ │ └── page.tsx │ ├── snapshot │ │ └── page.module.css │ └── test-avatar │ │ └── page.tsx │ ├── next-env.d.ts │ ├── next.config.js │ ├── css.d.ts │ ├── .gitignore │ ├── package.json │ └── tsconfig.json ├── pnpm-workspace.yaml ├── context7.json ├── .prettierrc ├── .gitignore ├── turbo.json ├── .github └── PULL_REQUEST_TEMPLATE.md ├── package.json ├── LICENSE ├── README.md └── release-process.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | use-beta-cli=true 2 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/.browserslistrc: -------------------------------------------------------------------------------- 1 | last 2 years 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "stylelint.enable": true 3 | } 4 | -------------------------------------------------------------------------------- /apps/playground/app/globals.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } 4 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'apps/*' 3 | - 'packages/*' 4 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components/index.js'; 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["stylelint.vscode-stylelint"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/dialog.css: -------------------------------------------------------------------------------- 1 | @import './_internal/base-dialog.css'; 2 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/radio.css: -------------------------------------------------------------------------------- 1 | @import './_internal/base-radio.css'; 2 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/alert-dialog.css: -------------------------------------------------------------------------------- 1 | @import './_internal/base-dialog.css'; 2 | -------------------------------------------------------------------------------- /apps/playground/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radix-ui/themes/HEAD/apps/playground/app/favicon.ico -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/layout.css: -------------------------------------------------------------------------------- 1 | @import './scaling.css'; 2 | @import './space.css'; 3 | -------------------------------------------------------------------------------- /context7.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://context7.com/radix-ui/themes", 3 | "public_key": "pk_q7NnKuFFXMWA7WnmjMHQU" 4 | } -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/box.css: -------------------------------------------------------------------------------- 1 | .rt-Box { 2 | box-sizing: border-box; 3 | display: block; 4 | } 5 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/radio.props.tsx: -------------------------------------------------------------------------------- 1 | export { baseRadioPropDefs as radioPropDefs } from './_internal/base-radio.props.js'; 2 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/button.props.tsx: -------------------------------------------------------------------------------- 1 | export { baseButtonPropDefs as buttonPropDefs } from './_internal/base-button.props.js'; 2 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/tab-nav.css: -------------------------------------------------------------------------------- 1 | @import './_internal/base-tab-list.css'; 2 | 3 | .rt-TabNavItem { 4 | display: flex; 5 | } 6 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/checkbox.props.tsx: -------------------------------------------------------------------------------- 1 | export { baseCheckboxPropDefs as checkboxPropDefs } from './_internal/base-checkbox.props.js'; 2 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/icon-button.props.tsx: -------------------------------------------------------------------------------- 1 | export { baseButtonPropDefs as iconButtonPropDefs } from './_internal/base-button.props.js'; 2 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/layout.css: -------------------------------------------------------------------------------- 1 | @import './tokens/layout.css'; 2 | @import '../components/layout.css'; 3 | @import './utilities/layout.css'; 4 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/truncate.css: -------------------------------------------------------------------------------- 1 | .rt-truncate { 2 | overflow: hidden; 3 | text-overflow: ellipsis; 4 | white-space: nowrap; 5 | } 6 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/layout.css: -------------------------------------------------------------------------------- 1 | @import './box.css'; 2 | @import './flex.css'; 3 | @import './grid.css'; 4 | @import './section.css'; 5 | @import './container.css'; 6 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/index.css: -------------------------------------------------------------------------------- 1 | @import './breakpoints.css'; 2 | @import './tokens/index.css'; 3 | @import '../components/index.css'; 4 | @import './utilities/index.css'; 5 | -------------------------------------------------------------------------------- /apps/playground/app/test-tabnav/(accounts)/page.tsx: -------------------------------------------------------------------------------- 1 | import { Heading } from '@radix-ui/themes'; 2 | 3 | export default function Accounts() { 4 | return Accounts; 5 | } 6 | -------------------------------------------------------------------------------- /apps/playground/app/test-tabnav/settings/page.tsx: -------------------------------------------------------------------------------- 1 | import { Heading } from '@radix-ui/themes'; 2 | 3 | export default function Settings() { 4 | return Settings; 5 | } 6 | -------------------------------------------------------------------------------- /apps/playground/app/test-tabnav/documents/page.tsx: -------------------------------------------------------------------------------- 1 | import { Heading } from '@radix-ui/themes'; 2 | 3 | export default function Documents() { 4 | return Documents; 5 | } 6 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/table-layout.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-tl-auto { 3 | table-layout: auto; 4 | } 5 | .rt-r-tl-fixed { 6 | table-layout: fixed; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/base.css: -------------------------------------------------------------------------------- 1 | @import './color.css'; 2 | @import './cursor.css'; 3 | @import './layout.css'; 4 | @import './radius.css'; 5 | @import './shadow.css'; 6 | @import './typography.css'; 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "overrides": [ 5 | { 6 | "files": "*.css", 7 | "options": { 8 | "printWidth": 120 9 | } 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/slot.tsx: -------------------------------------------------------------------------------- 1 | import { Slot as SlotPrimitive } from 'radix-ui'; 2 | export const Root = SlotPrimitive.Root; 3 | export const Slot = SlotPrimitive.Root; 4 | export const Slottable = SlotPrimitive.Slottable; 5 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/alert-dialog.props.tsx: -------------------------------------------------------------------------------- 1 | export { dialogContentPropDefs as alertDialogContentPropDefs } from './dialog.props.js'; 2 | export type { DialogContentOwnProps as AlertDialogContentOwnProps } from './dialog.props.js'; 3 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/blockquote.css: -------------------------------------------------------------------------------- 1 | .rt-Blockquote { 2 | box-sizing: border-box; 3 | border-left: max(var(--space-1), 0.25em) solid var(--accent-a6); 4 | padding-left: min(var(--space-5), max(var(--space-3), 0.5em)); 5 | } 6 | -------------------------------------------------------------------------------- /apps/playground/app/demo/page.module.css: -------------------------------------------------------------------------------- 1 | .body :global(.rt-DialogContent) { 2 | max-width: 400px; 3 | } 4 | 5 | .body :global(#root) { 6 | padding: 100px 400px; 7 | } 8 | 9 | .body :global(.rt-SelectTrigger) { 10 | width: 100%; 11 | } 12 | -------------------------------------------------------------------------------- /apps/playground/app/next-theme-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { ThemeProvider } from 'next-themes'; 4 | 5 | export function NextThemeProvider({ children }) { 6 | return {children}; 7 | } 8 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | import { AspectRatio as AspectRatioPrimitive } from 'radix-ui'; 2 | export const AspectRatio = AspectRatioPrimitive.Root; 3 | export type AspectRatioProps = AspectRatioPrimitive.AspectRatioProps; 4 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/inert.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | // "inert" works differently between React versions 4 | // https://github.com/facebook/react/pull/24730 5 | export const inert = parseFloat(React.version) >= 19 || ''; 6 | -------------------------------------------------------------------------------- /apps/playground/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/portal.tsx: -------------------------------------------------------------------------------- 1 | import { Portal as PortalPrimitive } from 'radix-ui'; 2 | export const Portal = PortalPrimitive.Root; 3 | export const Root = PortalPrimitive.Root; 4 | export type PortalProps = PortalPrimitive.PortalProps; 5 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/breakpoints.css: -------------------------------------------------------------------------------- 1 | @custom-media --xs (min-width: 520px); 2 | @custom-media --sm (min-width: 768px); 3 | @custom-media --md (min-width: 1024px); 4 | @custom-media --lg (min-width: 1280px); 5 | @custom-media --xl (min-width: 1640px); 6 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/tabs.css: -------------------------------------------------------------------------------- 1 | @import './_internal/base-tab-list.css'; 2 | 3 | .rt-TabsContent { 4 | position: relative; 5 | outline: 0; 6 | } 7 | 8 | .rt-TabsContent:where(:focus-visible) { 9 | outline: 2px solid var(--focus-8); 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .turbo 4 | *.log 5 | .next 6 | dist 7 | dist-ssr 8 | *.local 9 | .env 10 | .cache 11 | server/dist 12 | public/dist 13 | packages/radix-ui-themes/*.css 14 | packages/radix-ui-themes/tokens 15 | packages/radix-ui-themes/layout 16 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/accessible-icon.tsx: -------------------------------------------------------------------------------- 1 | import { AccessibleIcon as AccessibleIconPrimitive } from 'radix-ui'; 2 | export const AccessibleIcon = AccessibleIconPrimitive.Root; 3 | export type AccessibleIconProps = AccessibleIconPrimitive.AccessibleIconProps; 4 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/context-menu.css: -------------------------------------------------------------------------------- 1 | @import './_internal/base-menu.css'; 2 | 3 | .rt-ContextMenuContent { 4 | max-height: var(--radix-context-menu-content-available-height); 5 | transform-origin: var(--radix-context-menu-content-transform-origin); 6 | } 7 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/flex.css: -------------------------------------------------------------------------------- 1 | .rt-Flex { 2 | box-sizing: border-box; 3 | 4 | /* Default values to provide the initial styles in the object syntax, e.g. `` */ 5 | display: flex; 6 | justify-content: flex-start; 7 | } 8 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/text-align.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-ta-left { 3 | text-align: left; 4 | } 5 | 6 | .rt-r-ta-center { 7 | text-align: center; 8 | } 9 | 10 | .rt-r-ta-right { 11 | text-align: right; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/dropdown-menu.css: -------------------------------------------------------------------------------- 1 | @import './_internal/base-menu.css'; 2 | 3 | .rt-DropdownMenuContent { 4 | max-height: var(--radix-dropdown-menu-content-available-height); 5 | transform-origin: var(--radix-dropdown-menu-content-transform-origin); 6 | } 7 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/flex-wrap.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-fw-nowrap { 3 | flex-wrap: nowrap; 4 | } 5 | 6 | .rt-r-fw-wrap { 7 | flex-wrap: wrap; 8 | } 9 | 10 | .rt-r-fw-wrap-reverse { 11 | flex-wrap: wrap-reverse; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/extract-margin-props.ts: -------------------------------------------------------------------------------- 1 | import type { MarginProps } from '../props/margin.props.js'; 2 | 3 | export function extractMarginProps(props: T) { 4 | const { m, mx, my, mt, mr, mb, ml, ...rest } = props; 5 | return { m, mx, my, mt, mr, mb, ml, rest }; 6 | } 7 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/truncate.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | const truncatePropDef = { 4 | truncate: { 5 | type: 'boolean', 6 | className: 'rt-truncate', 7 | }, 8 | } satisfies { 9 | truncate: PropDef; 10 | }; 11 | 12 | export { truncatePropDef }; 13 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/visually-hidden.tsx: -------------------------------------------------------------------------------- 1 | import { VisuallyHidden as VisuallyHiddenPrimitive } from 'radix-ui'; 2 | export const VisuallyHidden = VisuallyHiddenPrimitive.Root; 3 | export const Root = VisuallyHiddenPrimitive.Root; 4 | export type VisuallyHiddenProps = VisuallyHiddenPrimitive.VisuallyHiddenProps; 5 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/resize.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-resize-none { 3 | resize: none; 4 | } 5 | .rt-r-resize-vertical { 6 | resize: vertical; 7 | } 8 | .rt-r-resize-horizontal { 9 | resize: horizontal; 10 | } 11 | .rt-r-resize-both { 12 | resize: both; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/index.css: -------------------------------------------------------------------------------- 1 | @import './layout.css'; 2 | 3 | @import './font-weight.css'; 4 | @import './leading-trim.css'; 5 | @import './resize.css'; 6 | @import './table-layout.css'; 7 | @import './text-align.css'; 8 | @import './text-wrap.css'; 9 | @import './truncate.css'; 10 | @import './vertical-align.css'; 11 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/checkbox-group.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { baseCheckboxPropDefs } from './_internal/base-checkbox.props.js'; 3 | 4 | const checkboxGroupRootPropDefs = { 5 | ...asChildPropDef, 6 | ...baseCheckboxPropDefs, 7 | }; 8 | 9 | export { checkboxGroupRootPropDefs }; 10 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/context-menu.props.tsx: -------------------------------------------------------------------------------- 1 | export { 2 | baseMenuContentPropDefs as contextMenuContentPropDefs, 3 | baseMenuItemPropDefs as contextMenuItemPropDefs, 4 | baseMenuCheckboxItemPropDefs as contextMenuCheckboxItemPropDefs, 5 | baseMenuRadioItemPropDefs as contextMenuRadioItemPropDefs, 6 | } from './_internal/base-menu.props.js'; 7 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/dropdown-menu.props.tsx: -------------------------------------------------------------------------------- 1 | export { 2 | baseMenuContentPropDefs as dropdownMenuContentPropDefs, 3 | baseMenuItemPropDefs as dropdownMenuItemPropDefs, 4 | baseMenuCheckboxItemPropDefs as dropdownMenuCheckboxItemPropDefs, 5 | baseMenuRadioItemPropDefs as dropdownMenuRadioItemPropDefs, 6 | } from './_internal/base-menu.props.js'; 7 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/vertical-align.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-va-baseline { 3 | vertical-align: baseline; 4 | } 5 | 6 | .rt-r-va-top { 7 | vertical-align: top; 8 | } 9 | 10 | .rt-r-va-middle { 11 | vertical-align: middle; 12 | } 13 | 14 | .rt-r-va-bottom { 15 | vertical-align: bottom; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/high-contrast.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | const highContrastPropDef = { 4 | highContrast: { 5 | type: 'boolean', 6 | className: 'rt-high-contrast', 7 | default: undefined, 8 | }, 9 | } satisfies { 10 | highContrast: PropDef; 11 | }; 12 | 13 | export { highContrastPropDef }; 14 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/grid.css: -------------------------------------------------------------------------------- 1 | .rt-Grid { 2 | box-sizing: border-box; 3 | 4 | /* Default values to provide the initial styles in the object syntax, e.g. `` */ 5 | display: grid; 6 | align-items: stretch; 7 | justify-content: flex-start; 8 | grid-template-columns: minmax(0, 1fr); 9 | grid-template-rows: none; 10 | } 11 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/flex-direction.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-fd-row { 3 | flex-direction: row; 4 | } 5 | 6 | .rt-r-fd-column { 7 | flex-direction: column; 8 | } 9 | 10 | .rt-r-fd-row-reverse { 11 | flex-direction: row-reverse; 12 | } 13 | 14 | .rt-r-fd-column-reverse { 15 | flex-direction: column-reverse; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/justify-content.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-jc-start { 3 | justify-content: flex-start; 4 | } 5 | 6 | .rt-r-jc-center { 7 | justify-content: center; 8 | } 9 | 10 | .rt-r-jc-end { 11 | justify-content: flex-end; 12 | } 13 | 14 | .rt-r-jc-space-between { 15 | justify-content: space-between; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/em.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { textWrapPropDef } from '../props/text-wrap.prop.js'; 3 | import { truncatePropDef } from '../props/truncate.prop.js'; 4 | 5 | const emPropDefs = { 6 | ...asChildPropDef, 7 | ...truncatePropDef, 8 | ...textWrapPropDef, 9 | }; 10 | 11 | export { emPropDefs }; 12 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/cursor.css: -------------------------------------------------------------------------------- 1 | .radix-themes { 2 | --cursor-button: default; 3 | --cursor-checkbox: default; 4 | --cursor-disabled: not-allowed; 5 | --cursor-link: pointer; 6 | --cursor-menu-item: default; 7 | --cursor-radio: default; 8 | --cursor-slider-thumb: default; 9 | --cursor-slider-thumb-active: default; 10 | --cursor-switch: default; 11 | } 12 | -------------------------------------------------------------------------------- /apps/playground/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './globals.css'; 3 | import '@radix-ui/themes/styles.css'; 4 | 5 | export const metadata = { 6 | title: 'Radix Themes playground', 7 | description: 'A playground of Radix Themes components', 8 | }; 9 | 10 | export default function RootLayout({ children }: { children: React.ReactNode }) { 11 | return children; 12 | } 13 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/has-own-property.ts: -------------------------------------------------------------------------------- 1 | /** A util to check whether the object has a key, while inferring the correct key type */ 2 | function hasOwnProperty( 3 | obj: Record, 4 | key: string | number | symbol 5 | ): key is K { 6 | return Object.prototype.hasOwnProperty.call(obj, key); 7 | } 8 | 9 | export { hasOwnProperty }; 10 | -------------------------------------------------------------------------------- /apps/playground/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | transpilePackages: ['@radix-ui/themes'], 5 | async redirects() { 6 | return [ 7 | { 8 | source: '/', 9 | destination: '/sink', 10 | permanent: false, 11 | }, 12 | ]; 13 | }, 14 | }; 15 | 16 | module.exports = nextConfig; 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/quote.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { textWrapPropDef } from '../props/text-wrap.prop.js'; 3 | import { truncatePropDef } from '../props/truncate.prop.js'; 4 | 5 | const quotePropDefs = { 6 | ...asChildPropDef, 7 | ...truncatePropDef, 8 | ...textWrapPropDef, 9 | }; 10 | 11 | export { quotePropDefs }; 12 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/strong.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { textWrapPropDef } from '../props/text-wrap.prop.js'; 3 | import { truncatePropDef } from '../props/truncate.prop.js'; 4 | 5 | const strongPropDefs = { 6 | ...asChildPropDef, 7 | ...truncatePropDef, 8 | ...textWrapPropDef, 9 | }; 10 | 11 | export { strongPropDefs }; 12 | -------------------------------------------------------------------------------- /apps/playground/app/api/avatar/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from 'next/server'; 2 | 3 | async function wait(ms: number) { 4 | return new Promise((resolve) => setTimeout(resolve, ms)); 5 | } 6 | 7 | export async function GET() { 8 | await wait(1000); 9 | return NextResponse.redirect( 10 | 'https://images.unsplash.com/photo-1492633423870-43d1cd2775eb?&w=160&h=160&dpr=2&q=80' 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/tabs.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | 3 | const tabsRootPropDefs = { 4 | ...asChildPropDef, 5 | }; 6 | 7 | const tabsContentPropDefs = { 8 | ...asChildPropDef, 9 | }; 10 | 11 | export { baseTabListPropDefs as tabsListPropDefs } from './_internal/base-tab-list.props.js'; 12 | export { tabsRootPropDefs, tabsContentPropDefs }; 13 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/align-self.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-as-start { 3 | align-self: start; 4 | } 5 | 6 | .rt-r-as-center { 7 | align-self: center; 8 | } 9 | 10 | .rt-r-as-end { 11 | align-self: end; 12 | } 13 | 14 | .rt-r-as-baseline { 15 | align-self: baseline; 16 | } 17 | 18 | .rt-r-as-stretch { 19 | align-self: stretch; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/radius.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | const radii = ['none', 'small', 'medium', 'large', 'full'] as const; 4 | 5 | const radiusPropDef = { 6 | radius: { 7 | type: 'enum', 8 | values: radii, 9 | default: undefined, 10 | }, 11 | } satisfies { 12 | radius: PropDef<(typeof radii)[number]>; 13 | }; 14 | 15 | export { radiusPropDef, radii }; 16 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/justify-self.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-js-start { 3 | justify-self: start; 4 | } 5 | 6 | .rt-r-js-center { 7 | justify-self: center; 8 | } 9 | 10 | .rt-r-js-end { 11 | justify-self: end; 12 | } 13 | 14 | .rt-r-js-baseline { 15 | justify-self: baseline; 16 | } 17 | 18 | .rt-r-js-stretch { 19 | justify-self: stretch; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/align-items.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-ai-start { 3 | align-items: flex-start; 4 | } 5 | 6 | .rt-r-ai-center { 7 | align-items: center; 8 | } 9 | 10 | .rt-r-ai-end { 11 | align-items: flex-end; 12 | } 13 | 14 | .rt-r-ai-baseline { 15 | align-items: baseline; 16 | } 17 | 18 | .rt-r-ai-stretch { 19 | align-items: stretch; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/justify-items.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-ji-start { 3 | justify-items: start; 4 | } 5 | 6 | .rt-r-ji-center { 7 | justify-items: center; 8 | } 9 | 10 | .rt-r-ji-end { 11 | justify-items: end; 12 | } 13 | 14 | .rt-r-ji-baseline { 15 | justify-items: baseline; 16 | } 17 | 18 | .rt-r-ji-stretch { 19 | justify-items: stretch; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/scaling.css: -------------------------------------------------------------------------------- 1 | .radix-themes { 2 | &:where([data-scaling='90%']) { 3 | --scaling: 0.9; 4 | } 5 | &:where([data-scaling='95%']) { 6 | --scaling: 0.95; 7 | } 8 | &:where([data-scaling='100%']) { 9 | --scaling: 1; 10 | } 11 | &:where([data-scaling='105%']) { 12 | --scaling: 1.05; 13 | } 14 | &:where([data-scaling='110%']) { 15 | --scaling: 1.1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/font-weight.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-weight-light { 3 | font-weight: var(--font-weight-light); 4 | } 5 | 6 | .rt-r-weight-regular { 7 | font-weight: var(--font-weight-regular); 8 | } 9 | 10 | .rt-r-weight-medium { 11 | font-weight: var(--font-weight-medium); 12 | } 13 | 14 | .rt-r-weight-bold { 15 | font-weight: var(--font-weight-bold); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/position.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-position-static { 3 | position: static; 4 | } 5 | 6 | .rt-r-position-absolute { 7 | position: absolute; 8 | } 9 | 10 | .rt-r-position-relative { 11 | position: relative; 12 | } 13 | 14 | .rt-r-position-fixed { 15 | position: fixed; 16 | } 17 | 18 | .rt-r-position-sticky { 19 | position: sticky; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/checkbox.css: -------------------------------------------------------------------------------- 1 | @import './_internal/base-checkbox.css'; 2 | 3 | .rt-CheckboxRoot { 4 | &:where(:focus-visible) { 5 | &::before { 6 | outline: 2px solid var(--focus-8); 7 | outline-offset: 2px; 8 | } 9 | } 10 | 11 | &:where(:disabled) { 12 | cursor: var(--cursor-disabled); 13 | 14 | &::before { 15 | background-color: var(--gray-a3); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/weight.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | const weights = ['light', 'regular', 'medium', 'bold'] as const; 4 | 5 | const weightPropDef = { 6 | weight: { 7 | type: 'enum', 8 | className: 'rt-r-weight', 9 | values: weights, 10 | responsive: true, 11 | }, 12 | } satisfies { 13 | weight: PropDef<(typeof weights)[number]>; 14 | }; 15 | 16 | export { weightPropDef }; 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-auto-flow.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-gaf-row { 3 | grid-auto-flow: row; 4 | } 5 | 6 | .rt-r-gaf-column { 7 | grid-auto-flow: column; 8 | } 9 | 10 | .rt-r-gaf-dense { 11 | grid-auto-flow: dense; 12 | } 13 | 14 | .rt-r-gaf-row-dense { 15 | grid-auto-flow: row dense; 16 | } 17 | 18 | .rt-r-gaf-column-dense { 19 | grid-auto-flow: column dense; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/strong.css: -------------------------------------------------------------------------------- 1 | .rt-Strong { 2 | font-family: var(--strong-font-family); 3 | font-size: calc(var(--strong-font-size-adjust) * 1em); 4 | font-style: var(--strong-font-style); 5 | font-weight: var(--strong-font-weight); 6 | letter-spacing: calc( 7 | var(--strong-letter-spacing) + var(--letter-spacing, var(--default-letter-spacing)) 8 | ); 9 | 10 | & :where(&) { 11 | font-size: inherit; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/as-child.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | const asChildPropDef = { 4 | /** 5 | * Composes the component into its immediate child instead of rendering its own HTML element. 6 | * You’ll have to provide a single React Element child. 7 | */ 8 | asChild: { 9 | type: 'boolean', 10 | }, 11 | } satisfies { 12 | asChild: PropDef; 13 | }; 14 | 15 | export { asChildPropDef }; 16 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/radio-group.css: -------------------------------------------------------------------------------- 1 | .rt-RadioGroupRoot { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--space-1); 5 | } 6 | 7 | .rt-RadioGroupItem { 8 | display: flex; 9 | gap: 0.5em; 10 | 11 | /* Make sure whitespace to the right of the text is not clickable */ 12 | width: fit-content; 13 | } 14 | 15 | .rt-RadioGroupItemInner { 16 | /* Make layouts with text truncation possible */ 17 | min-width: 0; 18 | } 19 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/text-align.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | const textAlignValues = ['left', 'center', 'right'] as const; 4 | 5 | const textAlignPropDef = { 6 | align: { 7 | type: 'enum', 8 | className: 'rt-r-ta', 9 | values: textAlignValues, 10 | responsive: true, 11 | }, 12 | } satisfies { 13 | align: PropDef<(typeof textAlignValues)[number]>; 14 | }; 15 | 16 | export { textAlignPropDef }; 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/text-wrap.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | const textWrapValues = ['wrap', 'nowrap', 'pretty', 'balance'] as const; 4 | 5 | const textWrapPropDef = { 6 | wrap: { 7 | type: 'enum', 8 | className: 'rt-r-tw', 9 | values: textWrapValues, 10 | responsive: true, 11 | }, 12 | } satisfies { 13 | wrap: PropDef<(typeof textWrapValues)[number]>; 14 | }; 15 | 16 | export { textWrapPropDef }; 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/skeleton.props.tsx: -------------------------------------------------------------------------------- 1 | import { heightPropDefs } from '../props/height.props.js'; 2 | import { widthPropDefs } from '../props/width.props.js'; 3 | 4 | import type { PropDef } from '../props/prop-def.js'; 5 | 6 | const skeletonPropDefs = { 7 | loading: { type: 'boolean', default: true }, 8 | ...widthPropDefs, 9 | ...heightPropDefs, 10 | } satisfies { 11 | loading: PropDef; 12 | }; 13 | 14 | export { skeletonPropDefs }; 15 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "moduleResolution": "Bundler", 5 | "lib": ["DOM", "ESNext", "DOM.Iterable"], 6 | "jsx": "react", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "emitDeclarationOnly": true, 10 | "outDir": "dist", 11 | "strict": true, 12 | "skipLibCheck": true, 13 | "esModuleInterop": true, 14 | "verbatimModuleSyntax": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/leading-trim.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | const leadingTrimValues = ['normal', 'start', 'end', 'both'] as const; 4 | 5 | const leadingTrimPropDef = { 6 | trim: { 7 | type: 'enum', 8 | className: 'rt-r-lt', 9 | values: leadingTrimValues, 10 | responsive: true, 11 | }, 12 | } satisfies { 13 | trim: PropDef<(typeof leadingTrimValues)[number]>; 14 | }; 15 | 16 | export { leadingTrimPropDef }; 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/space.css: -------------------------------------------------------------------------------- 1 | .radix-themes { 2 | --space-1: calc(4px * var(--scaling)); 3 | --space-2: calc(8px * var(--scaling)); 4 | --space-3: calc(12px * var(--scaling)); 5 | --space-4: calc(16px * var(--scaling)); 6 | --space-5: calc(24px * var(--scaling)); 7 | --space-6: calc(32px * var(--scaling)); 8 | --space-7: calc(40px * var(--scaling)); 9 | --space-8: calc(48px * var(--scaling)); 10 | --space-9: calc(64px * var(--scaling)); 11 | } 12 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/spinner.props.tsx: -------------------------------------------------------------------------------- 1 | import type { PropDef } from '../props/prop-def.js'; 2 | 3 | const sizes = ['1', '2', '3'] as const; 4 | 5 | const spinnerPropDefs = { 6 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 7 | loading: { type: 'boolean', default: true }, 8 | } satisfies { 9 | size: PropDef<(typeof sizes)[number]>; 10 | loading: PropDef; 11 | }; 12 | 13 | export { spinnerPropDefs }; 14 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/tab-nav.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | 3 | import type { PropDef } from '../props/prop-def.js'; 4 | 5 | const tabNavLinkPropDefs = { 6 | ...asChildPropDef, 7 | active: { type: 'boolean', default: false }, 8 | } satisfies { 9 | active: PropDef; 10 | }; 11 | 12 | export { baseTabListPropDefs as tabNavRootPropDefs } from './_internal/base-tab-list.props.js'; 13 | export { tabNavLinkPropDefs }; 14 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/em.css: -------------------------------------------------------------------------------- 1 | .rt-Em { 2 | box-sizing: border-box; 3 | font-family: var(--em-font-family); 4 | font-size: calc(var(--em-font-size-adjust) * 1em); 5 | font-style: var(--em-font-style); 6 | font-weight: var(--em-font-weight); 7 | line-height: 1.25; 8 | letter-spacing: calc( 9 | var(--em-letter-spacing) + var(--letter-spacing, var(--default-letter-spacing)) 10 | ); 11 | color: inherit; 12 | 13 | & :where(&) { 14 | font-size: inherit; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/text-wrap.css: -------------------------------------------------------------------------------- 1 | /* 2 | * We are modeling this after the "text-wrap" property, but use "white-space" because it has better support as of 2024. 3 | */ 4 | @breakpoints { 5 | .rt-r-tw-wrap { 6 | white-space: normal; 7 | } 8 | .rt-r-tw-nowrap { 9 | white-space: nowrap; 10 | } 11 | .rt-r-tw-pretty { 12 | white-space: normal; 13 | text-wrap: pretty; 14 | } 15 | .rt-r-tw-balance { 16 | white-space: normal; 17 | text-wrap: balance; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/quote.css: -------------------------------------------------------------------------------- 1 | .rt-Quote { 2 | box-sizing: border-box; 3 | font-family: var(--quote-font-family); 4 | font-size: calc(var(--quote-font-size-adjust) * 1em); 5 | font-style: var(--quote-font-style); 6 | font-weight: var(--quote-font-weight); 7 | line-height: 1.25; 8 | letter-spacing: calc( 9 | var(--quote-letter-spacing) + var(--letter-spacing, var(--default-letter-spacing)) 10 | ); 11 | color: inherit; 12 | 13 | & :where(&) { 14 | font-size: inherit; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | plugins: [ 5 | require('postcss-import')({ 6 | path: [path.relative(process.cwd(), '../')], 7 | }), 8 | require('postcss-nesting'), 9 | require('./postcss-breakpoints.cjs'), 10 | require('postcss-custom-media'), 11 | require('postcss-combine-duplicated-selectors'), 12 | require('postcss-discard-empty'), 13 | require('./postcss-whitespace.cjs'), 14 | require('autoprefixer'), 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/kbd.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | 3 | import type { PropDef } from '../props/prop-def.js'; 4 | 5 | const sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] as const; 6 | 7 | const kbdPropDefs = { 8 | ...asChildPropDef, 9 | size: { 10 | type: 'enum', 11 | className: 'rt-r-size', 12 | values: sizes, 13 | responsive: true, 14 | }, 15 | } satisfies { 16 | size: PropDef<(typeof sizes)[number]>; 17 | }; 18 | 19 | export { kbdPropDefs }; 20 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/width.css: -------------------------------------------------------------------------------- 1 | .rt-r-w { 2 | width: var(--width); 3 | } 4 | @media (--xs) { 5 | .xs\:rt-r-w { 6 | width: var(--width-xs); 7 | } 8 | } 9 | @media (--sm) { 10 | .sm\:rt-r-w { 11 | width: var(--width-sm); 12 | } 13 | } 14 | @media (--md) { 15 | .md\:rt-r-w { 16 | width: var(--width-md); 17 | } 18 | } 19 | @media (--lg) { 20 | .lg\:rt-r-w { 21 | width: var(--width-lg); 22 | } 23 | } 24 | @media (--xl) { 25 | .xl\:rt-r-w { 26 | width: var(--width-xl); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/is-responsive-object.ts: -------------------------------------------------------------------------------- 1 | import { breakpoints } from '../props/prop-def.js'; 2 | 3 | import type { Responsive, Breakpoint } from '../props/prop-def.js'; 4 | 5 | export function isResponsiveObject( 6 | obj: Responsive> | undefined, 7 | ): obj is Record { 8 | return ( 9 | typeof obj === 'object' && 10 | obj !== null && 11 | Object.keys(obj).some((key) => { 12 | return breakpoints.has(key as any); 13 | }) 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/merge-styles.ts: -------------------------------------------------------------------------------- 1 | type InlineStyle = 2 | | React.CSSProperties 3 | | Record 4 | | undefined; 5 | 6 | // Merges CSS styles like `classNames` merges CSS classes 7 | export function mergeStyles(...styles: Array): InlineStyle { 8 | let result: InlineStyle = {}; 9 | 10 | for (const style of styles) { 11 | if (style) { 12 | result = { ...result, ...style }; 13 | } 14 | } 15 | 16 | return Object.keys(result).length ? result : undefined; 17 | } 18 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/height.css: -------------------------------------------------------------------------------- 1 | .rt-r-h { 2 | height: var(--height); 3 | } 4 | @media (--xs) { 5 | .xs\:rt-r-h { 6 | height: var(--height-xs); 7 | } 8 | } 9 | @media (--sm) { 10 | .sm\:rt-r-h { 11 | height: var(--height-sm); 12 | } 13 | } 14 | @media (--md) { 15 | .md\:rt-r-h { 16 | height: var(--height-md); 17 | } 18 | } 19 | @media (--lg) { 20 | .lg\:rt-r-h { 21 | height: var(--height-lg); 22 | } 23 | } 24 | @media (--xl) { 25 | .xl\:rt-r-h { 26 | height: var(--height-xl); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /apps/playground/css.d.ts: -------------------------------------------------------------------------------- 1 | // My css.d.ts file 2 | import type * as CSS from 'csstype'; 3 | 4 | declare module 'csstype' { 5 | interface Properties { 6 | // WebkitRocketLauncher?: string; 7 | 8 | // Add a CSS Custom Property 9 | // '--theme-color'?: 'black' | 'white'; 10 | 11 | // Allow namespaced CSS Custom Properties 12 | // [index: `--theme-${string}`]: any; 13 | 14 | // Allow any CSS Custom Properties 15 | [index: `--${string}`]: any; 16 | 17 | // ...or allow any other property 18 | // [index: string]: any; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "tasks": { 4 | "build": { 5 | "inputs": ["$TURBO_DEFAULT$", ".env*"], 6 | "dependsOn": ["^build"], 7 | "outputs": ["dist/**", ".next/**", "!.next/cache/**"] 8 | }, 9 | "test": { 10 | "outputs": ["coverage/**"], 11 | "dependsOn": [] 12 | }, 13 | "lint": {}, 14 | "dev": { 15 | "dependsOn": ["^build"], 16 | "cache": false, 17 | "persistent": true 18 | }, 19 | "clean": { 20 | "cache": false 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /apps/playground/app/sink/hide-cursor.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as React from 'react'; 4 | import { useIdle } from 'react-use'; 5 | 6 | function hideCursor() { 7 | document.body.classList.add('hide-cursor'); 8 | } 9 | function showCursor() { 10 | document.body.classList.remove('hide-cursor'); 11 | } 12 | 13 | export function HideCursor() { 14 | const isIdle = useIdle(1000); 15 | 16 | React.useEffect(() => { 17 | if (isIdle) { 18 | hideCursor(); 19 | } else { 20 | showCursor(); 21 | } 22 | }, [isIdle]); 23 | 24 | return null; 25 | } 26 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/.stylelintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // Disallow element type selector. 4 | 'selector-max-type': 0, 5 | // Allow 0,1,1 specificity for pseudo elements and effectively cap at 0,1,0 in all other cases. 6 | // This is so that Tailwind classes work as expected. 7 | 'selector-max-specificity': ['0,1,1'], 8 | // Enforce prefixes on classnames and keyframes 9 | 'selector-class-pattern': /^((xs|sm|md|lg|xl):)?-?rt-|^radix-themes$|^(light|dark)(-theme)?$/, 10 | 'keyframes-name-pattern': /^rt-([a-z]|-)+$/, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /apps/playground/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | tsconfig.tsbuildinfo 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # vercel 35 | .vercel 36 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component-props.js'; 2 | export * from './extract-margin-props.js'; 3 | export * from './extract-props.js'; 4 | export * from './get-margin-styles.js'; 5 | export * from './get-matching-gray-color.js'; 6 | export * from './get-responsive-styles.js'; 7 | export * from './get-subtree.js'; 8 | export * from './has-own-property.js'; 9 | export * from './input-attributes.js'; 10 | export * from './is-responsive-object.js'; 11 | export * from './map-prop-values.js'; 12 | export * from './merge-styles.js'; 13 | export * from './require-react-element.js'; 14 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/flex-basis.css: -------------------------------------------------------------------------------- 1 | .rt-r-fb { 2 | flex-basis: var(--flex-basis); 3 | } 4 | @media (--xs) { 5 | .xs\:rt-r-fb { 6 | flex-basis: var(--flex-basis-xs); 7 | } 8 | } 9 | @media (--sm) { 10 | .sm\:rt-r-fb { 11 | flex-basis: var(--flex-basis-sm); 12 | } 13 | } 14 | @media (--md) { 15 | .md\:rt-r-fb { 16 | flex-basis: var(--flex-basis-md); 17 | } 18 | } 19 | @media (--lg) { 20 | .lg\:rt-r-fb { 21 | flex-basis: var(--flex-basis-lg); 22 | } 23 | } 24 | @media (--xl) { 25 | .xl\:rt-r-fb { 26 | flex-basis: var(--flex-basis-xl); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/max-width.css: -------------------------------------------------------------------------------- 1 | .rt-r-max-w { 2 | max-width: var(--max-width); 3 | } 4 | @media (--xs) { 5 | .xs\:rt-r-max-w { 6 | max-width: var(--max-width-xs); 7 | } 8 | } 9 | @media (--sm) { 10 | .sm\:rt-r-max-w { 11 | max-width: var(--max-width-sm); 12 | } 13 | } 14 | @media (--md) { 15 | .md\:rt-r-max-w { 16 | max-width: var(--max-width-md); 17 | } 18 | } 19 | @media (--lg) { 20 | .lg\:rt-r-max-w { 21 | max-width: var(--max-width-lg); 22 | } 23 | } 24 | @media (--xl) { 25 | .xl\:rt-r-max-w { 26 | max-width: var(--max-width-xl); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/min-width.css: -------------------------------------------------------------------------------- 1 | .rt-r-min-w { 2 | min-width: var(--min-width); 3 | } 4 | @media (--xs) { 5 | .xs\:rt-r-min-w { 6 | min-width: var(--min-width-xs); 7 | } 8 | } 9 | @media (--sm) { 10 | .sm\:rt-r-min-w { 11 | min-width: var(--min-width-sm); 12 | } 13 | } 14 | @media (--md) { 15 | .md\:rt-r-min-w { 16 | min-width: var(--min-width-md); 17 | } 18 | } 19 | @media (--lg) { 20 | .lg\:rt-r-min-w { 21 | min-width: var(--min-width-lg); 22 | } 23 | } 24 | @media (--xl) { 25 | .xl\:rt-r-min-w { 26 | min-width: var(--min-width-xl); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-area.css: -------------------------------------------------------------------------------- 1 | .rt-r-ga { 2 | grid-area: var(--grid-area); 3 | } 4 | 5 | @media (--xs) { 6 | .xs\:rt-r-ga { 7 | grid-area: var(--grid-area-xs); 8 | } 9 | } 10 | 11 | @media (--sm) { 12 | .sm\:rt-r-ga { 13 | grid-area: var(--grid-area-sm); 14 | } 15 | } 16 | 17 | @media (--md) { 18 | .md\:rt-r-ga { 19 | grid-area: var(--grid-area-md); 20 | } 21 | } 22 | 23 | @media (--lg) { 24 | .lg\:rt-r-ga { 25 | grid-area: var(--grid-area-lg); 26 | } 27 | } 28 | 29 | @media (--xl) { 30 | .xl\:rt-r-ga { 31 | grid-area: var(--grid-area-xl); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/max-height.css: -------------------------------------------------------------------------------- 1 | .rt-r-max-h { 2 | max-height: var(--max-height); 3 | } 4 | @media (--xs) { 5 | .xs\:rt-r-max-h { 6 | max-height: var(--max-height-xs); 7 | } 8 | } 9 | @media (--sm) { 10 | .sm\:rt-r-max-h { 11 | max-height: var(--max-height-sm); 12 | } 13 | } 14 | @media (--md) { 15 | .md\:rt-r-max-h { 16 | max-height: var(--max-height-md); 17 | } 18 | } 19 | @media (--lg) { 20 | .lg\:rt-r-max-h { 21 | max-height: var(--max-height-lg); 22 | } 23 | } 24 | @media (--xl) { 25 | .xl\:rt-r-max-h { 26 | max-height: var(--max-height-xl); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/min-height.css: -------------------------------------------------------------------------------- 1 | .rt-r-min-h { 2 | min-height: var(--min-height); 3 | } 4 | @media (--xs) { 5 | .xs\:rt-r-min-h { 6 | min-height: var(--min-height-xs); 7 | } 8 | } 9 | @media (--sm) { 10 | .sm\:rt-r-min-h { 11 | min-height: var(--min-height-sm); 12 | } 13 | } 14 | @media (--md) { 15 | .md\:rt-r-min-h { 16 | min-height: var(--min-height-md); 17 | } 18 | } 19 | @media (--lg) { 20 | .lg\:rt-r-min-h { 21 | min-height: var(--min-height-lg); 22 | } 23 | } 24 | @media (--xl) { 25 | .xl\:rt-r-min-h { 26 | min-height: var(--min-height-xl); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import { BaseButton } from './_internal/base-button.js'; 5 | 6 | type ButtonElement = React.ElementRef; 7 | interface ButtonProps extends React.ComponentPropsWithoutRef {} 8 | const Button = React.forwardRef( 9 | ({ className, ...props }, forwardedRef) => ( 10 | 11 | ) 12 | ); 13 | Button.displayName = 'Button'; 14 | 15 | export { Button }; 16 | export type { ButtonProps }; 17 | -------------------------------------------------------------------------------- /apps/playground/app/sink/radix-logo.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const RadixLogo = (props: React.ComponentProps<'svg'>) => ( 4 | 12 | 13 | 14 | 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/align-content.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-ac-start { 3 | align-content: start; 4 | } 5 | 6 | .rt-r-ac-center { 7 | align-content: center; 8 | } 9 | 10 | .rt-r-ac-end { 11 | align-content: end; 12 | } 13 | 14 | .rt-r-ac-baseline { 15 | align-content: baseline; 16 | } 17 | 18 | .rt-r-ac-stretch { 19 | align-content: stretch; 20 | } 21 | 22 | .rt-r-ac-space-between { 23 | align-content: space-between; 24 | } 25 | 26 | .rt-r-ac-space-around { 27 | align-content: space-around; 28 | } 29 | 30 | .rt-r-ac-space-evenly { 31 | align-content: space-evenly; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/scripts/esbuild-cjs.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | 3 | const dir = 'dist/cjs'; 4 | 5 | /** @type {import('esbuild').BuildOptions} */ 6 | const options = { 7 | entryPoints: ['src/**/*.ts*'], 8 | outdir: dir, 9 | format: 'cjs', 10 | target: 'es2020', 11 | sourcemap: true, 12 | minify: true, 13 | }; 14 | 15 | // Check if "watch=true" flag is passed 16 | if (process.argv[2]) { 17 | const [key, value] = process.argv[2].split('='); 18 | if (key === 'watch' && value === 'true') { 19 | const ctx = await esbuild.context(options); 20 | await ctx.watch(); 21 | } 22 | } 23 | 24 | esbuild.build(options).catch(() => process.exit(1)); 25 | -------------------------------------------------------------------------------- /apps/playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playground", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "clean": "rm -rf node_modules .next .turbo", 10 | "lint": "tsc --noEmit" 11 | }, 12 | "dependencies": { 13 | "@radix-ui/react-icons": "^1.3.2", 14 | "@radix-ui/themes": "workspace:*", 15 | "next": "^15.1.2", 16 | "next-themes": "0.2.1", 17 | "react": "^19.0.0", 18 | "react-dom": "^19.0.0", 19 | "react-use": "^17.6.0", 20 | "seedrandom": "3.0.5" 21 | }, 22 | "devDependencies": { 23 | "typescript": "^5.7.2" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/card.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | 3 | import type { PropDef } from '../props/prop-def.js'; 4 | 5 | const sizes = ['1', '2', '3', '4', '5'] as const; 6 | const variants = ['surface', 'classic', 'ghost'] as const; 7 | 8 | const cardPropDefs = { 9 | ...asChildPropDef, 10 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '1', responsive: true }, 11 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 12 | } satisfies { 13 | size: PropDef<(typeof sizes)[number]>; 14 | variant: PropDef<(typeof variants)[number]>; 15 | }; 16 | 17 | export { cardPropDefs }; 18 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/section.css: -------------------------------------------------------------------------------- 1 | .rt-Section { 2 | box-sizing: border-box; 3 | flex-shrink: 0; 4 | } 5 | 6 | @breakpoints { 7 | .rt-Section { 8 | &:where(.rt-r-size-1) { 9 | padding-top: var(--space-5); 10 | padding-bottom: var(--space-5); 11 | } 12 | &:where(.rt-r-size-2) { 13 | padding-top: var(--space-7); 14 | padding-bottom: var(--space-7); 15 | } 16 | &:where(.rt-r-size-3) { 17 | padding-top: var(--space-9); 18 | padding-bottom: var(--space-9); 19 | } 20 | &:where(.rt-r-size-4) { 21 | padding-top: calc(80px * var(--scaling)); 22 | padding-bottom: calc(80px * var(--scaling)); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/icon-button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import { BaseButton } from './_internal/base-button.js'; 5 | 6 | type IconButtonElement = React.ElementRef; 7 | interface IconButtonProps extends React.ComponentPropsWithoutRef {} 8 | const IconButton = React.forwardRef( 9 | ({ className, ...props }, forwardedRef) => ( 10 | 11 | ) 12 | ); 13 | IconButton.displayName = 'IconButton'; 14 | 15 | export { IconButton }; 16 | export type { IconButtonProps }; 17 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ## Description 12 | 13 | 14 | 15 | ## Testing steps 16 | 17 | 18 | 19 | ## Relates issues / PRs 20 | 21 | 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "monorepo", 3 | "private": true, 4 | "packageManager": "pnpm@10.0.0", 5 | "scripts": { 6 | "build": "turbo run build", 7 | "build:pkg": "pnpm --filter @radix-ui/themes build", 8 | "dev": "turbo run dev --no-cache --continue", 9 | "lint": "turbo run lint", 10 | "clean": "turbo run clean && rm -rf node_modules .turbo" 11 | }, 12 | "devDependencies": { 13 | "@types/node": "^20.16.10", 14 | "@types/react": "^19.0.2", 15 | "@types/react-dom": "^19.0.2", 16 | "prettier": "^3.4.2", 17 | "turbo": "^2.3.3", 18 | "typescript": "^5.7.2" 19 | }, 20 | "pnpm": { 21 | "overrides": { 22 | "string-width": "4.2.3" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/display.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-display-block { 3 | display: block; 4 | } 5 | 6 | .rt-r-display-inline { 7 | display: inline; 8 | } 9 | 10 | .rt-r-display-inline-block { 11 | display: inline-block; 12 | } 13 | 14 | .rt-r-display-flex { 15 | display: flex; 16 | } 17 | 18 | .rt-r-display-inline-flex { 19 | display: inline-flex; 20 | } 21 | 22 | .rt-r-display-grid { 23 | display: grid; 24 | } 25 | 26 | .rt-r-display-inline-grid { 27 | display: inline-grid; 28 | } 29 | 30 | .rt-r-display-none { 31 | display: none; 32 | } 33 | 34 | .rt-r-display-contents { 35 | display: contents; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-template-areas.css: -------------------------------------------------------------------------------- 1 | .rt-r-gta { 2 | grid-template-areas: var(--grid-template-areas); 3 | } 4 | @media (--xs) { 5 | .xs\:rt-r-gta { 6 | grid-template-areas: var(--grid-template-areas-xs); 7 | } 8 | } 9 | @media (--sm) { 10 | .sm\:rt-r-gta { 11 | grid-template-areas: var(--grid-template-areas-sm); 12 | } 13 | } 14 | @media (--md) { 15 | .md\:rt-r-gta { 16 | grid-template-areas: var(--grid-template-areas-md); 17 | } 18 | } 19 | @media (--lg) { 20 | .lg\:rt-r-gta { 21 | grid-template-areas: var(--grid-template-areas-lg); 22 | } 23 | } 24 | @media (--xl) { 25 | .xl\:rt-r-gta { 26 | grid-template-areas: var(--grid-template-areas-xl); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/tooltip.props.tsx: -------------------------------------------------------------------------------- 1 | import { widthPropDefs } from '../props/width.props.js'; 2 | 3 | import type { PropDef, GetPropDefTypes } from '../props/prop-def.js'; 4 | 5 | const tooltipPropDefs = { 6 | content: { type: 'ReactNode', required: true }, 7 | width: widthPropDefs.width, 8 | minWidth: widthPropDefs.minWidth, 9 | maxWidth: { ...widthPropDefs.maxWidth, default: '360px' }, 10 | } satisfies { 11 | width: PropDef; 12 | minWidth: PropDef; 13 | maxWidth: PropDef; 14 | content: PropDef; 15 | }; 16 | 17 | type TooltipOwnProps = GetPropDefTypes; 18 | 19 | export { tooltipPropDefs }; 20 | export type { TooltipOwnProps }; 21 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/require-react-element.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | /** A function that throws an error when a value isn't a valid React Element, otherwise returns the value */ 4 | export const requireReactElement = (children: T): T => { 5 | const isReactElement = React.isValidElement(children); 6 | 7 | if (!isReactElement) { 8 | throw Error( 9 | `Expected a single React Element child, but got: ${React.Children.toArray(children) 10 | .map((child) => 11 | typeof child === 'object' && 'type' in child && typeof child.type === 'string' 12 | ? child.type 13 | : typeof child 14 | ) 15 | .join(', ')}` 16 | ); 17 | } 18 | 19 | return children; 20 | }; 21 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/scroll-area.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { radiusPropDef } from '../props/radius.prop.js'; 3 | 4 | import type { PropDef } from '../props/prop-def.js'; 5 | 6 | const sizes = ['1', '2', '3'] as const; 7 | const scrollbarsValues = ['vertical', 'horizontal', 'both'] as const; 8 | 9 | const scrollAreaPropDefs = { 10 | ...asChildPropDef, 11 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '1', responsive: true }, 12 | ...radiusPropDef, 13 | scrollbars: { type: 'enum', values: scrollbarsValues, default: 'both' }, 14 | } satisfies { 15 | size: PropDef<(typeof sizes)[number]>; 16 | scrollbars: PropDef<(typeof scrollbarsValues)[number]>; 17 | }; 18 | 19 | export { scrollAreaPropDefs }; 20 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/_internal/base-radio.props.ts: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../../props/color.prop.js'; 2 | import { highContrastPropDef } from '../../props/high-contrast.prop.js'; 3 | 4 | import type { PropDef } from '../../props/prop-def.js'; 5 | 6 | const sizes = ['1', '2', '3'] as const; 7 | const variants = ['classic', 'surface', 'soft'] as const; 8 | 9 | const baseRadioPropDefs = { 10 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 11 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 12 | ...colorPropDef, 13 | ...highContrastPropDef, 14 | } satisfies { 15 | size: PropDef<(typeof sizes)[number]>; 16 | variant: PropDef<(typeof variants)[number]>; 17 | }; 18 | 19 | export { baseRadioPropDefs }; 20 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/flex-grow.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-fg { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-fg-0 { 6 | flex-grow: 0; 7 | } 8 | .rt-r-fg-1 { 9 | flex-grow: 1; 10 | } 11 | } 12 | 13 | .rt-r-fg { 14 | flex-grow: var(--flex-grow); 15 | } 16 | @media (--xs) { 17 | .xs\:rt-r-fg { 18 | flex-grow: var(--flex-grow-xs); 19 | } 20 | } 21 | @media (--sm) { 22 | .sm\:rt-r-fg { 23 | flex-grow: var(--flex-grow-sm); 24 | } 25 | } 26 | @media (--md) { 27 | .md\:rt-r-fg { 28 | flex-grow: var(--flex-grow-md); 29 | } 30 | } 31 | @media (--lg) { 32 | .lg\:rt-r-fg { 33 | flex-grow: var(--flex-grow-lg); 34 | } 35 | } 36 | @media (--xl) { 37 | .xl\:rt-r-fg { 38 | flex-grow: var(--flex-grow-xl); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/_internal/base-checkbox.props.ts: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../../props/color.prop.js'; 2 | import { highContrastPropDef } from '../../props/high-contrast.prop.js'; 3 | 4 | import type { PropDef } from '../../props/prop-def.js'; 5 | 6 | const sizes = ['1', '2', '3'] as const; 7 | const variants = ['classic', 'surface', 'soft'] as const; 8 | 9 | const baseCheckboxPropDefs = { 10 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 11 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 12 | ...colorPropDef, 13 | ...highContrastPropDef, 14 | } satisfies { 15 | size: PropDef<(typeof sizes)[number]>; 16 | variant: PropDef<(typeof variants)[number]>; 17 | }; 18 | 19 | export { baseCheckboxPropDefs }; 20 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/checkbox-group.css: -------------------------------------------------------------------------------- 1 | .rt-CheckboxGroupRoot { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--space-1); 5 | } 6 | 7 | .rt-CheckboxGroupItem { 8 | display: flex; 9 | gap: 0.5em; 10 | 11 | /* Make sure whitespace to the right of the text is not clickable */ 12 | width: fit-content; 13 | } 14 | 15 | .rt-CheckboxGroupItemCheckbox { 16 | &:where(:focus-visible) { 17 | &::before { 18 | outline: 2px solid var(--focus-8); 19 | outline-offset: 2px; 20 | } 21 | } 22 | 23 | &:where(:disabled) { 24 | cursor: var(--cursor-disabled); 25 | 26 | &::before { 27 | background-color: var(--gray-a3); 28 | } 29 | } 30 | } 31 | 32 | .rt-CheckboxGroupItemInner { 33 | /* Make layouts with text truncation possible */ 34 | min-width: 0; 35 | } 36 | -------------------------------------------------------------------------------- /apps/playground/app/test-tabnav/layout.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Theme, Container, Section, Box } from '@radix-ui/themes'; 3 | import { NextThemeProvider } from '../next-theme-provider'; 4 | import { Nav } from './nav'; 5 | 6 | export default function Test({ children }: { children: React.ReactNode }) { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {children} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/segmented-control.props.tsx: -------------------------------------------------------------------------------- 1 | import { radiusPropDef } from '../props/radius.prop.js'; 2 | 3 | import type { PropDef } from '../props/prop-def.js'; 4 | 5 | const sizes = ['1', '2', '3'] as const; 6 | const variants = ['surface', 'classic'] as const; 7 | 8 | const segmentedControlRootPropDefs = { 9 | disabled: { type: 'boolean', className: 'disabled', default: false }, 10 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 11 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 12 | ...radiusPropDef, 13 | } satisfies { 14 | disabled?: PropDef; 15 | size: PropDef<(typeof sizes)[number]>; 16 | variant: PropDef<(typeof variants)[number]>; 17 | }; 18 | 19 | export { segmentedControlRootPropDefs }; 20 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/flex-shrink.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-fs { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-fs-0 { 6 | flex-shrink: 0; 7 | } 8 | .rt-r-fs-1 { 9 | flex-shrink: 1; 10 | } 11 | } 12 | 13 | .rt-r-fs { 14 | flex-shrink: var(--flex-shrink); 15 | } 16 | @media (--xs) { 17 | .xs\:rt-r-fs { 18 | flex-shrink: var(--flex-shrink-xs); 19 | } 20 | } 21 | @media (--sm) { 22 | .sm\:rt-r-fs { 23 | flex-shrink: var(--flex-shrink-sm); 24 | } 25 | } 26 | @media (--md) { 27 | .md\:rt-r-fs { 28 | flex-shrink: var(--flex-shrink-md); 29 | } 30 | } 31 | @media (--lg) { 32 | .lg\:rt-r-fs { 33 | flex-shrink: var(--flex-shrink-lg); 34 | } 35 | } 36 | @media (--xl) { 37 | .xl\:rt-r-fs { 38 | flex-shrink: var(--flex-shrink-xl); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/reset.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { requireReactElement } from '../helpers/require-react-element.js'; 6 | 7 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 8 | 9 | interface ResetProps extends ComponentPropsWithout {} 10 | const Reset = React.forwardRef( 11 | ({ className, children, ...props }, forwardedRef) => { 12 | return ( 13 | 14 | {requireReactElement(children)} 15 | 16 | ); 17 | } 18 | ); 19 | Reset.displayName = 'Reset'; 20 | 21 | export { Reset }; 22 | export type { ResetProps }; 23 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/slider.props.tsx: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../props/color.prop.js'; 2 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 3 | import { radiusPropDef } from '../props/radius.prop.js'; 4 | 5 | import type { PropDef } from '../props/prop-def.js'; 6 | 7 | const sizes = ['1', '2', '3'] as const; 8 | const variants = ['classic', 'surface', 'soft'] as const; 9 | 10 | const sliderPropDefs = { 11 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 12 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 13 | ...colorPropDef, 14 | ...highContrastPropDef, 15 | ...radiusPropDef, 16 | } satisfies { 17 | size: PropDef<(typeof sizes)[number]>; 18 | variant: PropDef<(typeof variants)[number]>; 19 | }; 20 | 21 | export { sliderPropDefs }; 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/switch.props.tsx: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../props/color.prop.js'; 2 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 3 | import { radiusPropDef } from '../props/radius.prop.js'; 4 | 5 | import type { PropDef } from '../props/prop-def.js'; 6 | 7 | const sizes = ['1', '2', '3'] as const; 8 | const variants = ['classic', 'surface', 'soft'] as const; 9 | 10 | const switchPropDefs = { 11 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 12 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 13 | ...colorPropDef, 14 | ...highContrastPropDef, 15 | ...radiusPropDef, 16 | } satisfies { 17 | size: PropDef<(typeof sizes)[number]>; 18 | variant: PropDef<(typeof variants)[number]>; 19 | }; 20 | 21 | export { switchPropDefs }; 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/postcss-whitespace.cjs: -------------------------------------------------------------------------------- 1 | // Clean up the whitespace mess left behind by other plugins 2 | module.exports = () => ({ 3 | postcssPlugin: 'postcss-whitespace', 4 | Comment(comment) { 5 | // Remove all comments 6 | comment.remove(); 7 | }, 8 | Declaration(decl) { 9 | if (decl.value.includes('\n')) { 10 | // Remove line breaks and consequent spaces 11 | decl.value = decl.value.replace(/\s+/g, ' '); 12 | // Collapse whitespace around round brackets 13 | decl.value = decl.value.replace(/\(\s/g, '('); 14 | decl.value = decl.value.replace(/\s\)/g, ')'); 15 | } 16 | }, 17 | AtRule(rule) { 18 | // Remove line breaks before and after the rule 19 | delete rule.raws.before; 20 | delete rule.raws.after; 21 | }, 22 | Rule(rule) { 23 | rule.cleanRaws(); 24 | }, 25 | }); 26 | 27 | module.exports.postcss = true; 28 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/callout.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { accentColorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | 5 | import type { PropDef } from '../props/prop-def.js'; 6 | 7 | const sizes = ['1', '2', '3'] as const; 8 | const variants = ['soft', 'surface', 'outline'] as const; 9 | 10 | const calloutRootPropDefs = { 11 | ...asChildPropDef, 12 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 13 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'soft' }, 14 | ...accentColorPropDef, 15 | ...highContrastPropDef, 16 | } satisfies { 17 | size: PropDef<(typeof sizes)[number]>; 18 | variant: PropDef<(typeof variants)[number]>; 19 | }; 20 | 21 | export { calloutRootPropDefs }; 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/radio-group.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { colorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | 5 | import type { PropDef } from '../props/prop-def.js'; 6 | 7 | const sizes = ['1', '2', '3'] as const; 8 | const variants = ['classic', 'surface', 'soft'] as const; 9 | 10 | const radioGroupRootPropDefs = { 11 | ...asChildPropDef, 12 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 13 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 14 | ...colorPropDef, 15 | ...highContrastPropDef, 16 | } satisfies { 17 | size: PropDef<(typeof sizes)[number]>; 18 | variant: PropDef<(typeof variants)[number]>; 19 | }; 20 | 21 | export { radioGroupRootPropDefs }; 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/component-props.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | 3 | type ComponentPropsAs< 4 | C extends React.ElementType, 5 | T extends React.ComponentPropsWithoutRef['as'] 6 | > = Omit, { as: T }>, 'as' | 'asChild'>; 7 | 8 | // Omits the specified props from the component props. Autocomplete will suggest props 9 | // of the component, but won't restrict the omittable props to those that actually exist. 10 | type ComponentPropsWithout< 11 | T extends React.ElementType, 12 | O extends 13 | | Omit> 14 | | keyof React.ComponentPropsWithoutRef 15 | > = Omit, O & string>; 16 | 17 | type RemovedProps = 'asChild' | 'defaultChecked' | 'defaultValue' | 'color'; 18 | 19 | export type { ComponentPropsAs, ComponentPropsWithout, RemovedProps }; 20 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/leading-trim.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-lt-normal::before, 3 | .rt-r-lt-end::before, 4 | .rt-r-lt-normal::after, 5 | .rt-r-lt-start::after { 6 | content: none; 7 | } 8 | 9 | .rt-r-lt-start::before, 10 | .rt-r-lt-both::before, 11 | .rt-r-lt-end::after, 12 | .rt-r-lt-both::after { 13 | content: ''; 14 | display: table; 15 | } 16 | 17 | .rt-r-lt-start::before, 18 | .rt-r-lt-both::before { 19 | margin-bottom: calc( 20 | var(--leading-trim-start, var(--default-leading-trim-start)) - 21 | var(--line-height, calc(1em * var(--default-line-height))) / 2 22 | ); 23 | } 24 | 25 | .rt-r-lt-end::after, 26 | .rt-r-lt-both::after { 27 | margin-top: calc( 28 | var(--leading-trim-end, var(--default-leading-trim-end)) - 29 | var(--line-height, calc(1em * var(--default-line-height))) / 2 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/red.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/red.css'; 2 | @import '@radix-ui/colors/red-dark.css'; 3 | @import '@radix-ui/colors/red-alpha.css'; 4 | @import '@radix-ui/colors/red-dark-alpha.css'; 5 | 6 | :root { 7 | --red-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --red-surface: #fff5f5cc; 14 | --red-indicator: var(--red-9); 15 | --red-track: var(--red-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --red-surface: color(display-p3 0.9961 0.9647 0.9647 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --red-surface: #2f151780; 26 | --red-indicator: var(--red-9); 27 | --red-track: var(--red-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --red-surface: color(display-p3 0.1647 0.0863 0.0863 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/gray.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/gray.css'; 2 | @import '@radix-ui/colors/gray-dark.css'; 3 | @import '@radix-ui/colors/gray-alpha.css'; 4 | @import '@radix-ui/colors/gray-dark-alpha.css'; 5 | 6 | :root { 7 | --gray-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --gray-surface: #ffffffcc; 14 | --gray-indicator: var(--gray-9); 15 | --gray-track: var(--gray-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --gray-surface: color(display-p3 1 1 1 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --gray-surface: #21212180; 26 | --gray-indicator: var(--gray-9); 27 | --gray-track: var(--gray-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --gray-surface: color(display-p3 0.1255 0.1255 0.1255 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/sage.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/sage.css'; 2 | @import '@radix-ui/colors/sage-dark.css'; 3 | @import '@radix-ui/colors/sage-alpha.css'; 4 | @import '@radix-ui/colors/sage-dark-alpha.css'; 5 | 6 | :root { 7 | --sage-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --sage-surface: #ffffffcc; 14 | --sage-indicator: var(--sage-9); 15 | --sage-track: var(--sage-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --sage-surface: color(display-p3 1 1 1 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --sage-surface: #1e201f80; 26 | --sage-indicator: var(--sage-9); 27 | --sage-track: var(--sage-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --sage-surface: color(display-p3 0.1176 0.1255 0.1176 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/sand.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/sand.css'; 2 | @import '@radix-ui/colors/sand-dark.css'; 3 | @import '@radix-ui/colors/sand-alpha.css'; 4 | @import '@radix-ui/colors/sand-dark-alpha.css'; 5 | 6 | :root { 7 | --sand-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --sand-surface: #ffffffcc; 14 | --sand-indicator: var(--sand-9); 15 | --sand-track: var(--sand-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --sand-surface: color(display-p3 1 1 1 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --sand-surface: #21212080; 26 | --sand-indicator: var(--sand-9); 27 | --sand-track: var(--sand-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --sand-surface: color(display-p3 0.1255 0.1255 0.1255 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/progress.props.tsx: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../props/color.prop.js'; 2 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 3 | import { radiusPropDef } from '../props/radius.prop.js'; 4 | 5 | import type { PropDef } from '../props/prop-def.js'; 6 | 7 | const sizes = ['1', '2', '3'] as const; 8 | const variants = ['classic', 'surface', 'soft'] as const; 9 | 10 | const progressPropDefs = { 11 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 12 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 13 | ...colorPropDef, 14 | ...highContrastPropDef, 15 | ...radiusPropDef, 16 | duration: { type: 'string' }, 17 | } satisfies { 18 | size: PropDef<(typeof sizes)[number]>; 19 | variant: PropDef<(typeof variants)[number]>; 20 | duration: PropDef; 21 | }; 22 | 23 | export { progressPropDefs }; 24 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/blue.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/blue.css'; 2 | @import '@radix-ui/colors/blue-dark.css'; 3 | @import '@radix-ui/colors/blue-alpha.css'; 4 | @import '@radix-ui/colors/blue-dark-alpha.css'; 5 | 6 | :root { 7 | --blue-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --blue-surface: #f1f9ffcc; 14 | --blue-indicator: var(--blue-9); 15 | --blue-track: var(--blue-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --blue-surface: color(display-p3 0.9529 0.9765 0.9961 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --blue-surface: #11213d80; 26 | --blue-indicator: var(--blue-9); 27 | --blue-track: var(--blue-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --blue-surface: color(display-p3 0.0706 0.1255 0.2196 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/cyan.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/cyan.css'; 2 | @import '@radix-ui/colors/cyan-dark.css'; 3 | @import '@radix-ui/colors/cyan-alpha.css'; 4 | @import '@radix-ui/colors/cyan-dark-alpha.css'; 5 | 6 | :root { 7 | --cyan-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --cyan-surface: #eff9facc; 14 | --cyan-indicator: var(--cyan-9); 15 | --cyan-track: var(--cyan-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --cyan-surface: color(display-p3 0.9412 0.9765 0.9804 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --cyan-surface: #11252d80; 26 | --cyan-indicator: var(--cyan-9); 27 | --cyan-track: var(--cyan-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --cyan-surface: color(display-p3 0.0784 0.1412 0.1725 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/gold.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/gold.css'; 2 | @import '@radix-ui/colors/gold-dark.css'; 3 | @import '@radix-ui/colors/gold-alpha.css'; 4 | @import '@radix-ui/colors/gold-dark-alpha.css'; 5 | 6 | :root { 7 | --gold-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --gold-surface: #f9f8efcc; 14 | --gold-indicator: var(--gold-9); 15 | --gold-track: var(--gold-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --gold-surface: color(display-p3 0.9765 0.9725 0.9412 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --gold-surface: #25231d80; 26 | --gold-indicator: var(--gold-9); 27 | --gold-track: var(--gold-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --gold-surface: color(display-p3 0.1412 0.1333 0.1098 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/iris.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/iris.css'; 2 | @import '@radix-ui/colors/iris-dark.css'; 3 | @import '@radix-ui/colors/iris-alpha.css'; 4 | @import '@radix-ui/colors/iris-dark-alpha.css'; 5 | 6 | :root { 7 | --iris-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --iris-surface: #f6f6ffcc; 14 | --iris-indicator: var(--iris-9); 15 | --iris-track: var(--iris-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --iris-surface: color(display-p3 0.9647 0.9647 0.9961 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --iris-surface: #1d1b3980; 26 | --iris-indicator: var(--iris-9); 27 | --iris-track: var(--iris-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --iris-surface: color(display-p3 0.1098 0.102 0.2118 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/jade.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/jade.css'; 2 | @import '@radix-ui/colors/jade-dark.css'; 3 | @import '@radix-ui/colors/jade-alpha.css'; 4 | @import '@radix-ui/colors/jade-dark-alpha.css'; 5 | 6 | :root { 7 | --jade-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --jade-surface: #f1faf5cc; 14 | --jade-indicator: var(--jade-9); 15 | --jade-track: var(--jade-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --jade-surface: color(display-p3 0.9529 0.9804 0.9608 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --jade-surface: #13271f80; 26 | --jade-indicator: var(--jade-9); 27 | --jade-track: var(--jade-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --jade-surface: color(display-p3 0.0863 0.149 0.1176 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/mauve.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/mauve.css'; 2 | @import '@radix-ui/colors/mauve-dark.css'; 3 | @import '@radix-ui/colors/mauve-alpha.css'; 4 | @import '@radix-ui/colors/mauve-dark-alpha.css'; 5 | 6 | :root { 7 | --mauve-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --mauve-surface: #ffffffcc; 14 | --mauve-indicator: var(--mauve-9); 15 | --mauve-track: var(--mauve-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --mauve-surface: color(display-p3 1 1 1 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --mauve-surface: #22212380; 26 | --mauve-indicator: var(--mauve-9); 27 | --mauve-track: var(--mauve-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --mauve-surface: color(display-p3 0.1333 0.1255 0.1333 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/olive.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/olive.css'; 2 | @import '@radix-ui/colors/olive-dark.css'; 3 | @import '@radix-ui/colors/olive-alpha.css'; 4 | @import '@radix-ui/colors/olive-dark-alpha.css'; 5 | 6 | :root { 7 | --olive-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --olive-surface: #ffffffcc; 14 | --olive-indicator: var(--olive-9); 15 | --olive-track: var(--olive-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --olive-surface: color(display-p3 1 1 1 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --olive-surface: #1f201e80; 26 | --olive-indicator: var(--olive-9); 27 | --olive-track: var(--olive-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --olive-surface: color(display-p3 0.1176 0.1255 0.1176 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/pink.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/pink.css'; 2 | @import '@radix-ui/colors/pink-dark.css'; 3 | @import '@radix-ui/colors/pink-alpha.css'; 4 | @import '@radix-ui/colors/pink-dark-alpha.css'; 5 | 6 | :root { 7 | --pink-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --pink-surface: #fef5facc; 14 | --pink-indicator: var(--pink-9); 15 | --pink-track: var(--pink-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --pink-surface: color(display-p3 0.9922 0.9608 0.9804 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --pink-surface: #31132980; 26 | --pink-indicator: var(--pink-9); 27 | --pink-track: var(--pink-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --pink-surface: color(display-p3 0.1725 0.0784 0.149 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/plum.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/plum.css'; 2 | @import '@radix-ui/colors/plum-dark.css'; 3 | @import '@radix-ui/colors/plum-alpha.css'; 4 | @import '@radix-ui/colors/plum-dark-alpha.css'; 5 | 6 | :root { 7 | --plum-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --plum-surface: #fdf5fdcc; 14 | --plum-indicator: var(--plum-9); 15 | --plum-track: var(--plum-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --plum-surface: color(display-p3 0.9843 0.9647 0.9843 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --plum-surface: #2f152f80; 26 | --plum-indicator: var(--plum-9); 27 | --plum-track: var(--plum-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --plum-surface: color(display-p3 0.1647 0.0863 0.1725 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/ruby.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/ruby.css'; 2 | @import '@radix-ui/colors/ruby-dark.css'; 3 | @import '@radix-ui/colors/ruby-alpha.css'; 4 | @import '@radix-ui/colors/ruby-dark-alpha.css'; 5 | 6 | :root { 7 | --ruby-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --ruby-surface: #fff5f6cc; 14 | --ruby-indicator: var(--ruby-9); 15 | --ruby-track: var(--ruby-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --ruby-surface: color(display-p3 0.9961 0.9647 0.9647 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --ruby-surface: #2b191d80; 26 | --ruby-indicator: var(--ruby-9); 27 | --ruby-track: var(--ruby-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --ruby-surface: color(display-p3 0.1569 0.0941 0.1098 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/slate.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/slate.css'; 2 | @import '@radix-ui/colors/slate-dark.css'; 3 | @import '@radix-ui/colors/slate-alpha.css'; 4 | @import '@radix-ui/colors/slate-dark-alpha.css'; 5 | 6 | :root { 7 | --slate-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --slate-surface: #ffffffcc; 14 | --slate-indicator: var(--slate-9); 15 | --slate-track: var(--slate-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --slate-surface: color(display-p3 1 1 1 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --slate-surface: #1f212380; 26 | --slate-indicator: var(--slate-9); 27 | --slate-track: var(--slate-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --slate-surface: color(display-p3 0.1176 0.1255 0.1333 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/teal.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/teal.css'; 2 | @import '@radix-ui/colors/teal-dark.css'; 3 | @import '@radix-ui/colors/teal-alpha.css'; 4 | @import '@radix-ui/colors/teal-dark-alpha.css'; 5 | 6 | :root { 7 | --teal-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --teal-surface: #f0faf8cc; 14 | --teal-indicator: var(--teal-9); 15 | --teal-track: var(--teal-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --teal-surface: color(display-p3 0.9451 0.9804 0.9725 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --teal-surface: #13272580; 26 | --teal-indicator: var(--teal-9); 27 | --teal-track: var(--teal-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --teal-surface: color(display-p3 0.0863 0.149 0.1412 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/playground/app/sink/page.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | margin-bottom: 400px; 3 | } 4 | 5 | .root :global(summary) { 6 | cursor: pointer; 7 | } 8 | .root :global(summary:focus-visible) { 9 | outline: 2px solid var(--accent-8); 10 | outline-offset: 2px; 11 | } 12 | 13 | .root :global(.hide-cursor), 14 | .root :global(.hide-cursor *) { 15 | cursor: none !important; 16 | } 17 | 18 | .table { 19 | border-collapse: collapse; 20 | } 21 | .table + .table { 22 | margin-top: var(--space-3); 23 | } 24 | 25 | .table thead tr, 26 | .table tbody tr:not(:last-child) { 27 | border-bottom: 1px solid var(--gray-a5); 28 | } 29 | 30 | .table th { 31 | font-weight: 400; 32 | } 33 | 34 | .table th, 35 | .table td { 36 | padding: 0; 37 | padding-top: var(--space-4); 38 | padding-right: var(--space-4); 39 | padding-bottom: var(--space-4); 40 | } 41 | 42 | .table .rowHeaderCell { 43 | padding-left: 0; 44 | padding-right: var(--space-5); 45 | min-width: 100px; 46 | } 47 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/brown.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/brown.css'; 2 | @import '@radix-ui/colors/brown-dark.css'; 3 | @import '@radix-ui/colors/brown-alpha.css'; 4 | @import '@radix-ui/colors/brown-dark-alpha.css'; 5 | 6 | :root { 7 | --brown-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --brown-surface: #fbf8f4cc; 14 | --brown-indicator: var(--brown-9); 15 | --brown-track: var(--brown-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --brown-surface: color(display-p3 0.9843 0.9725 0.9569 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --brown-surface: #271f1b80; 26 | --brown-indicator: var(--brown-9); 27 | --brown-track: var(--brown-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --brown-surface: color(display-p3 0.1412 0.1176 0.102 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/grass.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/grass.css'; 2 | @import '@radix-ui/colors/grass-dark.css'; 3 | @import '@radix-ui/colors/grass-alpha.css'; 4 | @import '@radix-ui/colors/grass-dark-alpha.css'; 5 | 6 | :root { 7 | --grass-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --grass-surface: #f3faf3cc; 14 | --grass-indicator: var(--grass-9); 15 | --grass-track: var(--grass-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --grass-surface: color(display-p3 0.9569 0.9804 0.9569 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --grass-surface: #19231b80; 26 | --grass-indicator: var(--grass-9); 27 | --grass-track: var(--grass-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --grass-surface: color(display-p3 0.102 0.1333 0.102 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/green.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/green.css'; 2 | @import '@radix-ui/colors/green-dark.css'; 3 | @import '@radix-ui/colors/green-alpha.css'; 4 | @import '@radix-ui/colors/green-dark-alpha.css'; 5 | 6 | :root { 7 | --green-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --green-surface: #f1faf4cc; 14 | --green-indicator: var(--green-9); 15 | --green-track: var(--green-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --green-surface: color(display-p3 0.9569 0.9804 0.9608 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --green-surface: #15251d80; 26 | --green-indicator: var(--green-9); 27 | --green-track: var(--green-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --green-surface: color(display-p3 0.0941 0.1412 0.1098 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/separator.props.tsx: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../props/color.prop.js'; 2 | 3 | import type { PropDef } from '../props/prop-def.js'; 4 | 5 | const orientationValues = ['horizontal', 'vertical'] as const; 6 | const sizes = ['1', '2', '3', '4'] as const; 7 | 8 | const separatorPropDefs = { 9 | orientation: { 10 | type: 'enum', 11 | className: 'rt-r-orientation', 12 | values: orientationValues, 13 | default: 'horizontal', 14 | responsive: true, 15 | }, 16 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '1', responsive: true }, 17 | color: { ...colorPropDef.color, default: 'gray' }, 18 | decorative: { type: 'boolean', default: true }, 19 | } satisfies { 20 | orientation: PropDef<(typeof orientationValues)[number]>; 21 | size: PropDef<(typeof sizes)[number]>; 22 | color: typeof colorPropDef.color; 23 | decorative: PropDef; 24 | }; 25 | 26 | export { separatorPropDefs }; 27 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/badge.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { accentColorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { radiusPropDef } from '../props/radius.prop.js'; 5 | 6 | import type { PropDef } from '../props/prop-def.js'; 7 | 8 | const sizes = ['1', '2', '3'] as const; 9 | const variants = ['solid', 'soft', 'surface', 'outline'] as const; 10 | 11 | const badgePropDefs = { 12 | ...asChildPropDef, 13 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '1', responsive: true }, 14 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'soft' }, 15 | ...accentColorPropDef, 16 | ...highContrastPropDef, 17 | ...radiusPropDef, 18 | } satisfies { 19 | size: PropDef<(typeof sizes)[number]>; 20 | variant: PropDef<(typeof variants)[number]>; 21 | }; 22 | 23 | export { badgePropDefs }; 24 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/bronze.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/bronze.css'; 2 | @import '@radix-ui/colors/bronze-dark.css'; 3 | @import '@radix-ui/colors/bronze-alpha.css'; 4 | @import '@radix-ui/colors/bronze-dark-alpha.css'; 5 | 6 | :root { 7 | --bronze-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --bronze-surface: #fdf5f3cc; 14 | --bronze-indicator: var(--bronze-9); 15 | --bronze-track: var(--bronze-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --bronze-surface: color(display-p3 0.9843 0.9608 0.9529 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --bronze-surface: #27211d80; 26 | --bronze-indicator: var(--bronze-9); 27 | --bronze-track: var(--bronze-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --bronze-surface: color(display-p3 0.1412 0.1255 0.1176 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/indigo.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/indigo.css'; 2 | @import '@radix-ui/colors/indigo-dark.css'; 3 | @import '@radix-ui/colors/indigo-alpha.css'; 4 | @import '@radix-ui/colors/indigo-dark-alpha.css'; 5 | 6 | :root { 7 | --indigo-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --indigo-surface: #f5f8ffcc; 14 | --indigo-indicator: var(--indigo-9); 15 | --indigo-track: var(--indigo-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --indigo-surface: color(display-p3 0.9647 0.9725 0.9961 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --indigo-surface: #171d3b80; 26 | --indigo-indicator: var(--indigo-9); 27 | --indigo-track: var(--indigo-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --indigo-surface: color(display-p3 0.0941 0.1098 0.2196 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/orange.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/orange.css'; 2 | @import '@radix-ui/colors/orange-dark.css'; 3 | @import '@radix-ui/colors/orange-alpha.css'; 4 | @import '@radix-ui/colors/orange-dark-alpha.css'; 5 | 6 | :root { 7 | --orange-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --orange-surface: #fff5e9cc; 14 | --orange-indicator: var(--orange-9); 15 | --orange-track: var(--orange-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --orange-surface: color(display-p3 0.9961 0.9608 0.9176 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --orange-surface: #271d1380; 26 | --orange-indicator: var(--orange-9); 27 | --orange-track: var(--orange-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --orange-surface: color(display-p3 0.1412 0.1098 0.0706 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/purple.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/purple.css'; 2 | @import '@radix-ui/colors/purple-dark.css'; 3 | @import '@radix-ui/colors/purple-alpha.css'; 4 | @import '@radix-ui/colors/purple-dark-alpha.css'; 5 | 6 | :root { 7 | --purple-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --purple-surface: #faf5fecc; 14 | --purple-indicator: var(--purple-9); 15 | --purple-track: var(--purple-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --purple-surface: color(display-p3 0.9804 0.9647 0.9922 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --purple-surface: #2b173580; 26 | --purple-indicator: var(--purple-9); 27 | --purple-track: var(--purple-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --purple-surface: color(display-p3 0.149 0.0941 0.1961 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/tomato.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/tomato.css'; 2 | @import '@radix-ui/colors/tomato-dark.css'; 3 | @import '@radix-ui/colors/tomato-alpha.css'; 4 | @import '@radix-ui/colors/tomato-dark-alpha.css'; 5 | 6 | :root { 7 | --tomato-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --tomato-surface: #fff6f5cc; 14 | --tomato-indicator: var(--tomato-9); 15 | --tomato-track: var(--tomato-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --tomato-surface: color(display-p3 0.9922 0.9647 0.9608 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --tomato-surface: #2d191580; 26 | --tomato-indicator: var(--tomato-9); 27 | --tomato-track: var(--tomato-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --tomato-surface: color(display-p3 0.1569 0.0941 0.0784 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/violet.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/violet.css'; 2 | @import '@radix-ui/colors/violet-dark.css'; 3 | @import '@radix-ui/colors/violet-alpha.css'; 4 | @import '@radix-ui/colors/violet-dark-alpha.css'; 5 | 6 | :root { 7 | --violet-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --violet-surface: #f9f6ffcc; 14 | --violet-indicator: var(--violet-9); 15 | --violet-track: var(--violet-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --violet-surface: color(display-p3 0.9725 0.9647 0.9961 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --violet-surface: #25193980; 26 | --violet-indicator: var(--violet-9); 27 | --violet-track: var(--violet-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --violet-surface: color(display-p3 0.1333 0.102 0.2118 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/blockquote.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { colorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { textWrapPropDef } from '../props/text-wrap.prop.js'; 5 | import { truncatePropDef } from '../props/truncate.prop.js'; 6 | import { weightPropDef } from '../props/weight.prop.js'; 7 | 8 | import type { PropDef } from '../props/prop-def.js'; 9 | 10 | const sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] as const; 11 | 12 | const blockquotePropDefs = { 13 | ...asChildPropDef, 14 | size: { 15 | type: 'enum', 16 | className: 'rt-r-size', 17 | values: sizes, 18 | responsive: true, 19 | }, 20 | ...weightPropDef, 21 | ...colorPropDef, 22 | ...highContrastPropDef, 23 | ...truncatePropDef, 24 | ...textWrapPropDef, 25 | } satisfies { 26 | size: PropDef<(typeof sizes)[number]>; 27 | }; 28 | 29 | export { blockquotePropDefs }; 30 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/crimson.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/crimson.css'; 2 | @import '@radix-ui/colors/crimson-dark.css'; 3 | @import '@radix-ui/colors/crimson-alpha.css'; 4 | @import '@radix-ui/colors/crimson-dark-alpha.css'; 5 | 6 | :root { 7 | --crimson-contrast: white; 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --crimson-surface: #fef5f8cc; 14 | --crimson-indicator: var(--crimson-9); 15 | --crimson-track: var(--crimson-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --crimson-surface: color(display-p3 0.9922 0.9608 0.9725 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --crimson-surface: #2f151f80; 26 | --crimson-indicator: var(--crimson-9); 27 | --crimson-track: var(--crimson-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --crimson-surface: color(display-p3 0.1647 0.0863 0.1176 / 0.5); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/overflow.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-overflow-visible { 3 | overflow: visible; 4 | } 5 | .rt-r-overflow-hidden { 6 | overflow: hidden; 7 | } 8 | .rt-r-overflow-clip { 9 | overflow: clip; 10 | } 11 | .rt-r-overflow-scroll { 12 | overflow: scroll; 13 | } 14 | .rt-r-overflow-auto { 15 | overflow: auto; 16 | } 17 | 18 | .rt-r-ox-visible { 19 | overflow-x: visible; 20 | } 21 | .rt-r-ox-hidden { 22 | overflow-x: hidden; 23 | } 24 | .rt-r-ox-clip { 25 | overflow-x: clip; 26 | } 27 | .rt-r-ox-scroll { 28 | overflow-x: scroll; 29 | } 30 | .rt-r-ox-auto { 31 | overflow-x: auto; 32 | } 33 | 34 | .rt-r-oy-visible { 35 | overflow-y: visible; 36 | } 37 | .rt-r-oy-hidden { 38 | overflow-y: hidden; 39 | } 40 | .rt-r-oy-clip { 41 | overflow-y: clip; 42 | } 43 | .rt-r-oy-scroll { 44 | overflow-y: scroll; 45 | } 46 | .rt-r-oy-auto { 47 | overflow-y: auto; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/em.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { emPropDefs } from './em.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | 8 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 9 | import type { GetPropDefTypes } from '../props/prop-def.js'; 10 | 11 | type EmElement = React.ElementRef<'em'>; 12 | type EmOwnProps = GetPropDefTypes; 13 | interface EmProps extends ComponentPropsWithout<'em', RemovedProps>, EmOwnProps {} 14 | const Em = React.forwardRef((props, forwardedRef) => { 15 | const { asChild, className, ...emProps } = extractProps(props, emPropDefs); 16 | const Comp = asChild ? Slot.Root : 'em'; 17 | return ; 18 | }); 19 | Em.displayName = 'Em'; 20 | 21 | export { Em }; 22 | export type { EmProps }; 23 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/get-subtree.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | /** 4 | * This is a helper function that is used when a component supports `asChild` 5 | * using the `Slot` component but its implementation contains nested DOM elements. 6 | * 7 | * Using it ensures if a consumer uses the `asChild` prop, the elements are in 8 | * correct order in the DOM, adopting the intended consumer `children`. 9 | */ 10 | export function getSubtree( 11 | options: { asChild: boolean | undefined; children: React.ReactNode }, 12 | content: React.ReactNode | ((children: React.ReactNode) => React.ReactNode) 13 | ) { 14 | const { asChild, children } = options; 15 | if (!asChild) return typeof content === 'function' ? content(children) : content; 16 | 17 | const firstChild = React.Children.only(children) as React.ReactElement; 18 | return React.cloneElement(firstChild, { 19 | // @ts-expect-error 20 | children: typeof content === 'function' ? content(firstChild.props.children) : content, 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/text-area.props.tsx: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../props/color.prop.js'; 2 | import { radiusPropDef } from '../props/radius.prop.js'; 3 | 4 | import type { PropDef } from '../props/prop-def.js'; 5 | 6 | const sizes = ['1', '2', '3'] as const; 7 | const variants = ['classic', 'surface', 'soft'] as const; 8 | const resizeValues = ['none', 'vertical', 'horizontal', 'both'] as const; 9 | 10 | // prettier-ignore 11 | const textAreaPropDefs = { 12 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 13 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 14 | resize: { type: 'enum', className: 'rt-r-resize', values: resizeValues, responsive: true }, 15 | ...colorPropDef, 16 | ...radiusPropDef, 17 | } satisfies { 18 | size: PropDef<(typeof sizes)[number]>; 19 | variant: PropDef<(typeof variants)[number]>; 20 | resize: PropDef<(typeof resizeValues)[number]>; 21 | }; 22 | 23 | export { textAreaPropDefs }; 24 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/get-matching-gray-color.ts: -------------------------------------------------------------------------------- 1 | import type { accentColors } from '../props/color.prop.js'; 2 | 3 | type ThemeAccentColor = (typeof accentColors)[number]; 4 | 5 | export function getMatchingGrayColor(accentColor: ThemeAccentColor) { 6 | switch (accentColor) { 7 | case 'tomato': 8 | case 'red': 9 | case 'ruby': 10 | case 'crimson': 11 | case 'pink': 12 | case 'plum': 13 | case 'purple': 14 | case 'violet': 15 | return 'mauve'; 16 | case 'iris': 17 | case 'indigo': 18 | case 'blue': 19 | case 'sky': 20 | case 'cyan': 21 | return 'slate'; 22 | case 'teal': 23 | case 'jade': 24 | case 'mint': 25 | case 'green': 26 | return 'sage'; 27 | case 'grass': 28 | case 'lime': 29 | return 'olive'; 30 | case 'yellow': 31 | case 'amber': 32 | case 'orange': 33 | case 'brown': 34 | case 'gold': 35 | case 'bronze': 36 | return 'sand'; 37 | case 'gray': 38 | return 'gray'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /apps/playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Next.js", 4 | "compilerOptions": { 5 | "composite": false, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "inlineSources": false, 9 | "isolatedModules": true, 10 | "moduleResolution": "Bundler", 11 | "noUnusedLocals": false, 12 | "noUnusedParameters": false, 13 | "preserveWatchOutput": true, 14 | "skipLibCheck": true, 15 | "plugins": [{ "name": "next" }], 16 | "allowJs": true, 17 | "declaration": false, 18 | "declarationMap": false, 19 | "incremental": true, 20 | "jsx": "preserve", 21 | "lib": ["dom", "dom.iterable", "esnext"], 22 | "module": "ESNext", 23 | "noEmit": true, 24 | "resolveJsonModule": true, 25 | "strict": false, 26 | "target": "es5", 27 | "strictNullChecks": true 28 | }, 29 | "include": ["src", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 30 | "exclude": ["node_modules"] 31 | } 32 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/quote.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { quotePropDefs } from './quote.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | 8 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 9 | import type { GetPropDefTypes } from '../props/prop-def.js'; 10 | 11 | type QuoteElement = React.ElementRef<'q'>; 12 | type QuoteOwnProps = GetPropDefTypes; 13 | interface QuoteProps extends ComponentPropsWithout<'q', RemovedProps>, QuoteOwnProps {} 14 | const Quote = React.forwardRef((props, forwardedRef) => { 15 | const { asChild, className, ...quoteProps } = extractProps(props, quotePropDefs); 16 | const Comp = asChild ? Slot.Root : 'q'; 17 | return ; 18 | }); 19 | Quote.displayName = 'Quote'; 20 | 21 | export { Quote }; 22 | export type { QuoteProps }; 23 | -------------------------------------------------------------------------------- /apps/playground/app/home-os/page.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | display: flex; 3 | justify-content: center; 4 | padding: var(--space-9); 5 | } 6 | 7 | .guestTrigger { 8 | all: unset; 9 | padding: var(--space-3) var(--space-4); 10 | border: 1px solid var(--gray-7); 11 | border-radius: var(--radius-3); 12 | display: flex; 13 | align-items: center; 14 | justify-content: space-between; 15 | } 16 | 17 | .guestTrigger svg { 18 | animation-duration: 300ms; 19 | animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); 20 | } 21 | .guestTrigger[data-state='open'] svg { 22 | animation-name: iconOpen; 23 | animation-fill-mode: forwards; 24 | } 25 | .guestTrigger[data-state='closed'] svg { 26 | animation-name: iconClosed; 27 | } 28 | 29 | @keyframes iconClosed { 30 | from { 31 | transform: translateY(-4px); 32 | } 33 | to { 34 | transform: translateY(0); 35 | } 36 | } 37 | 38 | @keyframes iconOpen { 39 | 0% { 40 | transform: translateY(4px) rotate(180deg); 41 | } 42 | 43 | to { 44 | transform: translateY(0) rotate(180deg); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/avatar.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { accentColorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { radiusPropDef } from '../props/radius.prop.js'; 5 | 6 | import type { PropDef } from '../props/prop-def.js'; 7 | 8 | const sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] as const; 9 | const variants = ['solid', 'soft'] as const; 10 | 11 | const avatarPropDefs = { 12 | ...asChildPropDef, 13 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '3', responsive: true }, 14 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'soft' }, 15 | ...accentColorPropDef, 16 | ...highContrastPropDef, 17 | ...radiusPropDef, 18 | fallback: { type: 'ReactNode', required: true }, 19 | } satisfies { 20 | size: PropDef<(typeof sizes)[number]>; 21 | variant: PropDef<(typeof variants)[number]>; 22 | fallback: PropDef; 23 | }; 24 | 25 | export { avatarPropDefs }; 26 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/sky.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/sky.css'; 2 | @import '@radix-ui/colors/sky-dark.css'; 3 | @import '@radix-ui/colors/sky-alpha.css'; 4 | @import '@radix-ui/colors/sky-dark-alpha.css'; 5 | 6 | :root { 7 | --sky-contrast: #1c2024; /* light mode slate 12 */ 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --sky-surface: #eef9fdcc; 14 | --sky-indicator: var(--sky-9); 15 | --sky-track: var(--sky-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --sky-surface: color(display-p3 0.9412 0.9765 0.9843 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --sky-surface: #13233b80; 26 | --sky-indicator: var(--sky-9); 27 | --sky-track: var(--sky-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --sky-surface: color(display-p3 0.0863 0.1333 0.2196 / 0.5); 31 | } 32 | } 33 | @supports (color: color-mix(in oklab, white, black)) { 34 | --sky-track: color-mix(in oklab, var(--sky-8), var(--sky-9) 65%); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/radius.css: -------------------------------------------------------------------------------- 1 | [data-radius] { 2 | --radius-1: calc(3px * var(--scaling) * var(--radius-factor)); 3 | --radius-2: calc(4px * var(--scaling) * var(--radius-factor)); 4 | --radius-3: calc(6px * var(--scaling) * var(--radius-factor)); 5 | --radius-4: calc(8px * var(--scaling) * var(--radius-factor)); 6 | --radius-5: calc(12px * var(--scaling) * var(--radius-factor)); 7 | --radius-6: calc(16px * var(--scaling) * var(--radius-factor)); 8 | } 9 | 10 | [data-radius='none'] { 11 | --radius-factor: 0; 12 | --radius-full: 0px; 13 | --radius-thumb: 0.5px; 14 | } 15 | 16 | [data-radius='small'] { 17 | --radius-factor: 0.75; 18 | --radius-full: 0px; 19 | --radius-thumb: 0.5px; 20 | } 21 | 22 | [data-radius='medium'] { 23 | --radius-factor: 1; 24 | --radius-full: 0px; 25 | --radius-thumb: 9999px; 26 | } 27 | 28 | [data-radius='large'] { 29 | --radius-factor: 1.5; 30 | --radius-full: 0px; 31 | --radius-thumb: 9999px; 32 | } 33 | 34 | [data-radius='full'] { 35 | --radius-factor: 1.5; 36 | --radius-full: 9999px; 37 | --radius-thumb: 9999px; 38 | } 39 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/_internal/base-tab-list.props.ts: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../../props/color.prop.js'; 2 | import { highContrastPropDef } from '../../props/high-contrast.prop.js'; 3 | 4 | import type { PropDef } from '../../props/prop-def.js'; 5 | 6 | const sizes = ['1', '2'] as const; 7 | const wrapValues = ['nowrap', 'wrap', 'wrap-reverse'] as const; 8 | const justifyValues = ['start', 'center', 'end'] as const; 9 | 10 | const baseTabListPropDefs = { 11 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 12 | wrap: { 13 | type: 'enum', 14 | className: 'rt-r-fw', 15 | values: wrapValues, 16 | responsive: true, 17 | }, 18 | justify: { 19 | type: 'enum', 20 | className: 'rt-r-jc', 21 | values: justifyValues, 22 | responsive: true, 23 | }, 24 | ...colorPropDef, 25 | ...highContrastPropDef, 26 | } satisfies { 27 | size: PropDef<(typeof sizes)[number]>; 28 | wrap: PropDef<(typeof wrapValues)[number]>; 29 | justify: PropDef<(typeof justifyValues)[number]>; 30 | }; 31 | 32 | export { baseTabListPropDefs }; 33 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/strong.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { extractProps } from '../helpers/extract-props.js'; 6 | import { strongPropDefs } from './strong.props.js'; 7 | 8 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 9 | import type { GetPropDefTypes } from '../props/prop-def.js'; 10 | 11 | type StrongElement = React.ElementRef<'strong'>; 12 | type StrongOwnProps = GetPropDefTypes; 13 | interface StrongProps extends ComponentPropsWithout<'strong', RemovedProps>, StrongOwnProps {} 14 | const Strong = React.forwardRef((props, forwardedRef) => { 15 | const { asChild, className, ...strongProps } = extractProps(props, strongPropDefs); 16 | const Comp = asChild ? Slot.Root : 'strong'; 17 | return ( 18 | 19 | ); 20 | }); 21 | Strong.displayName = 'Strong'; 22 | 23 | export { Strong }; 24 | export type { StrongProps }; 25 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/lime.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/lime.css'; 2 | @import '@radix-ui/colors/lime-dark.css'; 3 | @import '@radix-ui/colors/lime-alpha.css'; 4 | @import '@radix-ui/colors/lime-dark-alpha.css'; 5 | 6 | :root { 7 | --lime-contrast: #1d211c; /* light mode olive 12 */ 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --lime-surface: #f6f9f0cc; 14 | --lime-indicator: var(--lime-9); 15 | --lime-track: var(--lime-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --lime-surface: color(display-p3 0.9725 0.9765 0.9412 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --lime-surface: #1b211580; 26 | --lime-indicator: var(--lime-9); 27 | --lime-track: var(--lime-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --lime-surface: color(display-p3 0.1098 0.1255 0.0784 / 0.5); 31 | } 32 | } 33 | @supports (color: color-mix(in oklab, white, black)) { 34 | --lime-track: color-mix(in oklab, var(--lime-8), var(--lime-9) 65%); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/mint.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/mint.css'; 2 | @import '@radix-ui/colors/mint-dark.css'; 3 | @import '@radix-ui/colors/mint-alpha.css'; 4 | @import '@radix-ui/colors/mint-dark-alpha.css'; 5 | 6 | :root { 7 | --mint-contrast: #1a211e; /* light mode sage 12 */ 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --mint-surface: #effaf8cc; 14 | --mint-indicator: var(--mint-9); 15 | --mint-track: var(--mint-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --mint-surface: color(display-p3 0.9451 0.9804 0.9725 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --mint-surface: #15272780; 26 | --mint-indicator: var(--mint-9); 27 | --mint-track: var(--mint-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --mint-surface: color(display-p3 0.0941 0.149 0.1412 / 0.5); 31 | } 32 | } 33 | @supports (color: color-mix(in oklab, white, black)) { 34 | --mint-track: color-mix(in oklab, var(--mint-8), var(--mint-9) 65%); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/index.css: -------------------------------------------------------------------------------- 1 | @import './colors/gray.css'; 2 | @import './colors/mauve.css'; 3 | @import './colors/slate.css'; 4 | @import './colors/sage.css'; 5 | @import './colors/olive.css'; 6 | @import './colors/sand.css'; 7 | 8 | @import './colors/amber.css'; 9 | @import './colors/blue.css'; 10 | @import './colors/bronze.css'; 11 | @import './colors/brown.css'; 12 | @import './colors/crimson.css'; 13 | @import './colors/cyan.css'; 14 | @import './colors/gold.css'; 15 | @import './colors/grass.css'; 16 | @import './colors/green.css'; 17 | @import './colors/indigo.css'; 18 | @import './colors/iris.css'; 19 | @import './colors/jade.css'; 20 | @import './colors/lime.css'; 21 | @import './colors/mint.css'; 22 | @import './colors/orange.css'; 23 | @import './colors/pink.css'; 24 | @import './colors/plum.css'; 25 | @import './colors/purple.css'; 26 | @import './colors/red.css'; 27 | @import './colors/ruby.css'; 28 | @import './colors/sky.css'; 29 | @import './colors/teal.css'; 30 | @import './colors/tomato.css'; 31 | @import './colors/violet.css'; 32 | @import './colors/yellow.css'; 33 | 34 | @import './base.css'; 35 | -------------------------------------------------------------------------------- /apps/playground/app/sink/pointer-cursors-checkbox.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { Box, Checkbox, Flex, Text } from '@radix-ui/themes'; 3 | import React from 'react'; 4 | 5 | export function PointerCursorsCheckbox() { 6 | const [checked, setChecked] = React.useState(false); 7 | 8 | return ( 9 | 10 | 11 | 12 | setChecked(!!value)} /> 13 | Use pointer cursors 14 | 15 | 16 | {checked && ( 17 | 32 | )} 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 WorkOS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/scripts/esbuild-esm.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | import fs from 'fs'; 3 | import path from 'path'; 4 | import pkg from '../package.json' with { type: 'json' }; 5 | 6 | const dir = 'dist/esm'; 7 | 8 | /** @type {import('esbuild').BuildOptions} */ 9 | const options = { 10 | entryPoints: ['src/**/*.ts*'], 11 | outdir: dir, 12 | format: 'esm', 13 | target: 'es2020', 14 | sourcemap: true, 15 | minify: true, 16 | }; 17 | 18 | // Check if "watch=true" flag is passed 19 | if (process.argv[2]) { 20 | const [key, value] = process.argv[2].split('='); 21 | if (key === 'watch' && value === 'true') { 22 | const ctx = await esbuild.context(options); 23 | await ctx.watch(); 24 | } 25 | } 26 | 27 | esbuild.build(options).catch(() => process.exit(1)); 28 | 29 | // Create a package.json file in the dist/esm directory with "type": "module" field 30 | if (!fs.existsSync(dir)) { 31 | fs.mkdirSync(dir, { recursive: true }); 32 | } 33 | fs.writeFileSync( 34 | path.join(dir, 'package.json'), 35 | JSON.stringify({ type: 'module', sideEffects: pkg.sideEffects }, null, 2) + '\n', 36 | 'utf-8', 37 | ); 38 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/amber.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/amber.css'; 2 | @import '@radix-ui/colors/amber-dark.css'; 3 | @import '@radix-ui/colors/amber-alpha.css'; 4 | @import '@radix-ui/colors/amber-dark-alpha.css'; 5 | 6 | :root { 7 | --amber-contrast: #21201c; /* light mode sand 12 */ 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --amber-surface: #fefae4cc; 14 | --amber-indicator: var(--amber-9); 15 | --amber-track: var(--amber-9); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --amber-surface: color(display-p3 0.9922 0.9843 0.902 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --amber-surface: #271f1380; 26 | --amber-indicator: var(--amber-9); 27 | --amber-track: var(--amber-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --amber-surface: color(display-p3 0.1412 0.1176 0.0784 / 0.5); 31 | } 32 | } 33 | @supports (color: color-mix(in oklab, white, black)) { 34 | --amber-track: color-mix(in oklab, var(--amber-8), var(--amber-9) 75%); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-row.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-gr { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-gr-1 { 6 | grid-row: 1; 7 | } 8 | .rt-r-gr-2 { 9 | grid-row: 2; 10 | } 11 | .rt-r-gr-3 { 12 | grid-row: 3; 13 | } 14 | .rt-r-gr-4 { 15 | grid-row: 4; 16 | } 17 | .rt-r-gr-5 { 18 | grid-row: 5; 19 | } 20 | .rt-r-gr-6 { 21 | grid-row: 6; 22 | } 23 | .rt-r-gr-7 { 24 | grid-row: 7; 25 | } 26 | .rt-r-gr-8 { 27 | grid-row: 8; 28 | } 29 | .rt-r-gr-9 { 30 | grid-row: 9; 31 | } 32 | } 33 | 34 | .rt-r-gr { 35 | grid-row: var(--grid-row); 36 | } 37 | @media (--xs) { 38 | .xs\:rt-r-gr { 39 | grid-row: var(--grid-row-xs); 40 | } 41 | } 42 | @media (--sm) { 43 | .sm\:rt-r-gr { 44 | grid-row: var(--grid-row-sm); 45 | } 46 | } 47 | @media (--md) { 48 | .md\:rt-r-gr { 49 | grid-row: var(--grid-row-md); 50 | } 51 | } 52 | @media (--lg) { 53 | .lg\:rt-r-gr { 54 | grid-row: var(--grid-row-lg); 55 | } 56 | } 57 | @media (--xl) { 58 | .xl\:rt-r-gr { 59 | grid-row: var(--grid-row-xl); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/_internal/base-button.props.ts: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../../props/as-child.prop.js'; 2 | import { accentColorPropDef } from '../../props/color.prop.js'; 3 | import { highContrastPropDef } from '../../props/high-contrast.prop.js'; 4 | import { radiusPropDef } from '../../props/radius.prop.js'; 5 | 6 | import type { PropDef } from '../../props/prop-def.js'; 7 | 8 | const sizes = ['1', '2', '3', '4'] as const; 9 | const variants = ['classic', 'solid', 'soft', 'surface', 'outline', 'ghost'] as const; 10 | 11 | const baseButtonPropDefs = { 12 | ...asChildPropDef, 13 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 14 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'solid' }, 15 | ...accentColorPropDef, 16 | ...highContrastPropDef, 17 | ...radiusPropDef, 18 | loading: { type: 'boolean', className: 'rt-loading', default: false }, 19 | } satisfies { 20 | size: PropDef<(typeof sizes)[number]>; 21 | variant: PropDef<(typeof variants)[number]>; 22 | loading: PropDef; 23 | }; 24 | 25 | export { baseButtonPropDefs }; 26 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/tooltip.css: -------------------------------------------------------------------------------- 1 | .rt-TooltipContent { 2 | box-sizing: border-box; 3 | padding: var(--space-1) var(--space-2); 4 | background-color: var(--gray-12); 5 | border-radius: var(--radius-2); 6 | 7 | transform-origin: var(--radix-tooltip-content-transform-origin); 8 | 9 | animation-duration: 140ms; 10 | animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); 11 | 12 | @media (prefers-reduced-motion: no-preference) { 13 | &:where([data-state='delayed-open']) { 14 | &:where([data-side='top']) { 15 | animation-name: rt-slide-from-top, rt-fade-in; 16 | } 17 | &:where([data-side='bottom']) { 18 | animation-name: rt-slide-from-bottom, rt-fade-in; 19 | } 20 | &:where([data-side='left']) { 21 | animation-name: rt-slide-from-left, rt-fade-in; 22 | } 23 | &:where([data-side='right']) { 24 | animation-name: rt-slide-from-right, rt-fade-in; 25 | } 26 | } 27 | } 28 | } 29 | 30 | .rt-TooltipText { 31 | color: var(--gray-1); 32 | user-select: none; 33 | cursor: default; 34 | } 35 | 36 | .rt-TooltipArrow { 37 | fill: var(--gray-12); 38 | } 39 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/tokens/colors/yellow.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/yellow.css'; 2 | @import '@radix-ui/colors/yellow-dark.css'; 3 | @import '@radix-ui/colors/yellow-alpha.css'; 4 | @import '@radix-ui/colors/yellow-dark-alpha.css'; 5 | 6 | :root { 7 | --yellow-contrast: #21201c; /* light mode sand 12 */ 8 | } 9 | 10 | :root, 11 | .light, 12 | .light-theme { 13 | --yellow-surface: #fefbe4cc; 14 | --yellow-indicator: var(--yellow-10); 15 | --yellow-track: var(--yellow-10); 16 | @supports (color: color(display-p3 1 1 1)) { 17 | @media (color-gamut: p3) { 18 | --yellow-surface: color(display-p3 0.9961 0.9922 0.902 / 0.8); 19 | } 20 | } 21 | } 22 | 23 | .dark, 24 | .dark-theme { 25 | --yellow-surface: #231f1380; 26 | --yellow-indicator: var(--yellow-9); 27 | --yellow-track: var(--yellow-9); 28 | @supports (color: color(display-p3 1 1 1)) { 29 | @media (color-gamut: p3) { 30 | --yellow-surface: color(display-p3 0.1333 0.1176 0.0706 / 0.5); 31 | } 32 | } 33 | @supports (color: color-mix(in oklab, white, black)) { 34 | --yellow-track: color-mix(in oklab, var(--yellow-8), var(--yellow-9) 65%); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /apps/playground/app/test-grid-align-self/page.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Theme, Grid, Text, Box, BoxProps, Code } from '@radix-ui/themes'; 3 | import { NextThemeProvider } from '../next-theme-provider'; 4 | 5 | export default function Test() { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | start 14 | center 15 | end 16 | stretch 17 | 18 | 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | 26 | const BlueBox = ({ children, ...props }: BoxProps) => ( 27 | 28 | 29 | {children} 30 | 31 | 32 | ); 33 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/code.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { accentColorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { textWrapPropDef } from '../props/text-wrap.prop.js'; 5 | import { truncatePropDef } from '../props/truncate.prop.js'; 6 | import { weightPropDef } from '../props/weight.prop.js'; 7 | 8 | import type { PropDef } from '../props/prop-def.js'; 9 | 10 | const sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] as const; 11 | const variants = ['solid', 'soft', 'outline', 'ghost'] as const; 12 | 13 | const codePropDefs = { 14 | ...asChildPropDef, 15 | size: { 16 | type: 'enum', 17 | className: 'rt-r-size', 18 | values: sizes, 19 | responsive: true, 20 | }, 21 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'soft' }, 22 | ...weightPropDef, 23 | ...accentColorPropDef, 24 | ...highContrastPropDef, 25 | ...truncatePropDef, 26 | ...textWrapPropDef, 27 | } satisfies { 28 | size: PropDef<(typeof sizes)[number]>; 29 | variant: PropDef<(typeof variants)[number]>; 30 | }; 31 | 32 | export { codePropDefs }; 33 | -------------------------------------------------------------------------------- /apps/playground/app/test-grid-justify-self/page.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Theme, Grid, Text, Box, BoxProps, Code } from '@radix-ui/themes'; 3 | import { NextThemeProvider } from '../next-theme-provider'; 4 | 5 | export default function Test() { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | start 14 | center 15 | end 16 | stretch 17 | 18 | 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | 26 | const BlueBox = ({ children, ...props }: BoxProps) => ( 27 | 28 | 29 | {children} 30 | 31 | 32 | ); 33 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/radio-cards.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { colorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { gridPropDefs } from './grid.props.js'; 5 | 6 | import type { PropDef } from '../props/prop-def.js'; 7 | 8 | const sizes = ['1', '2', '3'] as const; 9 | const variants = ['surface', 'classic'] as const; 10 | 11 | const radioCardsRootPropDefs = { 12 | ...asChildPropDef, 13 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 14 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 15 | ...colorPropDef, 16 | ...highContrastPropDef, 17 | columns: { ...gridPropDefs.columns, default: 'repeat(auto-fit, minmax(160px, 1fr))' }, 18 | gap: { ...gridPropDefs.gap, default: '4' }, 19 | } satisfies { 20 | size: PropDef<(typeof sizes)[number]>; 21 | variant: PropDef<(typeof variants)[number]>; 22 | columns: PropDef<(typeof gridPropDefs.columns.values)[number]>; 23 | gap: PropDef<(typeof gridPropDefs.gap.values)[number]>; 24 | }; 25 | 26 | export { radioCardsRootPropDefs }; 27 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-column.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-gc { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-gc-1 { 6 | grid-column: 1; 7 | } 8 | .rt-r-gc-2 { 9 | grid-column: 2; 10 | } 11 | .rt-r-gc-3 { 12 | grid-column: 3; 13 | } 14 | .rt-r-gc-4 { 15 | grid-column: 4; 16 | } 17 | .rt-r-gc-5 { 18 | grid-column: 5; 19 | } 20 | .rt-r-gc-6 { 21 | grid-column: 6; 22 | } 23 | .rt-r-gc-7 { 24 | grid-column: 7; 25 | } 26 | .rt-r-gc-8 { 27 | grid-column: 8; 28 | } 29 | .rt-r-gc-9 { 30 | grid-column: 9; 31 | } 32 | } 33 | 34 | .rt-r-gc { 35 | grid-column: var(--grid-column); 36 | } 37 | @media (--xs) { 38 | .xs\:rt-r-gc { 39 | grid-column: var(--grid-column-xs); 40 | } 41 | } 42 | @media (--sm) { 43 | .sm\:rt-r-gc { 44 | grid-column: var(--grid-column-sm); 45 | } 46 | } 47 | @media (--md) { 48 | .md\:rt-r-gc { 49 | grid-column: var(--grid-column-md); 50 | } 51 | } 52 | @media (--lg) { 53 | .lg\:rt-r-gc { 54 | grid-column: var(--grid-column-lg); 55 | } 56 | } 57 | @media (--xl) { 58 | .xl\:rt-r-gc { 59 | grid-column: var(--grid-column-xl); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/checkbox-cards.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { colorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { gridPropDefs } from './grid.props.js'; 5 | 6 | import type { PropDef } from '../props/prop-def.js'; 7 | 8 | const sizes = ['1', '2', '3'] as const; 9 | const variants = ['surface', 'classic'] as const; 10 | 11 | const checkboxCardsRootPropDefs = { 12 | ...asChildPropDef, 13 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 14 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 15 | ...colorPropDef, 16 | ...highContrastPropDef, 17 | columns: { ...gridPropDefs.columns, default: 'repeat(auto-fit, minmax(200px, 1fr))' }, 18 | gap: { ...gridPropDefs.gap, default: '4' }, 19 | } satisfies { 20 | size: PropDef<(typeof sizes)[number]>; 21 | variant: PropDef<(typeof variants)[number]>; 22 | columns: PropDef<(typeof gridPropDefs.columns.values)[number]>; 23 | gap: PropDef<(typeof gridPropDefs.gap.values)[number]>; 24 | }; 25 | 26 | export { checkboxCardsRootPropDefs }; 27 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/popover.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { heightPropDefs } from '../props/height.props.js'; 3 | import { widthPropDefs } from '../props/width.props.js'; 4 | 5 | import type { PropDef, GetPropDefTypes } from '../props/prop-def.js'; 6 | 7 | const contentSizes = ['1', '2', '3', '4'] as const; 8 | 9 | const popoverContentPropDefs = { 10 | ...asChildPropDef, 11 | size: { 12 | type: 'enum', 13 | className: 'rt-r-size', 14 | values: contentSizes, 15 | default: '2', 16 | responsive: true, 17 | }, 18 | width: widthPropDefs.width, 19 | minWidth: widthPropDefs.minWidth, 20 | maxWidth: { ...widthPropDefs.maxWidth, default: '480px' }, 21 | ...heightPropDefs, 22 | } satisfies { 23 | width: PropDef; 24 | minWidth: PropDef; 25 | maxWidth: PropDef; 26 | size: PropDef<(typeof contentSizes)[number]>; 27 | }; 28 | 29 | type PopoverContentOwnProps = GetPropDefTypes< 30 | typeof popoverContentPropDefs & 31 | typeof asChildPropDef & 32 | typeof widthPropDefs & 33 | typeof heightPropDefs 34 | >; 35 | 36 | export { popoverContentPropDefs }; 37 | export type { PopoverContentOwnProps }; 38 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/hover-card.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { heightPropDefs } from '../props/height.props.js'; 3 | import { widthPropDefs } from '../props/width.props.js'; 4 | 5 | import type { PropDef, GetPropDefTypes } from '../props/prop-def.js'; 6 | 7 | const contentSizes = ['1', '2', '3'] as const; 8 | 9 | const hoverCardContentPropDefs = { 10 | ...asChildPropDef, 11 | size: { 12 | type: 'enum', 13 | className: 'rt-r-size', 14 | values: contentSizes, 15 | default: '2', 16 | responsive: true, 17 | }, 18 | width: widthPropDefs.width, 19 | minWidth: widthPropDefs.minWidth, 20 | maxWidth: { ...widthPropDefs.maxWidth, default: '480px' }, 21 | ...heightPropDefs, 22 | } satisfies { 23 | width: PropDef; 24 | minWidth: PropDef; 25 | maxWidth: PropDef; 26 | size: PropDef<(typeof contentSizes)[number]>; 27 | }; 28 | 29 | type HoverCardContentOwnProps = GetPropDefTypes< 30 | typeof hoverCardContentPropDefs & 31 | typeof asChildPropDef & 32 | typeof widthPropDefs & 33 | typeof heightPropDefs 34 | >; 35 | 36 | export { hoverCardContentPropDefs }; 37 | export type { HoverCardContentOwnProps }; 38 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/layout.css: -------------------------------------------------------------------------------- 1 | @import '../breakpoints.css'; 2 | 3 | @import './align-content.css'; 4 | @import './align-items.css'; 5 | @import './align-self.css'; 6 | @import './display.css'; 7 | @import './flex-basis.css'; 8 | @import './flex-direction.css'; 9 | @import './flex-grow.css'; 10 | @import './flex-shrink.css'; 11 | @import './flex-wrap.css'; 12 | @import './gap.css'; 13 | @import './grid-area.css'; 14 | @import './grid-auto-flow.css'; 15 | @import './grid-column.css'; 16 | @import './grid-column-start.css'; 17 | @import './grid-column-end.css'; 18 | @import './grid-row.css'; 19 | @import './grid-row-start.css'; 20 | @import './grid-row-end.css'; 21 | @import './grid-template-areas.css'; 22 | @import './grid-template-columns.css'; 23 | @import './grid-template-rows.css'; 24 | @import './height.css'; 25 | @import './min-height.css'; 26 | @import './max-height.css'; 27 | @import './inset.css'; 28 | @import './justify-content.css'; 29 | @import './justify-items.css'; 30 | @import './justify-self.css'; 31 | @import './margin.css'; 32 | @import './overflow.css'; 33 | @import './padding.css'; 34 | @import './position.css'; 35 | @import './width.css'; 36 | @import './min-width.css'; 37 | @import './max-width.css'; 38 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-row-end.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-gre { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-gre-1 { 6 | grid-row-end: 1; 7 | } 8 | .rt-r-gre-2 { 9 | grid-row-end: 2; 10 | } 11 | .rt-r-gre-3 { 12 | grid-row-end: 3; 13 | } 14 | .rt-r-gre-4 { 15 | grid-row-end: 4; 16 | } 17 | .rt-r-gre-5 { 18 | grid-row-end: 5; 19 | } 20 | .rt-r-gre-6 { 21 | grid-row-end: 6; 22 | } 23 | .rt-r-gre-7 { 24 | grid-row-end: 7; 25 | } 26 | .rt-r-gre-8 { 27 | grid-row-end: 8; 28 | } 29 | .rt-r-gre-9 { 30 | grid-row-end: 9; 31 | } 32 | } 33 | 34 | .rt-r-gre { 35 | grid-row-end: var(--grid-row-end); 36 | } 37 | @media (--xs) { 38 | .xs\:rt-r-gre { 39 | grid-row-end: var(--grid-row-end-xs); 40 | } 41 | } 42 | @media (--sm) { 43 | .sm\:rt-r-gre { 44 | grid-row-end: var(--grid-row-end-sm); 45 | } 46 | } 47 | @media (--md) { 48 | .md\:rt-r-gre { 49 | grid-row-end: var(--grid-row-end-md); 50 | } 51 | } 52 | @media (--lg) { 53 | .lg\:rt-r-gre { 54 | grid-row-end: var(--grid-row-end-lg); 55 | } 56 | } 57 | @media (--xl) { 58 | .xl\:rt-r-gre { 59 | grid-row-end: var(--grid-row-end-xl); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/inset.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { insetPropDefs } from './inset.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { marginPropDefs } from '../props/margin.props.js'; 8 | 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 11 | import type { GetPropDefTypes } from '../props/prop-def.js'; 12 | 13 | type InsetElement = React.ElementRef<'div'>; 14 | type InsetOwnProps = GetPropDefTypes; 15 | interface InsetProps 16 | extends ComponentPropsWithout<'div', RemovedProps>, 17 | MarginProps, 18 | InsetOwnProps {} 19 | 20 | const Inset = React.forwardRef((props, forwardedRef) => { 21 | const { asChild, className, ...insetProps } = extractProps(props, insetPropDefs, marginPropDefs); 22 | const Comp = asChild ? Slot.Root : 'div'; 23 | return ; 24 | }); 25 | Inset.displayName = 'Inset'; 26 | 27 | export { Inset }; 28 | export type { InsetProps }; 29 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/kbd.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { kbdPropDefs } from './kbd.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { marginPropDefs } from '../props/margin.props.js'; 8 | 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 11 | import type { GetPropDefTypes } from '../props/prop-def.js'; 12 | 13 | type KbdElement = React.ElementRef<'kbd'>; 14 | type KbdOwnProps = GetPropDefTypes; 15 | interface KbdProps extends ComponentPropsWithout<'kbd', RemovedProps>, MarginProps, KbdOwnProps {} 16 | const Kbd = React.forwardRef((props, forwardedRef) => { 17 | const { asChild, className, ...kbdProps } = extractProps(props, kbdPropDefs, marginPropDefs); 18 | const Comp = asChild ? Slot.Root : 'kbd'; 19 | return ( 20 | 25 | ); 26 | }); 27 | Kbd.displayName = 'Kbd'; 28 | 29 | export { Kbd }; 30 | export type { KbdProps }; 31 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/card.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { cardPropDefs } from './card.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { marginPropDefs } from '../props/margin.props.js'; 8 | 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 11 | import type { GetPropDefTypes } from '../props/prop-def.js'; 12 | 13 | type CardElement = React.ElementRef<'div'>; 14 | type CardOwnProps = GetPropDefTypes; 15 | interface CardProps extends ComponentPropsWithout<'div', RemovedProps>, MarginProps, CardOwnProps {} 16 | const Card = React.forwardRef((props, forwardedRef) => { 17 | const { asChild, className, ...cardProps } = extractProps(props, cardPropDefs, marginPropDefs); 18 | const Comp = asChild ? Slot.Root : 'div'; 19 | return ( 20 | 25 | ); 26 | }); 27 | Card.displayName = 'Card'; 28 | 29 | export { Card }; 30 | export type { CardProps }; 31 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/color.prop.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef } from './prop-def.js'; 2 | 3 | // prettier-ignore 4 | const accentColors = ['gray', 'gold', 'bronze', 'brown', 'yellow', 'amber', 'orange', 'tomato', 'red', 'ruby', 'crimson', 'pink', 'plum', 'purple', 'violet', 'iris', 'indigo', 'blue', 'cyan', 'teal', 'jade', 'green', 'grass', 'lime', 'mint', 'sky'] as const; 5 | 6 | const grayColors = ['auto', 'gray', 'mauve', 'slate', 'sage', 'olive', 'sand'] as const; 7 | 8 | const colorPropDef = { 9 | color: { 10 | type: 'enum', 11 | values: accentColors, 12 | default: undefined as (typeof accentColors)[number] | undefined, 13 | }, 14 | } satisfies { 15 | color: PropDef<(typeof accentColors)[number]>; 16 | }; 17 | 18 | // 1. When used on components that compose Text, sets the color of the text to the current accent. 19 | // 2. Defines accent color for descendant text components with `highContrast={true}`. 20 | const accentColorPropDef = { 21 | color: { 22 | type: 'enum', 23 | values: accentColors, 24 | default: '' as (typeof accentColors)[number], 25 | }, 26 | } satisfies { 27 | color: PropDef<(typeof accentColors)[number]>; 28 | }; 29 | 30 | export { 31 | accentColorPropDef, 32 | colorPropDef, 33 | // 34 | accentColors, 35 | grayColors, 36 | }; 37 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-row-start.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-grs { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-grs-1 { 6 | grid-row-start: 1; 7 | } 8 | .rt-r-grs-2 { 9 | grid-row-start: 2; 10 | } 11 | .rt-r-grs-3 { 12 | grid-row-start: 3; 13 | } 14 | .rt-r-grs-4 { 15 | grid-row-start: 4; 16 | } 17 | .rt-r-grs-5 { 18 | grid-row-start: 5; 19 | } 20 | .rt-r-grs-6 { 21 | grid-row-start: 6; 22 | } 23 | .rt-r-grs-7 { 24 | grid-row-start: 7; 25 | } 26 | .rt-r-grs-8 { 27 | grid-row-start: 8; 28 | } 29 | .rt-r-grs-9 { 30 | grid-row-start: 9; 31 | } 32 | } 33 | 34 | .rt-r-grs { 35 | grid-row-start: var(--grid-row-start); 36 | } 37 | @media (--xs) { 38 | .xs\:rt-r-grs { 39 | grid-row-start: var(--grid-row-start-xs); 40 | } 41 | } 42 | @media (--sm) { 43 | .sm\:rt-r-grs { 44 | grid-row-start: var(--grid-row-start-sm); 45 | } 46 | } 47 | @media (--md) { 48 | .md\:rt-r-grs { 49 | grid-row-start: var(--grid-row-start-md); 50 | } 51 | } 52 | @media (--lg) { 53 | .lg\:rt-r-grs { 54 | grid-row-start: var(--grid-row-start-lg); 55 | } 56 | } 57 | @media (--xl) { 58 | .xl\:rt-r-grs { 59 | grid-row-start: var(--grid-row-start-xl); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-column-end.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-gce { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-gce-1 { 6 | grid-column-end: 1; 7 | } 8 | .rt-r-gce-2 { 9 | grid-column-end: 2; 10 | } 11 | .rt-r-gce-3 { 12 | grid-column-end: 3; 13 | } 14 | .rt-r-gce-4 { 15 | grid-column-end: 4; 16 | } 17 | .rt-r-gce-5 { 18 | grid-column-end: 5; 19 | } 20 | .rt-r-gce-6 { 21 | grid-column-end: 6; 22 | } 23 | .rt-r-gce-7 { 24 | grid-column-end: 7; 25 | } 26 | .rt-r-gce-8 { 27 | grid-column-end: 8; 28 | } 29 | .rt-r-gce-9 { 30 | grid-column-end: 9; 31 | } 32 | } 33 | 34 | .rt-r-gce { 35 | grid-column-end: var(--grid-column-end); 36 | } 37 | @media (--xs) { 38 | .xs\:rt-r-gce { 39 | grid-column-end: var(--grid-column-end-xs); 40 | } 41 | } 42 | @media (--sm) { 43 | .sm\:rt-r-gce { 44 | grid-column-end: var(--grid-column-end-sm); 45 | } 46 | } 47 | @media (--md) { 48 | .md\:rt-r-gce { 49 | grid-column-end: var(--grid-column-end-md); 50 | } 51 | } 52 | @media (--lg) { 53 | .lg\:rt-r-gce { 54 | grid-column-end: var(--grid-column-end-lg); 55 | } 56 | } 57 | @media (--xl) { 58 | .xl\:rt-r-gce { 59 | grid-column-end: var(--grid-column-end-xl); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/link.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { accentColorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { leadingTrimPropDef } from '../props/leading-trim.prop.js'; 5 | import { textWrapPropDef } from '../props/text-wrap.prop.js'; 6 | import { truncatePropDef } from '../props/truncate.prop.js'; 7 | import { weightPropDef } from '../props/weight.prop.js'; 8 | 9 | import type { PropDef } from '../props/prop-def.js'; 10 | 11 | const sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] as const; 12 | const underline = ['auto', 'always', 'hover', 'none'] as const; 13 | 14 | const linkPropDefs = { 15 | ...asChildPropDef, 16 | size: { 17 | type: 'enum', 18 | className: 'rt-r-size', 19 | values: sizes, 20 | responsive: true, 21 | }, 22 | ...weightPropDef, 23 | ...leadingTrimPropDef, 24 | ...truncatePropDef, 25 | ...textWrapPropDef, 26 | underline: { type: 'enum', className: 'rt-underline', values: underline, default: 'auto' }, 27 | ...accentColorPropDef, 28 | ...highContrastPropDef, 29 | } satisfies { 30 | size: PropDef<(typeof sizes)[number]>; 31 | underline: PropDef<(typeof underline)[number]>; 32 | }; 33 | 34 | export { linkPropDefs }; 35 | -------------------------------------------------------------------------------- /apps/playground/app/snapshot/page.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | min-width: 1280px; 3 | max-width: 1600px; 4 | margin: 0 auto; 5 | } 6 | 7 | .search { 8 | flex: 1; 9 | display: flex; 10 | align-items: center; 11 | height: var(--space-7); 12 | border-radius: max(var(--radius-3), var(--radius-full)); 13 | border: none; 14 | background-color: var(--gray-a5); 15 | padding: 0 var(--space-5); 16 | } 17 | .search:focus { 18 | outline-color: var(--accent-9); 19 | } 20 | 21 | .grid { 22 | display: grid; 23 | padding: var(--space-5); 24 | grid-template-columns: repeat(3, 1fr); 25 | gap: var(--space-5); 26 | } 27 | 28 | .imageCard { 29 | position: relative; 30 | } 31 | 32 | .imageCardOverlay { 33 | position: absolute; 34 | inset: 0px; 35 | background-image: linear-gradient(-135deg, var(--black-a8), transparent); 36 | padding: var(--space-3); 37 | opacity: 0; 38 | } 39 | 40 | .imageCard:hover .imageCardOverlay, 41 | .imageCard:focus-within .imageCardOverlay, 42 | .imageCardOverlay[data-visible] { 43 | opacity: 1; 44 | } 45 | 46 | .downloadPopover { 47 | accent-color: var(--accent-9); 48 | } 49 | 50 | .container { 51 | padding-left: var(--space-5); 52 | padding-right: var(--space-5); 53 | } 54 | @media (min-width: 1600px) { 55 | .container { 56 | padding-left: 0; 57 | padding-right: 0; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/text.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { colorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { leadingTrimPropDef } from '../props/leading-trim.prop.js'; 5 | import { textAlignPropDef } from '../props/text-align.prop.js'; 6 | import { textWrapPropDef } from '../props/text-wrap.prop.js'; 7 | import { truncatePropDef } from '../props/truncate.prop.js'; 8 | import { weightPropDef } from '../props/weight.prop.js'; 9 | 10 | import type { PropDef } from '../props/prop-def.js'; 11 | 12 | const as = ['span', 'div', 'label', 'p'] as const; 13 | const sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] as const; 14 | 15 | const textPropDefs = { 16 | as: { type: 'enum', values: as, default: 'span' }, 17 | ...asChildPropDef, 18 | size: { 19 | type: 'enum', 20 | className: 'rt-r-size', 21 | values: sizes, 22 | responsive: true, 23 | }, 24 | ...weightPropDef, 25 | ...textAlignPropDef, 26 | ...leadingTrimPropDef, 27 | ...truncatePropDef, 28 | ...textWrapPropDef, 29 | ...colorPropDef, 30 | ...highContrastPropDef, 31 | } satisfies { 32 | as: PropDef<(typeof as)[number]>; 33 | size: PropDef<(typeof sizes)[number]>; 34 | }; 35 | 36 | export { textPropDefs }; 37 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-column-start.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-gcs { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-gcs-1 { 6 | grid-column-start: 1; 7 | } 8 | .rt-r-gcs-2 { 9 | grid-column-start: 2; 10 | } 11 | .rt-r-gcs-3 { 12 | grid-column-start: 3; 13 | } 14 | .rt-r-gcs-4 { 15 | grid-column-start: 4; 16 | } 17 | .rt-r-gcs-5 { 18 | grid-column-start: 5; 19 | } 20 | .rt-r-gcs-6 { 21 | grid-column-start: 6; 22 | } 23 | .rt-r-gcs-7 { 24 | grid-column-start: 7; 25 | } 26 | .rt-r-gcs-8 { 27 | grid-column-start: 8; 28 | } 29 | .rt-r-gcs-9 { 30 | grid-column-start: 9; 31 | } 32 | } 33 | 34 | .rt-r-gcs { 35 | grid-column-start: var(--grid-column-start); 36 | } 37 | @media (--xs) { 38 | .xs\:rt-r-gcs { 39 | grid-column-start: var(--grid-column-start-xs); 40 | } 41 | } 42 | @media (--sm) { 43 | .sm\:rt-r-gcs { 44 | grid-column-start: var(--grid-column-start-sm); 45 | } 46 | } 47 | @media (--md) { 48 | .md\:rt-r-gcs { 49 | grid-column-start: var(--grid-column-start-md); 50 | } 51 | } 52 | @media (--lg) { 53 | .lg\:rt-r-gcs { 54 | grid-column-start: var(--grid-column-start-lg); 55 | } 56 | } 57 | @media (--xl) { 58 | .xl\:rt-r-gcs { 59 | grid-column-start: var(--grid-column-start-xl); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/blockquote.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { Text } from './text.js'; 6 | 7 | import type { blockquotePropDefs } from './blockquote.props.js'; 8 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { GetPropDefTypes } from '../props/prop-def.js'; 11 | 12 | type BlockquoteElement = React.ElementRef<'blockquote'>; 13 | type BlockQuoteOwnProps = GetPropDefTypes; 14 | interface BlockquoteProps 15 | extends ComponentPropsWithout<'blockquote', RemovedProps>, 16 | MarginProps, 17 | BlockQuoteOwnProps {} 18 | const Blockquote = React.forwardRef((props, forwardedRef) => { 19 | const { asChild, children, className, ...blockquoteProps } = props; 20 | const Comp = asChild ? Slot.Root : 'blockquote'; 21 | return ( 22 | 28 | {children} 29 | 30 | ); 31 | }); 32 | Blockquote.displayName = 'Blockquote'; 33 | 34 | export { Blockquote }; 35 | export type { BlockquoteProps }; 36 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/heading.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { colorPropDef } from '../props/color.prop.js'; 3 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 4 | import { leadingTrimPropDef } from '../props/leading-trim.prop.js'; 5 | import { textAlignPropDef } from '../props/text-align.prop.js'; 6 | import { textWrapPropDef } from '../props/text-wrap.prop.js'; 7 | import { truncatePropDef } from '../props/truncate.prop.js'; 8 | import { weightPropDef } from '../props/weight.prop.js'; 9 | 10 | import type { PropDef } from '../props/prop-def.js'; 11 | 12 | const as = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const; 13 | const sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] as const; 14 | 15 | const headingPropDefs = { 16 | as: { type: 'enum', values: as, default: 'h1' }, 17 | ...asChildPropDef, 18 | size: { 19 | type: 'enum', 20 | className: 'rt-r-size', 21 | values: sizes, 22 | default: '6', 23 | responsive: true, 24 | }, 25 | ...weightPropDef, 26 | ...textAlignPropDef, 27 | ...leadingTrimPropDef, 28 | ...truncatePropDef, 29 | ...textWrapPropDef, 30 | ...colorPropDef, 31 | ...highContrastPropDef, 32 | } satisfies { 33 | as: PropDef<(typeof as)[number]>; 34 | size: PropDef<(typeof sizes)[number]>; 35 | }; 36 | 37 | export { headingPropDefs }; 38 | -------------------------------------------------------------------------------- /apps/playground/app/test-avatar/page.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Theme, Avatar, Flex, ThemePanel } from '@radix-ui/themes'; 3 | import { NextThemeProvider } from '../next-theme-provider'; 4 | 5 | export default function Test() { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | } /> 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | 27 | function CustomUserIcon() { 28 | return ( 29 | 35 | 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/box.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | 3 | import type { PropDef, GetPropDefTypes } from '../props/prop-def.js'; 4 | 5 | const as = ['div', 'span'] as const; 6 | const displayValues = ['none', 'inline', 'inline-block', 'block', 'contents'] as const; 7 | 8 | const boxPropDefs = { 9 | /** 10 | * Controls whether to render **div** or **span** 11 | * 12 | * @example 13 | * as="div" 14 | * as="span" 15 | */ 16 | as: { type: 'enum', values: as, default: 'div' }, 17 | ...asChildPropDef, 18 | /** 19 | * Sets the CSS **display** property. 20 | * Supports a subset of the corresponding CSS values and responsive objects. 21 | * 22 | * @example 23 | * display="inline-block" 24 | * display={{ sm: 'none', lg: 'block' }} 25 | * 26 | * @link 27 | * https://developer.mozilla.org/en-US/docs/Web/CSS/display 28 | */ 29 | display: { 30 | type: 'enum', 31 | className: 'rt-r-display', 32 | values: displayValues, 33 | responsive: true, 34 | }, 35 | } satisfies { 36 | as: PropDef<(typeof as)[number]>; 37 | display: PropDef<(typeof displayValues)[number]>; 38 | }; 39 | 40 | // Use all of the imported prop defs to ensure that JSDoc works 41 | type BoxOwnProps = GetPropDefTypes; 42 | 43 | export { boxPropDefs }; 44 | export type { BoxOwnProps }; 45 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/container.css: -------------------------------------------------------------------------------- 1 | .radix-themes { 2 | --container-1: 448px; 3 | --container-2: 688px; 4 | --container-3: 880px; 5 | --container-4: 1136px; 6 | } 7 | 8 | .rt-Container { 9 | display: flex; 10 | box-sizing: border-box; 11 | flex-direction: column; 12 | align-items: center; 13 | flex-shrink: 0; 14 | flex-grow: 1; 15 | } 16 | 17 | .rt-ContainerInner { 18 | width: 100%; 19 | } 20 | 21 | /*************************************************************************************************** 22 | * * 23 | * SIZES * 24 | * * 25 | ***************************************************************************************************/ 26 | 27 | @breakpoints { 28 | .rt-ContainerInner { 29 | :where(.rt-Container.rt-r-size-1) & { 30 | max-width: var(--container-1); 31 | } 32 | :where(.rt-Container.rt-r-size-2) & { 33 | max-width: var(--container-2); 34 | } 35 | :where(.rt-Container.rt-r-size-3) & { 36 | max-width: var(--container-3); 37 | } 38 | :where(.rt-Container.rt-r-size-4) & { 39 | max-width: var(--container-4); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/link.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import { Text } from './text.js'; 5 | import { extractProps } from '../helpers/extract-props.js'; 6 | import { linkPropDefs } from './link.props.js'; 7 | 8 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { GetPropDefTypes } from '../props/prop-def.js'; 11 | 12 | type LinkElement = React.ElementRef<'a'>; 13 | type LinkOwnProps = GetPropDefTypes; 14 | interface LinkProps extends ComponentPropsWithout<'a', RemovedProps>, MarginProps, LinkOwnProps {} 15 | const Link = React.forwardRef((props, forwardedRef) => { 16 | const { children, className, color, asChild, ...linkProps } = extractProps(props, linkPropDefs); 17 | return ( 18 | 25 | {asChild ? ( 26 | children 27 | ) : ( 28 | // eslint-disable-next-line jsx-a11y/anchor-is-valid 29 | {children} 30 | )} 31 | 32 | ); 33 | }); 34 | Link.displayName = 'Link'; 35 | 36 | export { Link }; 37 | export type { LinkProps }; 38 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/select.props.tsx: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../props/color.prop.js'; 2 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 3 | import { radiusPropDef } from '../props/radius.prop.js'; 4 | 5 | import type { PropDef } from '../props/prop-def.js'; 6 | 7 | const sizes = ['1', '2', '3'] as const; 8 | 9 | const selectRootPropDefs = { 10 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 11 | } satisfies { 12 | size: PropDef<(typeof sizes)[number]>; 13 | }; 14 | 15 | const triggerVariants = ['classic', 'surface', 'soft', 'ghost'] as const; 16 | 17 | const selectTriggerPropDefs = { 18 | variant: { type: 'enum', className: 'rt-variant', values: triggerVariants, default: 'surface' }, 19 | ...colorPropDef, 20 | ...radiusPropDef, 21 | placeholder: { type: 'string' }, 22 | } satisfies { 23 | variant: PropDef<(typeof triggerVariants)[number]>; 24 | placeholder: PropDef; 25 | }; 26 | 27 | const contentVariants = ['solid', 'soft'] as const; 28 | 29 | const selectContentPropDefs = { 30 | variant: { type: 'enum', className: 'rt-variant', values: contentVariants, default: 'solid' }, 31 | ...colorPropDef, 32 | ...highContrastPropDef, 33 | } satisfies { 34 | variant: PropDef<(typeof contentVariants)[number]>; 35 | }; 36 | 37 | export { selectRootPropDefs, selectTriggerPropDefs, selectContentPropDefs }; 38 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/text-field.props.tsx: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../props/color.prop.js'; 2 | import { paddingPropDefs } from '../props/padding.props.js'; 3 | import { radiusPropDef } from '../props/radius.prop.js'; 4 | import { flexPropDefs } from './flex.props.js'; 5 | 6 | import type { PropDef } from '../props/prop-def.js'; 7 | 8 | const sizes = ['1', '2', '3'] as const; 9 | const variants = ['classic', 'surface', 'soft'] as const; 10 | 11 | const textFieldRootPropDefs = { 12 | size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true }, 13 | variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' }, 14 | ...colorPropDef, 15 | ...radiusPropDef, 16 | } satisfies { 17 | size: PropDef<(typeof sizes)[number]>; 18 | variant: PropDef<(typeof variants)[number]>; 19 | }; 20 | 21 | const sides = ['left', 'right'] as const; 22 | 23 | const textFieldSlotPropDefs = { 24 | side: { type: 'enum', values: sides }, 25 | ...colorPropDef, 26 | gap: flexPropDefs.gap, 27 | px: paddingPropDefs.px, 28 | pl: paddingPropDefs.pl, 29 | pr: paddingPropDefs.pr, 30 | } satisfies { 31 | side: PropDef<(typeof sides)[number]>; 32 | gap: typeof flexPropDefs.gap; 33 | px: typeof paddingPropDefs.px; 34 | pl: typeof paddingPropDefs.pl; 35 | pr: typeof paddingPropDefs.pr; 36 | }; 37 | 38 | export { textFieldRootPropDefs, textFieldSlotPropDefs }; 39 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/separator.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import { separatorPropDefs } from './separator.props.js'; 5 | import { extractProps } from '../helpers/extract-props.js'; 6 | import { marginPropDefs } from '../props/margin.props.js'; 7 | 8 | import type { MarginProps } from '../props/margin.props.js'; 9 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 10 | import type { GetPropDefTypes } from '../props/prop-def.js'; 11 | 12 | type SeparatorElement = React.ElementRef<'span'>; 13 | type SeparatorOwnProps = GetPropDefTypes; 14 | interface SeparatorProps 15 | extends ComponentPropsWithout<'span', RemovedProps>, 16 | MarginProps, 17 | SeparatorOwnProps {} 18 | const Separator = React.forwardRef((props, forwardedRef) => { 19 | const { className, color, decorative, ...separatorProps } = extractProps( 20 | props, 21 | separatorPropDefs, 22 | marginPropDefs 23 | ); 24 | return ( 25 | 32 | ); 33 | }); 34 | Separator.displayName = 'Separator'; 35 | 36 | export { Separator }; 37 | export type { SeparatorProps }; 38 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/badge.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { badgePropDefs } from './badge.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { marginPropDefs } from '../props/margin.props.js'; 8 | 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 11 | import type { GetPropDefTypes } from '../props/prop-def.js'; 12 | 13 | type BadgeElement = React.ElementRef<'span'>; 14 | type BadgeOwnProps = GetPropDefTypes; 15 | interface BadgeProps 16 | extends ComponentPropsWithout<'span', RemovedProps>, 17 | MarginProps, 18 | BadgeOwnProps {} 19 | const Badge = React.forwardRef((props, forwardedRef) => { 20 | const { asChild, className, color, radius, ...badgeProps } = extractProps( 21 | props, 22 | badgePropDefs, 23 | marginPropDefs 24 | ); 25 | const Comp = asChild ? Slot.Root : 'span'; 26 | return ( 27 | 34 | ); 35 | }); 36 | Badge.displayName = 'Badge'; 37 | 38 | export { Badge }; 39 | export type { BadgeProps }; 40 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/section.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { sectionPropDefs } from './section.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { layoutPropDefs } from '../props/layout.props.js'; 8 | import { marginPropDefs } from '../props/margin.props.js'; 9 | 10 | import type { LayoutProps } from '../props/layout.props.js'; 11 | import type { MarginProps } from '../props/margin.props.js'; 12 | import type { SectionOwnProps } from './section.props.js'; 13 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 14 | 15 | type SectionElement = React.ElementRef<'div'>; 16 | interface SectionProps 17 | extends ComponentPropsWithout<'div', RemovedProps>, 18 | MarginProps, 19 | LayoutProps, 20 | SectionOwnProps {} 21 | const Section = React.forwardRef((props, forwardedRef) => { 22 | const { asChild, className, ...sectionProps } = extractProps( 23 | props, 24 | sectionPropDefs, 25 | layoutPropDefs, 26 | marginPropDefs 27 | ); 28 | const Comp = asChild ? Slot.Root : 'section'; 29 | return ( 30 | 31 | ); 32 | }); 33 | Section.displayName = 'Section'; 34 | 35 | export { Section }; 36 | export type { SectionProps }; 37 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/dialog.props.tsx: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../props/as-child.prop.js'; 2 | import { widthPropDefs } from '../props/width.props.js'; 3 | import { heightPropDefs } from '../props/height.props.js'; 4 | 5 | import type { PropDef, GetPropDefTypes } from '../props/prop-def.js'; 6 | 7 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 8 | const alignValues = ['start', 'center'] as const; 9 | const contentSizes = ['1', '2', '3', '4'] as const; 10 | 11 | const dialogContentPropDefs = { 12 | ...asChildPropDef, 13 | align: { 14 | type: 'enum', 15 | className: 'rt-r-align', 16 | values: ['start', 'center'], 17 | default: 'center', 18 | }, 19 | size: { 20 | type: 'enum', 21 | className: 'rt-r-size', 22 | values: contentSizes, 23 | default: '3', 24 | responsive: true, 25 | }, 26 | width: widthPropDefs.width, 27 | minWidth: widthPropDefs.minWidth, 28 | maxWidth: { ...widthPropDefs.maxWidth, default: '600px' }, 29 | ...heightPropDefs, 30 | } satisfies { 31 | align: PropDef<(typeof alignValues)[number]>; 32 | size: PropDef<(typeof contentSizes)[number]>; 33 | width: PropDef; 34 | minWidth: PropDef; 35 | maxWidth: PropDef; 36 | }; 37 | 38 | type DialogContentOwnProps = GetPropDefTypes< 39 | typeof dialogContentPropDefs & typeof asChildPropDef & typeof widthPropDefs 40 | >; 41 | 42 | export { dialogContentPropDefs }; 43 | export type { DialogContentOwnProps }; 44 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/helpers/map-prop-values.ts: -------------------------------------------------------------------------------- 1 | import type { baseButtonPropDefs } from '../components/_internal/base-button.props.js'; 2 | import type { calloutRootPropDefs } from '../components/callout.props.js'; 3 | import type { spinnerPropDefs } from '../components/spinner.props.js'; 4 | import type { textPropDefs } from '../components/text.props.js'; 5 | import type { Responsive } from '../props/prop-def.js'; 6 | 7 | function mapResponsiveProp( 8 | propValue: Responsive | undefined, 9 | mapValue: (value: Input) => Output 10 | ): Responsive | undefined { 11 | if (propValue === undefined) return undefined; 12 | if (typeof propValue === 'string') { 13 | return mapValue(propValue); 14 | } 15 | return Object.fromEntries( 16 | Object.entries(propValue).map(([key, value]) => [key, mapValue(value)]) 17 | ); 18 | } 19 | 20 | function mapCalloutSizeToTextSize( 21 | size: (typeof calloutRootPropDefs.size.values)[number] 22 | ): (typeof textPropDefs.size.values)[number] { 23 | return size === '3' ? '3' : '2'; 24 | } 25 | 26 | function mapButtonSizeToSpinnerSize( 27 | size: (typeof baseButtonPropDefs.size.values)[number] 28 | ): (typeof spinnerPropDefs.size.values)[number] { 29 | switch (size) { 30 | case '1': 31 | return '1'; 32 | case '2': 33 | case '3': 34 | return '2'; 35 | case '4': 36 | return '3'; 37 | } 38 | } 39 | 40 | export { mapResponsiveProp, mapCalloutSizeToTextSize, mapButtonSizeToSpinnerSize }; 41 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/heading.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { headingPropDefs } from './heading.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { marginPropDefs } from '../props/margin.props.js'; 8 | 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 11 | import type { GetPropDefTypes } from '../props/prop-def.js'; 12 | 13 | type HeadingElement = React.ElementRef<'h1'>; 14 | type HeadingOwnProps = GetPropDefTypes; 15 | interface HeadingProps 16 | extends ComponentPropsWithout<'h1', RemovedProps>, 17 | MarginProps, 18 | HeadingOwnProps {} 19 | 20 | const Heading = React.forwardRef((props, forwardedRef) => { 21 | const { 22 | children, 23 | className, 24 | asChild, 25 | as: Tag = 'h1', 26 | color, 27 | ...headingProps 28 | } = extractProps(props, headingPropDefs, marginPropDefs); 29 | return ( 30 | 36 | {asChild ? children : {children}} 37 | 38 | ); 39 | }); 40 | Heading.displayName = 'Heading'; 41 | 42 | export { Heading }; 43 | export type { HeadingProps }; 44 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/box.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import { Slot } from './slot.js'; 5 | import { boxPropDefs } from './box.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { layoutPropDefs } from '../props/layout.props.js'; 8 | import { marginPropDefs } from '../props/margin.props.js'; 9 | 10 | import type { LayoutProps } from '../props/layout.props.js'; 11 | import type { MarginProps } from '../props/margin.props.js'; 12 | import type { BoxOwnProps } from './box.props.js'; 13 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 14 | 15 | type BoxElement = React.ElementRef<'div'>; 16 | interface CommonBoxProps extends MarginProps, LayoutProps, BoxOwnProps {} 17 | type BoxDivProps = { as?: 'div' } & ComponentPropsWithout<'div', RemovedProps>; 18 | type BoxSpanProps = { as: 'span' } & ComponentPropsWithout<'span', RemovedProps>; 19 | type BoxProps = CommonBoxProps & (BoxSpanProps | BoxDivProps); 20 | 21 | const Box = React.forwardRef((props, forwardedRef) => { 22 | const { 23 | className, 24 | asChild, 25 | as: Tag = 'div', 26 | ...boxProps 27 | } = extractProps(props, boxPropDefs, layoutPropDefs, marginPropDefs); 28 | const Comp = asChild ? Slot : Tag; 29 | return ; 30 | }); 31 | Box.displayName = 'Box'; 32 | 33 | export { Box }; 34 | export type { BoxProps }; 35 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/theme-panel.css: -------------------------------------------------------------------------------- 1 | .rt-ThemePanelShortcut { 2 | &:where(:focus-visible) { 3 | outline-style: solid; 4 | outline-width: 2px; 5 | outline-offset: 2px; 6 | outline-color: var(--accent-9); 7 | } 8 | } 9 | 10 | .rt-ThemePanelSwatch, 11 | .rt-ThemePanelRadioCard { 12 | position: relative; 13 | } 14 | 15 | .rt-ThemePanelSwatchInput, 16 | .rt-ThemePanelRadioCardInput { 17 | appearance: none; 18 | margin: 0; 19 | outline: none; 20 | outline-width: 2px; 21 | position: absolute; 22 | inset: 0; 23 | border-radius: inherit; 24 | 25 | /* iOS Safari */ 26 | width: 100%; 27 | height: 100%; 28 | } 29 | 30 | .rt-ThemePanelSwatch { 31 | width: var(--space-5); 32 | height: var(--space-5); 33 | border-radius: 100%; 34 | } 35 | 36 | .rt-ThemePanelSwatchInput { 37 | outline-offset: 2px; 38 | 39 | &:where(:checked) { 40 | outline-style: solid; 41 | outline-color: var(--gray-12); 42 | } 43 | &:where(:focus-visible) { 44 | outline-style: solid; 45 | outline-color: var(--accent-9); 46 | } 47 | } 48 | 49 | .rt-ThemePanelRadioCard { 50 | border-radius: var(--radius-1); 51 | box-shadow: 0 0 0 1px var(--gray-7); 52 | } 53 | 54 | .rt-ThemePanelRadioCardInput { 55 | outline-offset: -1px; 56 | 57 | &:where(:checked) { 58 | outline-style: solid; 59 | outline-color: var(--gray-12); 60 | } 61 | &:where(:focus-visible) { 62 | background-color: var(--accent-a3); 63 | outline-style: solid; 64 | outline-color: var(--accent-9); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](https://radix-ui.com/themes) 2 | 3 | # Radix Themes 4 | 5 | **An open-source component library optimized for fast development, easy maintenance, and accessibility.** 6 | 7 | --- 8 | 9 | ## Documentation 10 | 11 | For full documentation, visit [radix-ui.com/themes/docs](https://radix-ui.com/themes/docs). 12 | 13 | ## Releases 14 | 15 | For changelog, visit [radix-ui.com/themes/docs/overview/releases](https://radix-ui.com/themes/docs/overview/releases). 16 | 17 | ## Authors 18 | 19 | - Benoît Grélard ([@benoitgrelard](https://twitter.com/benoitgrelard)) 20 | - Vlad Moroz ([@vladyslavmoroz](https://twitter.com/vladyslavmoroz)) 21 | - Andy Hook ([@Andy_Hook](https://twitter.com/Andy_Hook)) 22 | - Lucas Motta ([@elmotta](https://twitter.com/elmotta)) 23 | 24 | --- 25 | 26 | ## Community 27 | 28 | See our [contribution guidelines](./.github/CONTRIBUTING.md) for information on local development and creating a pull request. 29 | 30 | - [Github Discussions](https://github.com/radix-ui/themes/discussions) - Ask questions and get answers from other community members. 31 | - [Discord](https://discord.com/invite/7Xb99uG) - To get involved with the Radix community, ask questions and share tips. 32 | - [Twitter](https://twitter.com/radix_ui) - To receive updates, announcements, blog posts, and general Radix tips. 33 | 34 | ## License 35 | 36 | Licensed under the MIT License, Copyright © 2023-present [WorkOS](https://workos.com). 37 | 38 | See [LICENSE](./LICENSE) for more information. 39 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/code.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { codePropDefs } from './code.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { marginPropDefs } from '../props/margin.props.js'; 8 | 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 11 | import type { GetPropDefTypes } from '../props/prop-def.js'; 12 | 13 | type CodeElement = React.ElementRef<'code'>; 14 | type CodeOwnProps = GetPropDefTypes; 15 | interface CodeProps 16 | extends ComponentPropsWithout<'code', RemovedProps>, 17 | MarginProps, 18 | CodeOwnProps {} 19 | const Code = React.forwardRef((props, forwardedRef) => { 20 | const { asChild, className, color, ...codeProps } = extractProps( 21 | props, 22 | codePropDefs, 23 | marginPropDefs 24 | ); 25 | // Code ghost color prop should work as text color by default 26 | const resolvedColor = props.variant === 'ghost' ? color || undefined : color; 27 | const Comp = asChild ? Slot.Root : 'code'; 28 | return ( 29 | 35 | ); 36 | }); 37 | Code.displayName = 'Code'; 38 | 39 | export { Code }; 40 | export type { CodeProps }; 41 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/_internal/base-menu.props.ts: -------------------------------------------------------------------------------- 1 | import { asChildPropDef } from '../../props/as-child.prop.js'; 2 | import { colorPropDef } from '../../props/color.prop.js'; 3 | import { highContrastPropDef } from '../../props/high-contrast.prop.js'; 4 | 5 | import type { PropDef } from '../../props/prop-def.js'; 6 | 7 | const contentSizes = ['1', '2'] as const; 8 | const contentVariants = ['solid', 'soft'] as const; 9 | 10 | const baseMenuContentPropDefs = { 11 | size: { 12 | type: 'enum', 13 | className: 'rt-r-size', 14 | values: contentSizes, 15 | default: '2', 16 | responsive: true, 17 | }, 18 | variant: { 19 | type: 'enum', 20 | className: 'rt-variant', 21 | values: contentVariants, 22 | default: 'solid', 23 | }, 24 | ...colorPropDef, 25 | ...highContrastPropDef, 26 | } satisfies { 27 | size: PropDef<(typeof contentSizes)[number]>; 28 | variant: PropDef<(typeof contentVariants)[number]>; 29 | }; 30 | 31 | const baseMenuItemPropDefs = { 32 | ...asChildPropDef, 33 | ...colorPropDef, 34 | shortcut: { type: 'string' }, 35 | } satisfies { 36 | shortcut: PropDef; 37 | }; 38 | 39 | const baseMenuCheckboxItemPropDefs = { 40 | ...colorPropDef, 41 | shortcut: { type: 'string' }, 42 | } satisfies { 43 | shortcut: PropDef; 44 | }; 45 | 46 | const baseMenuRadioItemPropDefs = { 47 | ...colorPropDef, 48 | }; 49 | 50 | export { 51 | baseMenuContentPropDefs, 52 | baseMenuItemPropDefs, 53 | baseMenuCheckboxItemPropDefs, 54 | baseMenuRadioItemPropDefs, 55 | }; 56 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/flex.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import { extractProps } from '../helpers/extract-props.js'; 5 | import { layoutPropDefs } from '../props/layout.props.js'; 6 | import { marginPropDefs } from '../props/margin.props.js'; 7 | import { Slot } from './slot.js'; 8 | import { flexPropDefs } from './flex.props.js'; 9 | 10 | import type { FlexOwnProps } from './flex.props.js'; 11 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 12 | import type { LayoutProps } from '../props/layout.props.js'; 13 | import type { MarginProps } from '../props/margin.props.js'; 14 | 15 | type FlexElement = React.ElementRef<'div'>; 16 | interface CommonFlexProps extends MarginProps, LayoutProps, FlexOwnProps {} 17 | type FlexDivProps = { as?: 'div' } & ComponentPropsWithout<'div', RemovedProps>; 18 | type FlexSpanProps = { as: 'span' } & ComponentPropsWithout<'span', RemovedProps>; 19 | type FlexProps = CommonFlexProps & (FlexSpanProps | FlexDivProps); 20 | 21 | const Flex = React.forwardRef((props, forwardedRef) => { 22 | const { 23 | className, 24 | asChild, 25 | as: Tag = 'div', 26 | ...flexProps 27 | } = extractProps(props, flexPropDefs, layoutPropDefs, marginPropDefs); 28 | const Comp = asChild ? Slot : Tag; 29 | return ; 30 | }); 31 | Flex.displayName = 'Flex'; 32 | 33 | export { Flex }; 34 | export type { FlexProps }; 35 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/grid.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import { Slot } from './slot.js'; 5 | import { gridPropDefs } from './grid.props.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { layoutPropDefs } from '../props/layout.props.js'; 8 | import { marginPropDefs } from '../props/margin.props.js'; 9 | 10 | import type { LayoutProps } from '../props/layout.props.js'; 11 | import type { MarginProps } from '../props/margin.props.js'; 12 | import type { GridOwnProps } from './grid.props.js'; 13 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 14 | 15 | type GridElement = React.ElementRef<'div'>; 16 | interface CommonGridProps extends MarginProps, LayoutProps, GridOwnProps {} 17 | type GridDivProps = { as?: 'div' } & ComponentPropsWithout<'div', RemovedProps>; 18 | type GridSpanProps = { as: 'span' } & ComponentPropsWithout<'span', RemovedProps>; 19 | type GridProps = CommonGridProps & (GridSpanProps | GridDivProps); 20 | 21 | const Grid = React.forwardRef((props, forwardedRef) => { 22 | const { 23 | className, 24 | asChild, 25 | as: Tag = 'div', 26 | ...gridProps 27 | } = extractProps(props, gridPropDefs, layoutPropDefs, marginPropDefs); 28 | const Comp = asChild ? Slot : Tag; 29 | return ; 30 | }); 31 | Grid.displayName = 'Grid'; 32 | 33 | export { Grid }; 34 | export type { GridProps }; 35 | -------------------------------------------------------------------------------- /release-process.md: -------------------------------------------------------------------------------- 1 | # Release process 2 | 3 | > This is a work-in-progress document and will be updated as we refine our release process. 4 | 5 | ## Release strategy 6 | 7 | We track versions during the pull request process. As features are added, modified or improved it's important to keep track of these via versioning. 8 | 9 | ### Tracking version changes 10 | 11 | This is currently done manually. PRs that fix bugs or add features should include an addition to `packages/radix-ui-themes/changelog.md` under a new version heading. The actual release version may differ, so be sure to double check this at publish time. 12 | 13 | ### Publishing a stable release 14 | 15 | 1. Checkout latest `main` 16 | 2. Run `pnpm clean && pnpm i && pnpm build:pkg` 17 | 3. Run `pnpm lint` and ensure there are no errors 18 | 4. Update the version in `packages/radix-ui-themes/package.json` and ensure the changelog is up to date 19 | 5. Run `pnpm publish -r` to publish the new version 20 | 21 | - If publishing a pre-release version, use `pnpm publish -r --tag `, where `` is the pre-release tag (e.g. `alpha`, `beta`, `rc`) 22 | 23 | ## Updating documentation 24 | 25 | Our documentation is in a [separate repository](https://github.com/radix-ui/website) and updating it is a three step process: 26 | 27 | 1. Write and update the [change log](https://github.com/radix-ui/website/blob/main/data/themes/docs/overview/releases.mdx) 28 | 2. Bump package version/s and create / update the pages for each version change 29 | 3. Perform documentation updates and remove live demos from previous versions 30 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/README.md: -------------------------------------------------------------------------------- 1 | [](https://radix-ui.com/themes) 2 | 3 | # Radix Themes 4 | 5 | **An open-source component library optimized for fast development, easy maintenance, and accessibility.** 6 | 7 | --- 8 | 9 | ## Documentation 10 | 11 | For full documentation, visit [radix-ui.com/themes/docs](https://radix-ui.com/themes/docs). 12 | 13 | ## Releases 14 | 15 | For changelog, visit [radix-ui.com/themes/docs/overview/releases](https://radix-ui.com/themes/docs/overview/releases). 16 | 17 | ## Authors 18 | 19 | - Benoît Grélard ([@benoitgrelard](https://twitter.com/benoitgrelard)) 20 | - Vlad Moroz ([@vladyslavmoroz](https://twitter.com/vladyslavmoroz)) 21 | - Andy Hook ([@Andy_Hook](https://twitter.com/Andy_Hook)) 22 | - Lucas Motta ([@elmotta](https://twitter.com/elmotta)) 23 | 24 | --- 25 | 26 | ## Community 27 | 28 | See our [contribution guidelines](../../.github/CONTRIBUTING.md) for information on local development and creating a pull request. 29 | 30 | - [Github Discussions](https://github.com/radix-ui/themes/discussions) - Ask questions and get answers from other community members. 31 | - [Discord](https://discord.com/invite/7Xb99uG) - To get involved with the Radix community, ask questions and share tips. 32 | - [Twitter](https://twitter.com/radix_ui) - To receive updates, announcements, blog posts, and general Radix tips. 33 | 34 | ## License 35 | 36 | Licensed under the MIT License, Copyright © 2023-present [WorkOS](https://workos.com). 37 | 38 | See [LICENSE](./LICENSE) for more information. 39 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/text-area.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import { textAreaPropDefs } from './text-area.props.js'; 5 | import { extractProps } from '../helpers/extract-props.js'; 6 | import { marginPropDefs } from '../props/margin.props.js'; 7 | 8 | import type { MarginProps } from '../props/margin.props.js'; 9 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 10 | import type { GetPropDefTypes } from '../props/prop-def.js'; 11 | 12 | type TextAreaElement = React.ElementRef<'textarea'>; 13 | type TextAreaOwnProps = GetPropDefTypes & { 14 | defaultValue?: string; 15 | value?: string; 16 | }; 17 | interface TextAreaProps 18 | extends ComponentPropsWithout<'textarea', RemovedProps | 'size' | 'value'>, 19 | MarginProps, 20 | TextAreaOwnProps {} 21 | const TextArea = React.forwardRef((props, forwardedRef) => { 22 | const { className, color, radius, style, ...textAreaProps } = extractProps( 23 | props, 24 | textAreaPropDefs, 25 | marginPropDefs 26 | ); 27 | return ( 28 | 34 | 35 | 36 | ); 37 | }); 38 | TextArea.displayName = 'TextArea'; 39 | 40 | export { TextArea }; 41 | export type { TextAreaProps }; 42 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-template-rows.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-gtr { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-gtr-1 { 6 | grid-template-rows: minmax(0, 1fr); 7 | } 8 | .rt-r-gtr-2 { 9 | grid-template-rows: repeat(2, minmax(0, 1fr)); 10 | } 11 | .rt-r-gtr-3 { 12 | grid-template-rows: repeat(3, minmax(0, 1fr)); 13 | } 14 | .rt-r-gtr-4 { 15 | grid-template-rows: repeat(4, minmax(0, 1fr)); 16 | } 17 | .rt-r-gtr-5 { 18 | grid-template-rows: repeat(5, minmax(0, 1fr)); 19 | } 20 | .rt-r-gtr-6 { 21 | grid-template-rows: repeat(6, minmax(0, 1fr)); 22 | } 23 | .rt-r-gtr-7 { 24 | grid-template-rows: repeat(7, minmax(0, 1fr)); 25 | } 26 | .rt-r-gtr-8 { 27 | grid-template-rows: repeat(8, minmax(0, 1fr)); 28 | } 29 | .rt-r-gtr-9 { 30 | grid-template-rows: repeat(9, minmax(0, 1fr)); 31 | } 32 | } 33 | 34 | .rt-r-gtr { 35 | grid-template-rows: var(--grid-template-rows); 36 | } 37 | @media (--xs) { 38 | .xs\:rt-r-gtr { 39 | grid-template-rows: var(--grid-template-rows-xs); 40 | } 41 | } 42 | @media (--sm) { 43 | .sm\:rt-r-gtr { 44 | grid-template-rows: var(--grid-template-rows-sm); 45 | } 46 | } 47 | @media (--md) { 48 | .md\:rt-r-gtr { 49 | grid-template-rows: var(--grid-template-rows-md); 50 | } 51 | } 52 | @media (--lg) { 53 | .lg\:rt-r-gtr { 54 | grid-template-rows: var(--grid-template-rows-lg); 55 | } 56 | } 57 | @media (--xl) { 58 | .xl\:rt-r-gtr { 59 | grid-template-rows: var(--grid-template-rows-xl); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/hover-card.css: -------------------------------------------------------------------------------- 1 | .rt-HoverCardContent { 2 | background-color: var(--color-panel-solid); 3 | box-shadow: var(--shadow-4); 4 | overflow: auto; 5 | position: relative; 6 | 7 | --inset-padding-top: var(--hover-card-content-padding); 8 | --inset-padding-right: var(--hover-card-content-padding); 9 | --inset-padding-bottom: var(--hover-card-content-padding); 10 | --inset-padding-left: var(--hover-card-content-padding); 11 | padding: var(--hover-card-content-padding); 12 | box-sizing: border-box; 13 | 14 | transform-origin: var(--radix-hover-card-content-transform-origin); 15 | } 16 | 17 | /*************************************************************************************************** 18 | * * 19 | * SIZES * 20 | * * 21 | ***************************************************************************************************/ 22 | 23 | @breakpoints { 24 | .rt-HoverCardContent { 25 | &:where(.rt-r-size-1) { 26 | --hover-card-content-padding: var(--space-3); 27 | border-radius: var(--radius-4); 28 | } 29 | &:where(.rt-r-size-2) { 30 | --hover-card-content-padding: var(--space-4); 31 | border-radius: var(--radius-4); 32 | } 33 | &:where(.rt-r-size-3) { 34 | --hover-card-content-padding: var(--space-5); 35 | border-radius: var(--radius-5); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/styles/utilities/grid-template-columns.css: -------------------------------------------------------------------------------- 1 | @breakpoints { 2 | .rt-r-gtc { 3 | /* Keep this selector here to maintain the source order */ 4 | } 5 | .rt-r-gtc-1 { 6 | grid-template-columns: minmax(0, 1fr); 7 | } 8 | .rt-r-gtc-2 { 9 | grid-template-columns: repeat(2, minmax(0, 1fr)); 10 | } 11 | .rt-r-gtc-3 { 12 | grid-template-columns: repeat(3, minmax(0, 1fr)); 13 | } 14 | .rt-r-gtc-4 { 15 | grid-template-columns: repeat(4, minmax(0, 1fr)); 16 | } 17 | .rt-r-gtc-5 { 18 | grid-template-columns: repeat(5, minmax(0, 1fr)); 19 | } 20 | .rt-r-gtc-6 { 21 | grid-template-columns: repeat(6, minmax(0, 1fr)); 22 | } 23 | .rt-r-gtc-7 { 24 | grid-template-columns: repeat(7, minmax(0, 1fr)); 25 | } 26 | .rt-r-gtc-8 { 27 | grid-template-columns: repeat(8, minmax(0, 1fr)); 28 | } 29 | .rt-r-gtc-9 { 30 | grid-template-columns: repeat(9, minmax(0, 1fr)); 31 | } 32 | } 33 | 34 | .rt-r-gtc { 35 | grid-template-columns: var(--grid-template-columns); 36 | } 37 | @media (--xs) { 38 | .xs\:rt-r-gtc { 39 | grid-template-columns: var(--grid-template-columns-xs); 40 | } 41 | } 42 | @media (--sm) { 43 | .sm\:rt-r-gtc { 44 | grid-template-columns: var(--grid-template-columns-sm); 45 | } 46 | } 47 | @media (--md) { 48 | .md\:rt-r-gtc { 49 | grid-template-columns: var(--grid-template-columns-md); 50 | } 51 | } 52 | @media (--lg) { 53 | .lg\:rt-r-gtc { 54 | grid-template-columns: var(--grid-template-columns-lg); 55 | } 56 | } 57 | @media (--xl) { 58 | .xl\:rt-r-gtc { 59 | grid-template-columns: var(--grid-template-columns-xl); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/data-list.props.tsx: -------------------------------------------------------------------------------- 1 | import { colorPropDef } from '../props/color.prop.js'; 2 | import { highContrastPropDef } from '../props/high-contrast.prop.js'; 3 | import { leadingTrimPropDef } from '../props/leading-trim.prop.js'; 4 | import { widthPropDefs } from '../props/width.props.js'; 5 | 6 | import type { PropDef } from '../props/prop-def.js'; 7 | 8 | const alignValues = ['start', 'center', 'end', 'baseline', 'stretch'] as const; 9 | const orientationValues = ['horizontal', 'vertical'] as const; 10 | const sizes = ['1', '2', '3'] as const; 11 | 12 | const dataListRootPropDefs = { 13 | orientation: { 14 | type: 'enum', 15 | className: 'rt-r-orientation', 16 | values: orientationValues, 17 | default: 'horizontal', 18 | responsive: true, 19 | }, 20 | size: { 21 | type: 'enum', 22 | className: 'rt-r-size', 23 | values: sizes, 24 | default: '2', 25 | responsive: true, 26 | }, 27 | trim: { 28 | ...leadingTrimPropDef.trim, 29 | className: 'rt-r-trim', // Custom trim styles due to grid layout 30 | }, 31 | } satisfies { 32 | orientation: PropDef<(typeof orientationValues)[number]>; 33 | size: PropDef<(typeof sizes)[number]>; 34 | trim: typeof leadingTrimPropDef.trim; 35 | }; 36 | 37 | const dataListItemPropDefs = { 38 | align: { 39 | type: 'enum', 40 | className: 'rt-r-ai', 41 | values: alignValues, 42 | responsive: true, 43 | }, 44 | } satisfies { 45 | align: PropDef<(typeof alignValues)[number]>; 46 | }; 47 | 48 | const dataListLabelPropDefs = { 49 | ...widthPropDefs, 50 | ...colorPropDef, 51 | ...highContrastPropDef, 52 | }; 53 | 54 | export { dataListRootPropDefs, dataListItemPropDefs, dataListLabelPropDefs }; 55 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/switch.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Switch as SwitchPrimitive } from 'radix-ui'; 4 | 5 | import { extractProps } from '../helpers/extract-props.js'; 6 | import { marginPropDefs } from '../props/margin.props.js'; 7 | import { switchPropDefs } from './switch.props.js'; 8 | 9 | import type { MarginProps } from '../props/margin.props.js'; 10 | import type { GetPropDefTypes } from '../props/prop-def.js'; 11 | import type { ComponentPropsWithout } from '../helpers/component-props.js'; 12 | 13 | type SwitchElement = React.ElementRef; 14 | type SwitchOwnProps = GetPropDefTypes; 15 | interface SwitchProps 16 | extends ComponentPropsWithout< 17 | typeof SwitchPrimitive.Root, 18 | 'asChild' | 'color' | 'defaultValue' | 'children' 19 | >, 20 | MarginProps, 21 | SwitchOwnProps {} 22 | const Switch = React.forwardRef((props, forwardedRef) => { 23 | const { className, color, radius, ...switchProps } = extractProps( 24 | props, 25 | switchPropDefs, 26 | marginPropDefs 27 | ); 28 | return ( 29 | 37 | 40 | 41 | ); 42 | }); 43 | Switch.displayName = 'Switch'; 44 | 45 | export { Switch }; 46 | export type { SwitchProps }; 47 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/skeleton.css: -------------------------------------------------------------------------------- 1 | .rt-Skeleton { 2 | --skeleton-radius: var(--skeleton-radius-override); 3 | --skeleton-height: var(--skeleton-height-override); 4 | border-radius: var(--radius-1); 5 | animation: rt-skeleton-pulse 1000ms infinite alternate-reverse !important; 6 | background-image: none !important; 7 | background-clip: border-box !important; 8 | border: none !important; 9 | box-shadow: none !important; 10 | box-decoration-break: clone !important; 11 | color: transparent !important; 12 | outline: none !important; 13 | pointer-events: none !important; 14 | user-select: none !important; 15 | cursor: default !important; 16 | } 17 | 18 | /* 19 | * Take font differences out of equation for inline Skeletons that just wrap text. 20 | * This makes the dimensions consistent between the following non-Skeleton and Skeleton text: 21 | * ``` 22 | * Example text 23 | * 24 | * 25 | * Example text 26 | * 27 | * ``` 28 | * 29 | * Will NOT collapse Skeletons as the browsers use line-height on inline elements just for alignment. 30 | */ 31 | .rt-Skeleton:where([data-inline-skeleton]) { 32 | line-height: 0; 33 | /* Font metrics on Arial yield much nicer height for the text background bounding box */ 34 | font-family: Arial, sans-serif !important; 35 | } 36 | 37 | :where(.rt-Skeleton:empty) { 38 | display: block; 39 | height: var(--space-3); 40 | } 41 | 42 | .rt-Skeleton > *, 43 | .rt-Skeleton::after, 44 | .rt-Skeleton::before { 45 | visibility: hidden !important; 46 | } 47 | 48 | @keyframes rt-skeleton-pulse { 49 | from { 50 | background-color: var(--gray-a3); 51 | } 52 | to { 53 | background-color: var(--gray-a4); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /apps/playground/app/sink/tab-nav-demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as React from 'react'; 4 | import NextLink from 'next/link'; 5 | import { useSearchParams } from 'next/navigation'; 6 | import { TabNav } from '@radix-ui/themes'; 7 | 8 | const TabNavDemo = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >((props, forwardedRef) => { 12 | const params = useSearchParams(); 13 | const tab = params?.get('tab'); 14 | return ( 15 | 16 | 17 | 18 | Account 19 | 20 | 21 | 22 | 23 | Documents 24 | 25 | 26 | 27 | 28 | Settings 29 | 30 | 31 | 32 | {/* without asChild */} 33 | {/* 34 | Account 35 | 36 | 37 | Documents 38 | 39 | 40 | Settings 41 | */} 42 | 43 | ); 44 | }); 45 | TabNavDemo.displayName = 'TabNavDemo'; 46 | 47 | export { TabNavDemo }; 48 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { Slot } from 'radix-ui'; 4 | 5 | import { inert } from '../helpers/inert.js'; 6 | import { extractProps } from '../helpers/extract-props.js'; 7 | import { marginPropDefs } from '../props/margin.props.js'; 8 | import { skeletonPropDefs } from './skeleton.props.js'; 9 | 10 | import type { MarginProps } from '../props/margin.props.js'; 11 | import type { GetPropDefTypes } from '../props/prop-def.js'; 12 | import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'; 13 | 14 | type SkeletonElement = React.ElementRef<'span'>; 15 | type SkeletonOwnProps = GetPropDefTypes; 16 | interface SkeletonProps 17 | extends ComponentPropsWithout<'span', RemovedProps>, 18 | MarginProps, 19 | SkeletonOwnProps {} 20 | const Skeleton = React.forwardRef((props, forwardedRef) => { 21 | const { children, className, loading, ...skeletonProps } = extractProps( 22 | props, 23 | skeletonPropDefs, 24 | marginPropDefs 25 | ); 26 | 27 | if (!loading) return children; 28 | 29 | const Tag = React.isValidElement(children) ? Slot.Root : 'span'; 30 | 31 | return ( 32 | 42 | {children} 43 | 44 | ); 45 | }); 46 | Skeleton.displayName = 'Skeleton'; 47 | 48 | export { Skeleton }; 49 | export type { SkeletonProps }; 50 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/width.props.ts: -------------------------------------------------------------------------------- 1 | import type { GetPropDefTypes, PropDef } from './prop-def.js'; 2 | 3 | const widthPropDefs = { 4 | /** 5 | * Sets the CSS **width** property. 6 | * Supports CSS strings and responsive objects. 7 | * 8 | * @example 9 | * width="100px" 10 | * width={{ md: '100vw', xl: '1400px' }} 11 | * 12 | * @link 13 | * https://developer.mozilla.org/en-US/docs/Web/CSS/width 14 | */ 15 | width: { 16 | type: 'string', 17 | className: 'rt-r-w', 18 | customProperties: ['--width'], 19 | responsive: true, 20 | }, 21 | /** 22 | * Sets the CSS **min-width** property. 23 | * Supports CSS strings and responsive objects. 24 | * 25 | * @example 26 | * minWidth="100px" 27 | * minWidth={{ md: '100vw', xl: '1400px' }} 28 | * 29 | * @link 30 | * https://developer.mozilla.org/en-US/docs/Web/CSS/min-width 31 | */ 32 | minWidth: { 33 | type: 'string', 34 | className: 'rt-r-min-w', 35 | customProperties: ['--min-width'], 36 | responsive: true, 37 | }, 38 | /** 39 | * Sets the CSS **max-width** property. 40 | * Supports CSS strings and responsive objects. 41 | * 42 | * @example 43 | * maxWidth="100px" 44 | * maxWidth={{ md: '100vw', xl: '1400px' }} 45 | * 46 | * @link 47 | * https://developer.mozilla.org/en-US/docs/Web/CSS/max-width 48 | */ 49 | maxWidth: { 50 | type: 'string', 51 | className: 'rt-r-max-w', 52 | customProperties: ['--max-width'], 53 | responsive: true, 54 | }, 55 | } satisfies { 56 | width: PropDef; 57 | minWidth: PropDef; 58 | maxWidth: PropDef; 59 | }; 60 | 61 | type WidthProps = GetPropDefTypes; 62 | 63 | export { widthPropDefs }; 64 | export type { WidthProps }; 65 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/props/height.props.ts: -------------------------------------------------------------------------------- 1 | import type { PropDef, GetPropDefTypes } from './prop-def.js'; 2 | 3 | const heightPropDefs = { 4 | /** 5 | * Sets the CSS **height** property. 6 | * Supports CSS strings and responsive objects. 7 | * 8 | * @example 9 | * height="100px" 10 | * height={{ md: '100vh', xl: '600px' }} 11 | * 12 | * @link 13 | * https://developer.mozilla.org/en-US/docs/Web/CSS/height 14 | */ 15 | height: { 16 | type: 'string', 17 | className: 'rt-r-h', 18 | customProperties: ['--height'], 19 | responsive: true, 20 | }, 21 | /** 22 | * Sets the CSS **min-height** property. 23 | * Supports CSS strings and responsive objects. 24 | * 25 | * @example 26 | * minHeight="100px" 27 | * minHeight={{ md: '100vh', xl: '600px' }} 28 | * 29 | * @link 30 | * https://developer.mozilla.org/en-US/docs/Web/CSS/min-height 31 | */ 32 | minHeight: { 33 | type: 'string', 34 | className: 'rt-r-min-h', 35 | customProperties: ['--min-height'], 36 | responsive: true, 37 | }, 38 | /** 39 | * Sets the CSS **max-height** property. 40 | * Supports CSS strings and responsive objects. 41 | * 42 | * @example 43 | * maxHeight="100px" 44 | * maxHeight={{ md: '100vh', xl: '600px' }} 45 | * 46 | * @link 47 | * https://developer.mozilla.org/en-US/docs/Web/CSS/max-height 48 | */ 49 | maxHeight: { 50 | type: 'string', 51 | className: 'rt-r-max-h', 52 | customProperties: ['--max-height'], 53 | responsive: true, 54 | }, 55 | } satisfies { 56 | height: PropDef; 57 | minHeight: PropDef; 58 | maxHeight: PropDef; 59 | }; 60 | 61 | type HeightProps = GetPropDefTypes; 62 | 63 | export { heightPropDefs }; 64 | export type { HeightProps }; 65 | -------------------------------------------------------------------------------- /packages/radix-ui-themes/src/components/popover.css: -------------------------------------------------------------------------------- 1 | .rt-PopoverContent { 2 | background-color: var(--color-panel-solid); 3 | box-shadow: var(--shadow-5); 4 | min-width: var(--radix-popover-trigger-width); 5 | outline: 0; 6 | overflow: auto; 7 | position: relative; 8 | 9 | --inset-padding-top: var(--popover-content-padding); 10 | --inset-padding-right: var(--popover-content-padding); 11 | --inset-padding-bottom: var(--popover-content-padding); 12 | --inset-padding-left: var(--popover-content-padding); 13 | padding: var(--popover-content-padding); 14 | box-sizing: border-box; 15 | 16 | transform-origin: var(--radix-popover-content-transform-origin); 17 | } 18 | 19 | /*************************************************************************************************** 20 | * * 21 | * SIZES * 22 | * * 23 | ***************************************************************************************************/ 24 | 25 | @breakpoints { 26 | .rt-PopoverContent { 27 | &:where(.rt-r-size-1) { 28 | --popover-content-padding: var(--space-3); 29 | border-radius: var(--radius-4); 30 | } 31 | &:where(.rt-r-size-2) { 32 | --popover-content-padding: var(--space-4); 33 | border-radius: var(--radius-4); 34 | } 35 | &:where(.rt-r-size-3) { 36 | --popover-content-padding: var(--space-5); 37 | border-radius: var(--radius-5); 38 | } 39 | &:where(.rt-r-size-4) { 40 | --popover-content-padding: var(--space-6); 41 | border-radius: var(--radius-5); 42 | } 43 | } 44 | } 45 | --------------------------------------------------------------------------------
{children}