@platned/ui 0.1.4 → 0.5.1

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.
package/dist/sidebar.d.ts CHANGED
@@ -1,13 +1,131 @@
1
1
  import * as react from 'react';
2
+ import { ReactNode, HTMLAttributes } from 'react';
2
3
 
4
+ type NavItemSize = 'sm' | 'md';
5
+ type NavItemVariant = 'card' | 'plain';
6
+
7
+ interface NavTabItem {
8
+ to: string;
9
+ label: string;
10
+ /** Match this route exactly — needed for an index route like `/account`. */
11
+ end?: boolean;
12
+ }
13
+ interface NavTabsProps {
14
+ items: NavTabItem[];
15
+ className?: string;
16
+ }
17
+ /** Route-driven tab strip, backed by react-router's `NavLink`.
18
+ *
19
+ * Use this when each tab is its own route. For state-driven tabs that do not change
20
+ * the URL, use `Tabs` from the main entry point instead — it has no router dependency.
21
+ *
22
+ * The active underline and label use `brand-emphasis` (#0C2D58), the brand fill colour
23
+ * Figma specifies for a tab rule, rather than the lighter `brand` border token. */
24
+ declare function NavTabs({ items, className }: NavTabsProps): react.JSX.Element;
25
+
26
+ interface SidebarNavItem {
27
+ to: string;
28
+ label: string;
29
+ /** Optional — a collapsed row without one falls back to a monogram of its label. */
30
+ icon?: ReactNode;
31
+ /** Red dot on the row — something new behind this destination. */
32
+ indicator?: boolean;
33
+ /** Match the path exactly rather than as a prefix. Needed for an index route. */
34
+ end?: boolean;
35
+ }
36
+ interface SidebarNavGroup {
37
+ /**
38
+ * Uppercase heading above the group. Omit for an ungrouped run of rows.
39
+ *
40
+ * Kept in the accessibility tree when the rail is collapsed rather than dropped: it is the
41
+ * only thing saying what the run of icons below it has in common.
42
+ */
43
+ title?: string;
44
+ items: SidebarNavItem[];
45
+ }
3
46
  interface AppSidebarProps {
4
- collapsed: boolean;
5
- onToggle: () => void;
6
- isAdmin?: boolean;
7
- userName: string;
8
- userRole: string;
47
+ /** The scrolling nav. One untitled group is a flat list. */
48
+ groups: SidebarNavGroup[];
49
+ /** Rows pinned below the scrolling nav — settings, help, a sign-out link. */
50
+ footerNav?: SidebarNavItem[];
51
+ /**
52
+ * Brand lockup. Given a function it receives `collapsed`, so the caller can swap a full
53
+ * lockup for a mark alone rather than having one squeezed into an 80px rail.
54
+ */
55
+ brand?: ReactNode | ((state: {
56
+ collapsed: boolean;
57
+ }) => ReactNode);
58
+ /** Bottom slot, below a divider — a user card, a version pill, nothing. */
59
+ footer?: ReactNode;
60
+ /**
61
+ * Whether the rail can collapse at all.
62
+ *
63
+ * `false` locks it open: no toggle button, and `collapsed` is ignored rather than half
64
+ * honoured. A collapsed rail is 80px of icons, so it only earns its place in a nav short
65
+ * enough and iconographic enough to survive the loss of its labels — a long text nav
66
+ * (the docs site's own, for one) is better off never offering it.
67
+ */
68
+ collapsible?: boolean;
69
+ collapsed?: boolean;
70
+ /** Omit and the collapse toggle is not rendered, though `collapsed` still applies. */
71
+ onToggle?: () => void;
72
+ size?: NavItemSize;
73
+ variant?: NavItemVariant;
74
+ /** Expanded width, as a Tailwind class. */
75
+ width?: string;
76
+ collapsedWidth?: string;
77
+ className?: string;
78
+ }
79
+ /**
80
+ * The application nav rail: brand, a grouped list of destinations, and a footer.
81
+ *
82
+ * Lives on its own entry point (`@platned/ui/sidebar`) because it uses `NavLink`, and
83
+ * `react-router-dom` is an optional peer dependency.
84
+ *
85
+ * Through 0.4.0 this was not a library component at all. It hardcoded ten product routes,
86
+ * their labels and their icons, an `SCIC` wordmark, and an `isAdmin` flag gating two of the
87
+ * rows — so the only app it could render was the one it was extracted from, and the docs
88
+ * site kept a second, unrelated sidebar of its own rather than use it. Everything
89
+ * app-specific is now a prop or a slot, and the docs site runs on this component.
90
+ *
91
+ * Width is an explicit prop rather than something `className` overrides: the width is
92
+ * conditional on `collapsed`, so a `className="w-64"` would tailwind-merge away the
93
+ * collapsed width too and break the collapse. Everything else about the shell is fair game
94
+ * for `className` — `rounded-none` to flatten it for a full-bleed layout, for instance.
95
+ */
96
+ declare function AppSidebar({ groups, footerNav, brand, footer, collapsible, collapsed: collapsedProp, onToggle, size, variant, width, collapsedWidth, className, }: AppSidebarProps): react.JSX.Element;
97
+ type SidebarSeparatorProps = HTMLAttributes<HTMLDivElement>;
98
+ /**
99
+ * The rule between nav groups. `AppSidebar` draws one above every group after the first;
100
+ * this is exported so the same line can be used in the `footer` slot or in a hand-composed
101
+ * rail without anyone re-deriving `h-px bg-divider` and inevitably picking a different inset.
102
+ *
103
+ * Decorative by default. The grouping it marks is already carried semantically by each
104
+ * group's heading — which stays in the accessibility tree even when the rail is collapsed and
105
+ * the heading is visually hidden — so announcing the rule as well is redundant. Pass
106
+ * `role="separator"` through if you are using it somewhere that has no heading to lean on.
107
+ */
108
+ declare function SidebarSeparator({ className, ...rest }: SidebarSeparatorProps): react.JSX.Element;
109
+ interface SidebarUserCardProps {
110
+ name: string;
111
+ role: string;
9
112
  onLogout: () => void;
113
+ collapsed?: boolean;
114
+ /** Extra menu entries above Sign out. */
115
+ menu?: ReactNode;
116
+ className?: string;
10
117
  }
11
- declare function AppSidebar({ collapsed, onToggle, isAdmin, userName, userRole, onLogout }: AppSidebarProps): react.JSX.Element;
118
+ /**
119
+ * The signed-in user block, for `AppSidebar`'s `footer` slot.
120
+ *
121
+ * Was private, and its props were on `AppSidebar` itself — which meant every consumer of the
122
+ * sidebar had to have a user, a role and a logout handler whether it had a concept of any
123
+ * of them or not. The docs site has none, and passes no footer.
124
+ *
125
+ * Its menu is `DropdownMenu` rather than the hand-rolled click-outside popover it was: that
126
+ * one had no keyboard contract and, being absolutely positioned, was clipped by the
127
+ * collapsed rail. `DropdownMenu` portals.
128
+ */
129
+ declare function SidebarUserCard({ name, role, onLogout, collapsed, menu, className, }: SidebarUserCardProps): react.JSX.Element;
12
130
 
13
- export { AppSidebar };
131
+ export { AppSidebar, type AppSidebarProps, type NavTabItem, NavTabs, type NavTabsProps, type SidebarNavGroup, type SidebarNavItem, SidebarSeparator, type SidebarSeparatorProps, SidebarUserCard, type SidebarUserCardProps };