@crisp-ui-kit/crisp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -177,16 +177,7 @@
177
177
  & .recordstable-sum-btn[data-empty] { opacity: 0; justify-content: flex-start; }
178
178
  & .recordstable-sum-btn[data-empty]:hover { opacity: 1; }
179
179
 
180
- /* bulk action bar — Attio's white floating pill */
181
- & .recordstable-bulkbar { position: absolute; left: 50%; bottom: var(--space-4); transform: translateX(-50%); display: flex; align-items: center; gap: var(--space-0-5); height: 44px; padding: 0 var(--space-1) 0 var(--space-1-5); border-radius: 14px; background: var(--bg-surface); box-shadow: 0 0 0 1px rgba(28,40,64,0.04), 0 4px 8px -4px rgba(28,40,64,0.12), 0 4px 12px -2px rgba(24,41,75,0.16); color: var(--fg-primary); z-index: 10; opacity: 1; transition: opacity .16s ease, transform .16s ease; @starting-style { opacity: 0; transform: translateX(-50%) translateY(10px); } }
182
- & .recordstable-bulk-count { display: inline-flex; align-items: center; gap: var(--space-1); height: 32px; margin: 0; padding: 0 var(--space-2); border: none; border-radius: var(--radius-md); background: color-mix(in srgb, var(--fg-primary) 4%, transparent); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); color: var(--fg-muted); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
183
- & .recordstable-bulk-count:hover { background: color-mix(in srgb, var(--fg-primary) 8%, transparent); color: var(--fg-primary); }
184
- & .recordstable-bulk-count svg { flex-shrink: 0; }
185
- & .recordstable-bulk-btn { display: inline-flex; align-items: center; gap: var(--space-1); height: 32px; padding: 0 var(--space-2); border: none; border-radius: var(--radius-md); background: transparent; color: var(--fg-primary); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
186
- & .recordstable-bulk-btn:hover { background: var(--bg-raised); }
187
- & .recordstable-bulk-btn--danger { color: var(--bg-danger); }
188
- & .recordstable-bulk-btn--danger:hover { background: color-mix(in srgb, var(--bg-danger) 10%, transparent); }
189
- & .recordstable-bulk-btn svg { flex-shrink: 0; }
180
+ /* bulk action bar lives in its own component now — see components/bulkbar */
190
181
  & .recordstable-bulk-sep { width: 1px; height: 20px; margin: 0 var(--space-0-5); background: var(--border-subtle); }
191
182
  & .recordstable-bulk-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: none; border-radius: var(--radius-md); background: transparent; color: var(--fg-muted); cursor: pointer; }
192
183
  & .recordstable-bulk-close:hover { background: var(--bg-raised); color: var(--fg-primary); }
package/dist/styles.css CHANGED
@@ -679,6 +679,20 @@
679
679
 
680
680
  }
681
681
 
