Add initial component set#56
Conversation
b735500 to
51d80d8
Compare
Vendor eleven shadcn/Base UI primitives into @surfnet/react — avatar, breadcrumb, checkbox, dropdown-menu, field, input, label, select, separator, sidebar, table — each with a barrel, an index export, and a Storybook story. Add a DataTable component built on the table primitive + TanStack Table (row selection, sorting, filtering, column visibility, pagination); all of its user-facing strings are props with defaults. Add a contract per component in @surfnet/contracts (description-only where there is no axis) and tie each component to it via satisfies / typed props. Update the add-component skill to require a contract for every component and document the variant/size, orientation, and description-only shapes.
…cons Follow PR #44: replace all @tabler/icons-react usages in the new components and their stories with @phosphor-icons/react (`*Icon` suffix). The icon library config and peer/dev deps already came in via the rebase onto main.
The separator story declared an `orientation` control but every story hardcoded its render, so the control did nothing. Add an args-driven Default playground that consumes `orientation` (and adapts its layout) so the control works; keep the Horizontal/Vertical showcases. Audited the rest: Storybook here only surfaces explicitly declared argTypes (no prop inference), and separator was the only component with a declared-but- unconsumed control. Document the rule in the add-component skill so new stories always wire their controls to an args-driven story.
2692ebb to
0bc3dfa
Compare
…useDataTable hook
…hat look mostly like the React ones. Only the data-table lacks for now since that is not a standard spartan-ng component.
sjoerdbeentjes
left a comment
There was a problem hiding this comment.
@loofpc Angular deel ziet er netjes uit! Paar dingen die we nog kunnen fixen:
- Contracts worden niet afgedwongen
- Icons zijn Lucide ipv Phosphor
| `, | ||
| }) | ||
| export class HlmAvatar extends BrnAvatar { | ||
| public readonly size = input<'default' | 'sm' | 'lg'>('default'); |
There was a problem hiding this comment.
Deze as is hardcoded in plaats van gekoppeld aan @surfnet/contracts, waardoor de cross-framework parity aan de Angular-kant niet echt wordt afgedwongen. De story gebruikt avatarContract, maar deze type niet. Dit kan in de toekomst bij wijziging in avatarContract.sizes de React-build laten falen en hier niet.
We kunnen het laten voor nu en het Button component als voorbeeld nemen voor de contracts, maar denk dat het wel mooi is om het voor alle components te doen (misschien mooi werk voor een AI agent)
There was a problem hiding this comment.
Goed punt. Ik stel voor de wijzigingen aan de helm-components in een aparte PR te doen en dit voor nu de gescaffolde components te laten.
| @@ -0,0 +1,36 @@ | |||
| import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core'; | |||
| import { NgIcon, provideIcons } from '@ng-icons/core'; | |||
| import { lucideEllipsis } from '@ng-icons/lucide'; | |||
There was a problem hiding this comment.
We zijn inmiddels geswitcht naar Phosphor voor icons, dus denk ik ook mooi om dat in de angular components door te voeren.
There was a problem hiding this comment.
Goed punt, ik had dat al gezien en heb al phosphor icons gebruikt in de Storybook story's. Ik stel voor de wijzigingen aan de helm-components in een aparte PR te doen en dit voor nu de gescaffolde components te laten.
The new helm components only consumed the contracts in their stories, so a contract change failed the React build but compiled fine on the Angular side, defeating the cross-framework parity guarantee. Wire each axis-bearing component to its contract the way hlm-button already does: avatar, select-trigger, and dropdown-menu-item type their input from the contract name; field and sidebar-menu-button add `satisfies Record<…>` on their cva variant maps so a stray or missing key fails `pnpm lint`.
There is no Angular data table yet and nothing imports the package. Remove it from package.json and from ng-package.json allowedNonPeerDependencies.
| }; | ||
|
|
||
| /** Category select prefix — a dropdown trigger on the leading side. */ | ||
| export const WithLeadingDropdown: Story = { |
There was a problem hiding this comment.
Deze story lijkt functioneel niet goed te werken of is onduidelijk. Je hebt een input met een dropdown er voor, maar als je iets selecteert uit de dropdown dan doet dat niks. Ik zou verwachten dat de gekozen optie dan getoond wordt in het input field of zo. Dit is nu het geval zowel in React als Angular.
The vendored components shipped spartan's default @ng-icons/lucide glyphs while the design system standardized on Phosphor (React migrated in PR #44) and only the stories used it. Swap every component-side icon to its Phosphor equivalent (matching React's choices, e.g. CaretUpDown on the select trigger), promote @ng-icons/phosphor-icons to a runtime dependency, and remove @ng-icons/lucide from package.json and ng-package.json.
The WithLeadingDropdown story (React and Angular) had a static "Category" trigger and dropdown items that did nothing when selected. Track the chosen category in state and reflect it in the trigger label and input placeholder so the example demonstrates real behavior.
Add react-storybook (6006) and angular-storybook (6007) entries so the component libraries can be launched for preview/verification.
…tton The leading dropdown trigger used hlmBtn, which isn't among the story's imported directives, so it matched nothing and rendered unstyled. Switch to hlmInputGroupButton (already imported via HlmInputGroupImports), matching React's InputGroupButton, so the ghost-variant button styling applies.
What
Adds the React & Angular component-library half of the PoC component inventory to
@surfnet/reactand@surfnet/angular, plus the supporting contracts.Primitives vendored
React: (shadcn CLI / Base UI, Phosphor icons) — each with its own directory, barrel,
src/index.tsexport, and a Storybook story:avatar,breadcrumb,checkbox,dropdown-menu,field,input,label,select,separator,sidebar,table. (buttonalready existed.)Angular, (spartan-ng CLI / brain, Phosphor icons) —each with its own directory,
src\libfile with component files and Storybook and asrc/index.tsexport, Same components as for React, but addittionally also these because the desired components depend on these: icon, sheet, skeleton, tooltip.DataTable
React — a reusable component built on the
tableprimitive + TanStack Table (@tanstack/react-table), matching the dedicated "Data Table" Figma spec: row selection, sortable columns, text filter, column-visibility menu, row actions, and Previous/Next pagination. All user-facing strings (Columns,No results.,Previous,Next, the selection summary, filter placeholder) are props with sensible defaults.Angular — no data table yet, this would take considerably more effort to custom implement.
Contracts — every new component gets a
<name>Contractin@surfnet/contractsas the cross-framework source of truth. Components with a real axis are tied to the contract (cvasatisfies Record<…>or typed inline-union props):avatarsize,dropdown-menuitem variant,fieldorientation,selecttrigger size,sidebarmenu-button variant/size. The rest are description-only.Skill — updated
add-component(SKILL.md,react.md,angular.md) to require a contract for every component and to document the three contract shapes (variant/size, orientation, description-only), closing the gap that previously left primitives without contracts.Why
These are the primitives needed to rebuild the two PoC screens (App catalog, Login).