Add Grove, a component kit grown from the Animal Island design language - #10
Add Grove, a component kit grown from the Animal Island design language#10maceip wants to merge 1 commit into
Conversation
Grove takes the Animal Island design system (lifeodyssey/animal-island-ui- tailwind, MIT) as a foundation and rebuilds it as our own plain-CSS kit with thin React wrappers: no Tailwind, no Radix, nothing imported at runtime. Kept because they are the point: capsule shapes, the flat game-button press shadow (5px rest, 6px hover with a lift, 1px pressed with a drop), chunky sage borders, the yellow focus ring, organic title radii and the blob clip-path on a native <dialog>. Ours: the palette (paper, warm charcoal, leaf green, dry-sage shadow), status tags mapped to the workspace's activity states, speech bubbles for turns, a vine divider, toasts. - ui/src/grove: grove.css and Grove.tsx (Button, Input, Textarea, Switch, Checkbox, Tag, Ribbon, Speech, BlobDialog, Vine, GroveDefs) - The "Start a contribution" dialog now uses BlobDialog with Grove controls; the dialog fills the viewport with its own blur so the blob has no un-blurred rectangle behind it - docs/design/grove.html shows every component and the palette mapping; grove.md records what was kept, what is ours and where to apply it next
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 365917e195
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Create contribution <ArrowRight size={15} /> | ||
| </button> | ||
| </div> | ||
| <button type="submit" hidden /> |
There was a problem hiding this comment.
Disable the hidden submitter when inputs are blank
When either field contains only whitespace, the visible Create button is disabled, but pressing Enter still activates this enabled hidden submit button. Native required validation accepts whitespace, so onSubmit calls submit() and sends a request that the trimmed server schema rejects (src/workspace-commands.ts:25-26), presenting an error despite the UI indicating submission is unavailable. Apply the same disabled condition to this submitter or guard trimmed values in the submit handler.
Useful? React with 👍 / 👎.
| ] | ||
| .filter(Boolean) | ||
| .join(" "); | ||
| return <button type="button" {...rest} className={classes} />; |
There was a problem hiding this comment.
Disable loading buttons for keyboard activation
When loading is true without an explicit disabled prop, the CSS only suppresses pointer events; a focused button can still be activated with Enter or Space and invoke its handler again while the operation is pending. This can duplicate any action that adopts the kit's loading state, so the wrapper should make loading imply disabled (and preferably expose the busy state to assistive technology) rather than relying on pointer-events.
Useful? React with 👍 / 👎.
| border: 0; | ||
| padding: 24px; | ||
| display: grid; | ||
| place-items: center; |
There was a problem hiding this comment.
Keep oversized dialogs aligned to a reachable scroll origin
When the available viewport is shorter than the blob, such as mobile landscape or after an onscreen keyboard opens, centering the oversized shell puts its top above the scroll container's origin. Because the full-screen dialog inherits overflow: auto from ui/src/style.css:1729-1738, users can scroll toward the overflowing bottom but cannot reach content laid out at a negative top offset, potentially hiding the heading and first field; use safe/start alignment for overflow or constrain the shell and scroll its contents.
Useful? React with 👍 / 👎.
| .grove-btn-primary { | ||
| background: var(--grove-leaf); | ||
| border-color: var(--grove-leaf); | ||
| color: #fff; | ||
| text-shadow: 0 1px 0 rgba(0, 0, 0, 0.12); |
There was a problem hiding this comment.
Increase the primary button's text contrast
The enabled primary button renders 12px white text on #58aa72, which has only about a 2.83:1 contrast ratio; the #6dbb85 hover state drops to about 2.31:1. The newly surfaced Create contribution action is therefore below the 4.5:1 WCAG AA threshold for normal-sized text, making its label difficult to read for low-vision users; use a darker green or sufficiently contrasting text color in both states.
Useful? React with 👍 / 👎.
| .grove-input::placeholder, | ||
| .grove-textarea::placeholder { | ||
| color: var(--grove-ink-4); | ||
| font-weight: 400; |
There was a problem hiding this comment.
Raise the placeholder text contrast
Grove inputs render their 12px placeholder examples with #9aa59c on white, a contrast ratio of only about 2.55:1. Both fields in the new contribution dialog expose these placeholders, so low-vision users may be unable to read the examples even though this visible text is expected to meet the 4.5:1 normal-text threshold; use a darker placeholder token such as the already defined higher-contrast ink color.
Useful? React with 👍 / 👎.
What
Grove, AXP's component kit, grown from the Animal Island design language (lifeodyssey/animal-island-ui-tailwind, MIT) and rebuilt as our own plain-CSS kit with thin React wrappers — no Tailwind, no Radix, nothing imported at runtime.
Kept because they are the point: capsule shapes everywhere, the flat game-button press shadow (5px rest / 6px hover with a lift / 1px pressed with a drop), chunky sage borders, the yellow focus ring, organic title radii, the blob clip-path on a native
<dialog>. Ours: the palette (paper, warm charcoal, leaf green, dry-sage shadow), status tags mapped to the workspace's activity states, speech bubbles for turns, a vine divider, toasts.ui/src/grove/grove.css+Grove.tsx: Button, Input, Textarea, Switch, Checkbox, Tag, Ribbon, Speech, BlobDialog, Vine, GroveDefsBlobDialogwith Grove controls; the dialog fills the viewport with its own blur so the blob has no un-blurred rectangle behind itLook at
docs/design/grove.html— every component and the palette mapping; open locallydocs/design/grove.mdnpm run demo:ui→ New contributionVerification
npm run checkandnpm run test:uipass.Landing
Real overlap with the Liquid Leaf PR at the top of
App.tsx(both add a defs component and an import); otherwise adjacent-line conflicts only.