682
+ .bulkbar {
683
+ position: absolute; left: 0; right: 0; bottom: var(--space-4); display: flex; justify-content: center; pointer-events: none; z-index: 10;
684
+ & .bulkbar-bar { pointer-events: auto; display: flex; align-items: center; gap: var(--space-0-5); height: 44px; padding: 0 var(--space-1) 0 var(--space-1-5); border-radius: 14px; background: var(--bg-surface); box-shadow: 0 0 0 1px rgba(28,40,64,0.04), 0 4px 8px -4px rgba(28,40,64,0.12), 0 4px 12px -2px rgba(24,41,75,0.16); color: var(--fg-primary); transition: opacity .16s ease, transform .16s ease; }
685
+ & .bulkbar-bar { @starting-style { opacity: 0; transform: translateY(10px); } }
686
+ & .bulkbar-count { display: inline-flex; align-items: center; gap: var(--space-1); height: 32px; margin: 0; padding: 0 var(--space-2); border: none; border-radius: var(--radius-md); background: color-mix(in srgb, var(--fg-primary) 4%, transparent); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); color: var(--fg-muted); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
687
+ & .bulkbar-count:hover { background: color-mix(in srgb, var(--fg-primary) 8%, transparent); color: var(--fg-primary); }
688
+ & .bulkbar-count svg { flex-shrink: 0; }
689
+ & .bulkbar-btn { display: inline-flex; align-items: center; gap: var(--space-1); height: 32px; padding: 0 var(--space-2); border: none; border-radius: var(--radius-md); background: transparent; color: var(--fg-primary); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
690
+ & .bulkbar-btn:hover { background: var(--bg-raised); }
691
+ & .bulkbar-btn--danger { color: var(--bg-danger); }
692
+ & .bulkbar-btn--danger:hover { background: color-mix(in srgb, var(--bg-danger) 10%, transparent); }
693
+ & .bulkbar-btn svg { flex-shrink: 0; }
694
+ }
695
+
682
696
  .badge {
683
697
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1); font-family: var(--font-sans); font-weight: var(--weight-medium); letter-spacing: -0.1px; white-space: nowrap;
684
698
  & .badge-dot { width: 6px; height: 6px; flex-shrink: 0; border-radius: var(--radius-full); background: currentColor; }
@@ -1249,16 +1263,7 @@
1249
1263
  & .recordstable-sum-btn[data-empty] { opacity: 0; justify-content: flex-start; }
1250
1264
  & .recordstable-sum-btn[data-empty]:hover { opacity: 1; }
1251
1265
 
1252
- /* bulk action bar — Attio's white floating pill */
1253
- & .recordstable-bulkbar { position: absolute; left: 50%; bottom: var(--space-4); transform: translateX(-50%); display: flex; align-items: center; gap: var(--space-0-5); height: 44px; padding: 0 var(--space-1) 0 var(--space-1-5); border-radius: 14px; background: var(--bg-surface); box-shadow: 0 0 0 1px rgba(28,40,64,0.04), 0 4px 8px -4px rgba(28,40,64,0.12), 0 4px 12px -2px rgba(24,41,75,0.16); color: var(--fg-primary); z-index: 10; opacity: 1; transition: opacity .16s ease, transform .16s ease; @starting-style { opacity: 0; transform: translateX(-50%) translateY(10px); } }
1254
- & .recordstable-bulk-count { display: inline-flex; align-items: center; gap: var(--space-1); height: 32px; margin: 0; padding: 0 var(--space-2); border: none; border-radius: var(--radius-md); background: color-mix(in srgb, var(--fg-primary) 4%, transparent); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); color: var(--fg-muted); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
1255
- & .recordstable-bulk-count:hover { background: color-mix(in srgb, var(--fg-primary) 8%, transparent); color: var(--fg-primary); }
1256
- & .recordstable-bulk-count svg { flex-shrink: 0; }
1257
- & .recordstable-bulk-btn { display: inline-flex; align-items: center; gap: var(--space-1); height: 32px; padding: 0 var(--space-2); border: none; border-radius: var(--radius-md); background: transparent; color: var(--fg-primary); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
1258
- & .recordstable-bulk-btn:hover { background: var(--bg-raised); }
1259
- & .recordstable-bulk-btn--danger { color: var(--bg-danger); }
1260
- & .recordstable-bulk-btn--danger:hover { background: color-mix(in srgb, var(--bg-danger) 10%, transparent); }
1261
- & .recordstable-bulk-btn svg { flex-shrink: 0; }
1266
+ /* bulk action bar lives in its own component now — see components/bulkbar */
1262
1267
  & .recordstable-bulk-sep { width: 1px; height: 20px; margin: 0 var(--space-0-5); background: var(--border-subtle); }
1263
1268
  & .recordstable-bulk-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: none; border-radius: var(--radius-md); background: transparent; color: var(--fg-muted); cursor: pointer; }
1264
1269
  & .recordstable-bulk-close:hover { background: var(--bg-raised); color: var(--fg-primary); }
@@ -0,0 +1,32 @@
1
+ import * as React from "react";
2
+ export type BulkBarProps = {
3
+ /** Selected count — renders the leading "N selected" pill when provided. */
4
+ count?: number;
5
+ /** Called when the count pill (its ✕) is pressed — clear the selection. */
6
+ onClear?: () => void;
7
+ /** Word after the count in the pill (default "selected"). */
8
+ countLabel?: string;
9
+ /** Action buttons — usually `<BulkBarButton>`s and a `<Menu>` overflow. */
10
+ children?: React.ReactNode;
11
+ className?: string;
12
+ };
13
+ /**
14
+ * A floating bulk-action bar. Rises from the bottom-centre of its nearest
15
+ * positioned ancestor when a selection is active; render it conditionally
16
+ * (e.g. `count > 0 && <BulkBar …/>`). Measured from Attio's records table.
17
+ */
18
+ export declare function BulkBar({ count, onClear, countLabel, children, className, }: BulkBarProps): React.JSX.Element;
19
+ export declare namespace BulkBar {
20
+ var displayName: string;
21
+ }
22
+ export type BulkBarButtonProps = React.ComponentPropsWithoutRef<"button"> & {
23
+ icon?: React.ReactNode;
24
+ /** Danger styling (e.g. a destructive "Delete"). */
25
+ danger?: boolean;
26
+ };
27
+ /** A styled action button for use inside a `<BulkBar>` (or as a `<Menu>` trigger). */
28
+ export declare const BulkBarButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
29
+ icon?: React.ReactNode;
30
+ /** Danger styling (e.g. a destructive "Delete"). */
31
+ danger?: boolean;
32
+ } & React.RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,3 @@
1
+ declare const config: import("../..").RecipeConfig<{}>;
2
+ export declare const bulkbarRecipe: import("../..").RecipeFn<{}>;
3
+ export default config;
@@ -0,0 +1,2 @@
1
+ export { BulkBar, BulkBarButton, type BulkBarButtonProps, type BulkBarProps, } from "./bulkbar";
2
+ export { bulkbarRecipe } from "./bulkbar.recipe";
@@ -4,6 +4,7 @@ export * from "./components/avatargroup";
4
4
  export * from "./components/badge";
