@remit/ui 0.0.162 → 0.0.163

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/ui",
3
- "version": "0.0.162",
3
+ "version": "0.0.163",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src"
@@ -1,8 +1,9 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
2
  import { AtSign, Inbox, Server } from "lucide-react";
3
3
  import { useState } from "react";
4
+ import { Button } from "./button.js";
4
5
  import type { ServerSecurity } from "./security-select.js";
5
- import { ConnectorTile, ServerFields } from "./wizard.js";
6
+ import { ConnectorTile, ServerFields, WizardShell } from "./wizard.js";
6
7
 
7
8
  const meta: Meta = {
8
9
  title: "Components/Wizard",
@@ -101,3 +102,53 @@ export const ServerFieldsPhone: Story = {
101
102
  globals: { viewport: { value: "mobile" } },
102
103
  render: () => <ServerFieldsDemo />,
103
104
  };
105
+
106
+ const longStepRows = Array.from(
107
+ { length: 60 },
108
+ (_, index) => `Row ${index + 1} of a report nobody sized the box for`,
109
+ );
110
+
111
+ function LongStep() {
112
+ return (
113
+ <WizardShell
114
+ steps={["File", "Review", "Credentials", "Folders"]}
115
+ activeStep={1}
116
+ title="What this file will change"
117
+ subtitle="A step whose content runs well past the bottom of the screen."
118
+ footer={
119
+ <>
120
+ <Button variant="ghost">Back</Button>
121
+ <Button variant="primary">Continue</Button>
122
+ </>
123
+ }
124
+ >
125
+ <ul className="divide-y divide-line">
126
+ {longStepRows.map((row) => (
127
+ <li key={row} className="py-2 text-sm text-fg">
128
+ {row}
129
+ </li>
130
+ ))}
131
+ </ul>
132
+ </WizardShell>
133
+ );
134
+ }
135
+
136
+ /**
137
+ * A step taller than the viewport, on the 1512×827 laptop the config import
138
+ * wizard was found unusable on (#1021). The rows scroll inside the card; the
139
+ * title and the Continue button stay on screen.
140
+ */
141
+ export const ShellLongStepShortViewport: Story = {
142
+ name: "WizardShell — long step, short viewport",
143
+ parameters: { layout: "fullscreen" },
144
+ globals: { viewport: { value: "laptopShort" } },
145
+ render: () => <LongStep />,
146
+ };
147
+
148
+ /** The same step on a phone with the address bar and system nav showing. */
149
+ export const ShellLongStepPhoneShort: Story = {
150
+ name: "WizardShell — long step, short phone",
151
+ parameters: { layout: "fullscreen" },
152
+ globals: { viewport: { value: "mobileShort" } },
153
+ render: () => <LongStep />,
154
+ };
@@ -76,25 +76,40 @@ export function WizardShell({
76
76
  hideSteps,
77
77
  }: WizardShellProps) {
78
78
  return (
79
- // First-run is a focal moment: the wizard column is horizontally
80
- // centered with its top edge anchored ~30% down the viewport
81
- // (optical center) on larger screens. On phone the top padding is
82
- // minimal so taller steps (connector picker, servers) don't push the
83
- // CTA bar below the fold — the shell scrolls if content overflows.
84
- <div className="flex min-h-dvh w-full flex-col items-center overflow-y-auto bg-canvas pb-[max(2rem,env(safe-area-inset-bottom,0px))] pl-[max(2rem,env(safe-area-inset-left,0px))] pr-[max(2rem,env(safe-area-inset-right,0px))] pt-[max(2rem,env(safe-area-inset-top,0px))] font-sans text-fg sm:pt-[30vh]">
79
+ // The shell is exactly the viewport, never more: the step's own content
80
+ // is what scrolls, and the title and the footer actions are pinned
81
+ // either side of it. A dry-run report or a list of accounts can run to
82
+ // any length and the primary action stays where the reader can press it
83
+ // (#1021).
84
+ //
85
+ // First-run is still a focal moment, so on larger screens the column
86
+ // sits with its top edge about 30% down the viewport (optical centre).
87
+ // That offset is a flex spacer rather than top padding because padding
88
+ // cannot yield: the spacer collapses first and the card only gives up
89
+ // height once the offset is gone.
90
+ <div className="flex h-dvh w-full flex-col items-center overflow-hidden bg-canvas pb-[max(2rem,env(safe-area-inset-bottom,0px))] pl-[max(2rem,env(safe-area-inset-left,0px))] pr-[max(2rem,env(safe-area-inset-right,0px))] pt-[max(2rem,env(safe-area-inset-top,0px))] font-sans text-fg">
91
+ <div className="hidden shrink-[9999] basis-[30vh] sm:block" />
85
92
  {!hideSteps && (
86
- <div className="mb-5 w-full max-w-xl">
93
+ <div className="mb-5 w-full max-w-xl shrink-0">
87
94
  <StepRail steps={steps} activeStep={activeStep} />
88
95
  </div>
89
96
  )}
90
- <Card raised className="w-full max-w-xl">
91
- <div className="px-5 pt-5">
97
+ <Card raised className="flex w-full min-h-0 max-w-xl flex-col">
98
+ <div className="shrink-0 px-5 pt-5">
92
99
  <h1 className="text-xl font-semibold text-fg">{title}</h1>
93
100
  {subtitle && <p className="mt-1 text-sm text-fg-muted">{subtitle}</p>}
94
101
  </div>
95
- <div className="px-5 py-5">{children}</div>
102
+ <div
103
+ data-testid="wizard-body"
104
+ className="min-h-0 overflow-y-auto px-5 py-5"
105
+ >
106
+ {children}
107
+ </div>
96
108
  {footer && (
97
- <div className="flex items-center justify-between gap-3 border-t border-line px-5 py-3">
109
+ <div
110
+ data-testid="wizard-footer"
111
+ className="flex shrink-0 items-center justify-between gap-3 border-t border-line px-5 py-3"
112
+ >
98
113
  {footer}
99
114
  </div>
100
115
  )}