5
5
  export * from "./components/barchart";
6
6
  export * from "./components/breadcrumb";
7
+ export * from "./components/bulkbar";
7
8
  export * from "./components/button";
8
9
  export * from "./components/callout";
9
10
  export * from "./components/card";
@@ -42,6 +42,8 @@ export type RecordsTableProps = {
42
42
  onSelectionChange?: (ids: string[]) => void;
43
43
  /** Show the toolbar's "New" button (hide it when the page provides its own). */
44
44
  showNew?: boolean;
45
+ /** Allow adding columns via the trailing "+" header button (default true). */
46
+ allowAddColumn?: boolean;
45
47
  /** Called when a row's open (↗) button is pressed — opens a record panel. */
46
48
  onOpenRecord?: (row: Row) => void;
47
49
  /** Called when a row's entity name is clicked — navigate to its full record page. */
@@ -57,7 +59,7 @@ export declare function tagTone(t: string): string;
57
59
  * and a floating bulk-action bar (delete / deselect) when rows are selected.
58
60
  * Selection can be controlled via `selectedIds`/`onSelectionChange`.
59
61
  */
60
- export declare function RecordsTable({ columns: columnsProp, rows: rowsProp, selectedIds, onSelectionChange, showNew, onOpenRecord, onOpenRecordPage, className, }: RecordsTableProps): React.JSX.Element;
62
+ export declare function RecordsTable({ columns: columnsProp, rows: rowsProp, selectedIds, onSelectionChange, showNew, allowAddColumn, onOpenRecord, onOpenRecordPage, className, }: RecordsTableProps): React.JSX.Element;
61
63
  export declare const defaultColumns: Column[];
62
64
  export declare const defaultRows: Row[];
63
65
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crisp-ui-kit/crisp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A lean React design system, measured pixel-for-pixel from Attio.",
5
5
  "license": "MIT",
6
6
  "type": "module",